From 40d85d54433eccff19b4434c7073f2a7b6127426 Mon Sep 17 00:00:00 2001 From: Milton Chandro Bhowmick Date: Wed, 28 Jul 2021 16:50:21 +0600 Subject: [PATCH 001/726] Modified the a_star [dot] py for making readable (#4576) --- graphs/a_star.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphs/a_star.py b/graphs/a_star.py index cb5b2fcd1..d3657cb19 100644 --- a/graphs/a_star.py +++ b/graphs/a_star.py @@ -44,7 +44,7 @@ def search(grid, init, goal, cost, heuristic): x = init[0] y = init[1] g = 0 - f = g + heuristic[init[0]][init[0]] + f = g + heuristic[x][y] # cost from starting cell to destination cell cell = [[f, g, x, y]] found = False # flag that is set when search is complete From a5bcf0f6749a93a44f7a981edc9b0e35fbd066f2 Mon Sep 17 00:00:00 2001 From: Hasanul Islam Date: Thu, 29 Jul 2021 19:14:35 +0600 Subject: [PATCH 002/726] Fix mypy errors at even_tree algo (#4579) --- graphs/even_tree.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/graphs/even_tree.py b/graphs/even_tree.py index c9aef6e78..92ffb4b23 100644 --- a/graphs/even_tree.py +++ b/graphs/even_tree.py @@ -16,12 +16,12 @@ components containing an even number of nodes. from collections import defaultdict -def dfs(start): +def dfs(start: int) -> int: """DFS traversal""" # pylint: disable=redefined-outer-name ret = 1 visited[start] = True - for v in tree.get(start): + for v in tree[start]: if v not in visited: ret += dfs(v) if ret % 2 == 0: @@ -48,8 +48,8 @@ def even_tree(): if __name__ == "__main__": n, m = 10, 9 tree = defaultdict(list) - visited = {} - cuts = [] + visited: dict[int, bool] = {} + cuts: list[int] = [] count = 0 edges = [(2, 1), (3, 1), (4, 3), (5, 2), (6, 1), (7, 2), (8, 6), (9, 8), (10, 8)] for u, v in edges: From da71184b04837d2bc934f9947b4c262da096f349 Mon Sep 17 00:00:00 2001 From: Hasanul Islam Date: Mon, 2 Aug 2021 18:40:48 +0600 Subject: [PATCH 003/726] Fix mypy errors at mst_kruskal (#4581) --- graphs/minimum_spanning_tree_kruskal.py | 15 +++++++-------- graphs/tests/test_min_spanning_tree_kruskal.py | 4 ++-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/graphs/minimum_spanning_tree_kruskal.py b/graphs/minimum_spanning_tree_kruskal.py index a51f97034..f21a87a7d 100644 --- a/graphs/minimum_spanning_tree_kruskal.py +++ b/graphs/minimum_spanning_tree_kruskal.py @@ -1,15 +1,14 @@ -from typing import List, Tuple - - -def kruskal(num_nodes: int, num_edges: int, edges: List[Tuple[int, int, int]]) -> int: +def kruskal( + num_nodes: int, edges: list[tuple[int, int, int]] +) -> list[tuple[int, int, int]]: """ - >>> kruskal(4, 3, [(0, 1, 3), (1, 2, 5), (2, 3, 1)]) + >>> kruskal(4, [(0, 1, 3), (1, 2, 5), (2, 3, 1)]) [(2, 3, 1), (0, 1, 3), (1, 2, 5)] - >>> kruskal(4, 5, [(0, 1, 3), (1, 2, 5), (2, 3, 1), (0, 2, 1), (0, 3, 2)]) + >>> kruskal(4, [(0, 1, 3), (1, 2, 5), (2, 3, 1), (0, 2, 1), (0, 3, 2)]) [(2, 3, 1), (0, 2, 1), (0, 1, 3)] - >>> kruskal(4, 6, [(0, 1, 3), (1, 2, 5), (2, 3, 1), (0, 2, 1), (0, 3, 2), + >>> kruskal(4, [(0, 1, 3), (1, 2, 5), (2, 3, 1), (0, 2, 1), (0, 3, 2), ... (2, 1, 1)]) [(2, 3, 1), (0, 2, 1), (2, 1, 1)] """ @@ -44,4 +43,4 @@ if __name__ == "__main__": # pragma: no cover node1, node2, cost = [int(x) for x in input().strip().split()] edges.append((node1, node2, cost)) - kruskal(num_nodes, num_edges, edges) + kruskal(num_nodes, edges) diff --git a/graphs/tests/test_min_spanning_tree_kruskal.py b/graphs/tests/test_min_spanning_tree_kruskal.py index 3a527aef3..d6df242ec 100644 --- a/graphs/tests/test_min_spanning_tree_kruskal.py +++ b/graphs/tests/test_min_spanning_tree_kruskal.py @@ -2,7 +2,7 @@ from graphs.minimum_spanning_tree_kruskal import kruskal def test_kruskal_successful_result(): - num_nodes, num_edges = 9, 14 + num_nodes = 9 edges = [ [0, 1, 4], [0, 7, 8], @@ -20,7 +20,7 @@ def test_kruskal_successful_result(): [1, 7, 11], ] - result = kruskal(num_nodes, num_edges, edges) + result = kruskal(num_nodes, edges) expected = [ [7, 6, 1], From 5957eabd3e0c92650dba0962779b8729d2875209 Mon Sep 17 00:00:00 2001 From: jonabtc <39396756+jonabtc@users.noreply.github.com> Date: Tue, 3 Aug 2021 01:03:22 -0500 Subject: [PATCH 004/726] Adding the double factorial algorithm (#4550) --- maths/double_factorial_recursive.py | 31 +++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 maths/double_factorial_recursive.py diff --git a/maths/double_factorial_recursive.py b/maths/double_factorial_recursive.py new file mode 100644 index 000000000..05c9b2968 --- /dev/null +++ b/maths/double_factorial_recursive.py @@ -0,0 +1,31 @@ +def double_factorial(n: int) -> int: + """ + Compute double factorial using recursive method. + Recursion can be costly for large numbers. + + To learn about the theory behind this algorithm: + https://en.wikipedia.org/wiki/Double_factorial + + >>> import math + >>> all(double_factorial(i) == math.prod(range(i, 0, -2)) for i in range(20)) + True + >>> double_factorial(0.1) + Traceback (most recent call last): + ... + ValueError: double_factorial() only accepts integral values + >>> double_factorial(-1) + Traceback (most recent call last): + ... + ValueError: double_factorial() not defined for negative values + """ + if not isinstance(n, int): + raise ValueError("double_factorial() only accepts integral values") + if n < 0: + raise ValueError("double_factorial() not defined for negative values") + return 1 if n <= 1 else n * double_factorial(n - 2) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From f432bc76a6a8851b8bd2f29a45761a4ec538561f Mon Sep 17 00:00:00 2001 From: SURYAPRATAP SINGH SURYAVANSHI <67123991+suryapratapsinghsuryavanshi@users.noreply.github.com> Date: Fri, 6 Aug 2021 15:45:42 +0530 Subject: [PATCH 005/726] add alternative_string_arrange method (#4595) * add alternative_string_arrange method * fix issue * fix one more issue * changed the variable name li to output_list --- strings/alternative_string_arrange.py | 31 +++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 strings/alternative_string_arrange.py diff --git a/strings/alternative_string_arrange.py b/strings/alternative_string_arrange.py new file mode 100644 index 000000000..d81ddd8a1 --- /dev/null +++ b/strings/alternative_string_arrange.py @@ -0,0 +1,31 @@ +def alternative_string_arrange(first_str: str, second_str: str) -> str: + """ + Return the alternative arrangements of the two strings. + :param first_str: + :param second_str: + :return: String + >>> alternative_string_arrange("ABCD", "XY") + 'AXBYCD' + >>> alternative_string_arrange("XY", "ABCD") + 'XAYBCD' + >>> alternative_string_arrange("AB", "XYZ") + 'AXBYZ' + >>> alternative_string_arrange("ABC", "") + 'ABC' + """ + first_str_length: int = len(first_str) + second_str_length: int = len(second_str) + abs_length: int = ( + first_str_length if first_str_length > second_str_length else second_str_length + ) + output_list: list = [] + for char_count in range(abs_length): + if char_count < first_str_length: + output_list.append(first_str[char_count]) + if char_count < second_str_length: + output_list.append(second_str[char_count]) + return "".join(output_list) + + +if __name__ == "__main__": + print(alternative_string_arrange("AB", "XYZ"), end=" ") From 63ac09eeae6805ae25a3f994cb18e5df254ba4b6 Mon Sep 17 00:00:00 2001 From: Shubham Ganar <67952129+shubhamsg199@users.noreply.github.com> Date: Sun, 8 Aug 2021 23:51:26 +0530 Subject: [PATCH 006/726] Created check_valid_ip_address.py (#4602) * Created check_valid_ip_address.py * fixed typos error Co-authored-by: root --- maths/check_valid_ip_address.py | 46 +++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 maths/check_valid_ip_address.py diff --git a/maths/check_valid_ip_address.py b/maths/check_valid_ip_address.py new file mode 100644 index 000000000..6e8d35ebc --- /dev/null +++ b/maths/check_valid_ip_address.py @@ -0,0 +1,46 @@ +""" +Checking valid Ip Address. +A valid IP address must be in the form of A.B.C.D, +where A,B,C and D are numbers from 0-254 +for example: 192.168.23.1, 172.254.254.254 are valid IP address + 192.168.255.0, 255.192.3.121 are Invalid IP address +""" + + +def check_valid_ip(ip: str) -> bool: + """ + print "Valid IP address" If IP is valid. + or + print "Invalid IP address" If IP is Invalid. + + >>> check_valid_ip("192.168.0.23") + True + + >>> check_valid_ip("192.255.15.8") + False + + >>> check_valid_ip("172.100.0.8") + True + + >>> check_valid_ip("254.255.0.255") + False + """ + ip1 = ip.replace(".", " ") + list1 = [int(i) for i in ip1.split() if i.isdigit()] + count = 0 + for i in list1: + if i > 254: + count += 1 + break + if count: + return False + return True + + +if __name__ == "__main__": + ip = input() + output = check_valid_ip(ip) + if output is True: + print(f"{ip} is a Valid IP address") + else: + print(f"{ip} is an Invalid IP address") From d668c172b07bf9f54d63dc295016a96ec782a541 Mon Sep 17 00:00:00 2001 From: Hasanul Islam Date: Thu, 12 Aug 2021 02:48:53 +0600 Subject: [PATCH 007/726] Refactor graph_initialization at basic_graph.py (#4601) --- graphs/basic_graphs.py | 93 +++++++++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 33 deletions(-) diff --git a/graphs/basic_graphs.py b/graphs/basic_graphs.py index 0f73d8d07..9cd6dd0f9 100644 --- a/graphs/basic_graphs.py +++ b/graphs/basic_graphs.py @@ -1,42 +1,69 @@ from collections import deque + +def _input(message): + return input(message).strip().split(" ") + + +def initialize_unweighted_directed_graph( + node_count: int, edge_count: int +) -> dict[int, list[int]]: + graph: dict[int, list[int]] = {} + for i in range(node_count): + graph[i + 1] = [] + + for e in range(edge_count): + x, y = [int(i) for i in _input(f"Edge {e + 1}: ")] + graph[x].append(y) + return graph + + +def initialize_unweighted_undirected_graph( + node_count: int, edge_count: int +) -> dict[int, list[int]]: + graph: dict[int, list[int]] = {} + for i in range(node_count): + graph[i + 1] = [] + + for e in range(edge_count): + x, y = [int(i) for i in _input(f"Edge {e + 1}: ")] + graph[x].append(y) + graph[y].append(x) + return graph + + +def initialize_weighted_undirected_graph( + node_count: int, edge_count: int +) -> dict[int, list[tuple[int, int]]]: + graph: dict[int, list[tuple[int, int]]] = {} + for i in range(node_count): + graph[i + 1] = [] + + for e in range(edge_count): + 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__": - # Accept No. of Nodes and edges - n, m = map(int, input().split(" ")) + n, m = [int(i) for i in _input("Number of nodes and edges: ")] - # Initialising Dictionary of edges - g = {} - for i in range(n): - g[i + 1] = [] + graph_choice = int( + _input( + "Press 1 or 2 or 3 \n" + "1. Unweighted directed \n" + "2. Unweighted undirected \n" + "3. Weighted undirected \n" + )[0] + ) - """ - ---------------------------------------------------------------------------- - Accepting edges of Unweighted Directed Graphs - ---------------------------------------------------------------------------- - """ - for _ in range(m): - x, y = map(int, input().strip().split(" ")) - g[x].append(y) + g = { + 1: initialize_unweighted_directed_graph, + 2: initialize_unweighted_undirected_graph, + 3: initialize_weighted_undirected_graph, + }[graph_choice](n, m) - """ - ---------------------------------------------------------------------------- - Accepting edges of Unweighted Undirected Graphs - ---------------------------------------------------------------------------- - """ - for _ in range(m): - x, y = map(int, input().strip().split(" ")) - g[x].append(y) - g[y].append(x) - - """ - ---------------------------------------------------------------------------- - Accepting edges of Weighted Undirected Graphs - ---------------------------------------------------------------------------- - """ - for _ in range(m): - x, y, r = map(int, input().strip().split(" ")) - g[x].append([y, r]) - g[y].append([x, r]) """ -------------------------------------------------------------------------------- From cd987372e4c3a9f87d65b757ab46a48527fc9fa9 Mon Sep 17 00:00:00 2001 From: Hasanul Islam Date: Fri, 13 Aug 2021 13:10:24 +0600 Subject: [PATCH 008/726] Fix multi heuristic astar algo (#4612) --- graphs/multi_heuristic_astar.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/graphs/multi_heuristic_astar.py b/graphs/multi_heuristic_astar.py index 77ca5760d..8607f51d8 100644 --- a/graphs/multi_heuristic_astar.py +++ b/graphs/multi_heuristic_astar.py @@ -2,6 +2,8 @@ import heapq import numpy as np +TPos = tuple[int, int] + class PriorityQueue: def __init__(self): @@ -53,24 +55,24 @@ class PriorityQueue: return (priority, item) -def consistent_heuristic(P, goal): +def consistent_heuristic(P: TPos, goal: TPos): # euclidean distance a = np.array(P) b = np.array(goal) return np.linalg.norm(a - b) -def heuristic_2(P, goal): +def heuristic_2(P: TPos, goal: TPos): # integer division by time variable return consistent_heuristic(P, goal) // t -def heuristic_1(P, goal): +def heuristic_1(P: TPos, goal: TPos): # manhattan distance return abs(P[0] - goal[0]) + abs(P[1] - goal[1]) -def key(start, i, goal, g_function): +def key(start: TPos, i: int, goal: TPos, g_function: dict[TPos, float]): ans = g_function[start] + W1 * heuristics[i](start, goal) return ans @@ -117,7 +119,7 @@ def do_something(back_pointer, goal, start): quit() -def valid(p): +def valid(p: TPos): if p[0] < 0 or p[0] > n - 1: return False if p[1] < 0 or p[1] > n - 1: @@ -215,7 +217,6 @@ blocks_blk = [ (18, 1), (19, 1), ] -blocks_no = [] blocks_all = make_common_ground() @@ -233,7 +234,7 @@ goal = (n - 1, n - 1) t = 1 -def multi_a_star(start, goal, n_heuristic): +def multi_a_star(start: TPos, goal: TPos, n_heuristic: int): g_function = {start: 0, goal: float("inf")} back_pointer = {start: -1, goal: -1} open_list = [] @@ -243,8 +244,8 @@ def multi_a_star(start, goal, n_heuristic): open_list.append(PriorityQueue()) open_list[i].put(start, key(start, i, goal, g_function)) - close_list_anchor = [] - close_list_inad = [] + close_list_anchor: list[int] = [] + close_list_inad: list[int] = [] while open_list[0].minkey() < float("inf"): for i in range(1, n_heuristic): # print(open_list[0].minkey(), open_list[i].minkey()) From 3c225247b843233a306a94907f862bece6e637dc Mon Sep 17 00:00:00 2001 From: Shubham Ganar <67952129+shubhamsg199@users.noreply.github.com> Date: Fri, 13 Aug 2021 12:40:52 +0530 Subject: [PATCH 009/726] [mypy] Fix type annotations for strings/naive_string_search.py (#4611) --- strings/naive_string_search.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/strings/naive_string_search.py b/strings/naive_string_search.py index f28950264..315990087 100644 --- a/strings/naive_string_search.py +++ b/strings/naive_string_search.py @@ -1,10 +1,8 @@ """ https://en.wikipedia.org/wiki/String-searching_algorithm#Na%C3%AFve_string_search - this algorithm tries to find the pattern from every position of the mainString if pattern is found from position i it add it to the answer and does the same for position i+1 - Complexity : O(n*m) n=length of main string m=length of pattern string @@ -39,4 +37,4 @@ def naive_pattern_search(s: str, pattern: str) -> list: if __name__ == "__main__": assert naive_pattern_search("ABCDEFG", "DE") == [3] - print(f"{naive_pattern_search('ABAAABCDBBABCDDEBCABC', 'ABC') = }") + print(naive_pattern_search("ABAAABCDBBABCDDEBCABC", "ABC")) From 032999f36ed6eef61752e6bc5e399020988b06bd Mon Sep 17 00:00:00 2001 From: Bonnie <58572137+bonbon99@users.noreply.github.com> Date: Sun, 15 Aug 2021 01:43:05 -0400 Subject: [PATCH 010/726] Create exchange_sort.py (#4600) * Create exchange_sort.py added exchange sort * Fixed doctest in exchange_sort.py * Fixed formatting error and added new length variable added empty line at end of exchange_sort.py and turned len(numbers) into a variable * Fixed formatting errors with black added empty line --- sorts/exchange_sort.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 sorts/exchange_sort.py diff --git a/sorts/exchange_sort.py b/sorts/exchange_sort.py new file mode 100644 index 000000000..1ce78a9dc --- /dev/null +++ b/sorts/exchange_sort.py @@ -0,0 +1,27 @@ +def exchange_sort(numbers: list[int]) -> list[int]: + """ + Uses exchange sort to sort a list of numbers. + Source: https://en.wikipedia.org/wiki/Sorting_algorithm#Exchange_sort + >>> exchange_sort([5, 4, 3, 2, 1]) + [1, 2, 3, 4, 5] + >>> exchange_sort([-1, -2, -3]) + [-3, -2, -1] + >>> exchange_sort([1, 2, 3, 4, 5]) + [1, 2, 3, 4, 5] + >>> exchange_sort([0, 10, -2, 5, 3]) + [-2, 0, 3, 5, 10] + >>> exchange_sort([]) + [] + """ + numbers_length = len(numbers) + for i in range(numbers_length): + for j in range(i + 1, numbers_length): + if numbers[j] < numbers[i]: + numbers[i], numbers[j] = numbers[j], numbers[i] + return numbers + + +if __name__ == "__main__": + user_input = input("Enter numbers separated by a comma:\n").strip() + unsorted = [int(item) for item in user_input.split(",")] + print(exchange_sort(unsorted)) From d009cea391414bfef17520ba6b64e4c2d97163ed Mon Sep 17 00:00:00 2001 From: imp Date: Mon, 16 Aug 2021 03:15:53 +0800 Subject: [PATCH 011/726] Fix mypy error at maths (#4613) * Fix mypy errors for maths/greedy_coin_change.py * Fix mypy errors for maths/two_sum.py * Fix mypy errors for maths/triplet_sum.py * Fix the format of maths/greedy_coin_change.py * Fix the format of maths/greedy_coin_change.py * Fix format with pre-commit --- maths/greedy_coin_change.py | 4 ++-- maths/triplet_sum.py | 2 +- maths/two_sum.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/maths/greedy_coin_change.py b/maths/greedy_coin_change.py index 5a7d9e8d8..5233ee1cb 100644 --- a/maths/greedy_coin_change.py +++ b/maths/greedy_coin_change.py @@ -41,7 +41,7 @@ Following is minimal change for 456 : """ -def find_minimum_change(denominations: list[int], value: int) -> list[int]: +def find_minimum_change(denominations: list[int], value: str) -> list[int]: """ Find the minimum change from the given denominations and value >>> find_minimum_change([1, 5, 10, 20, 50, 100, 200, 500, 1000,2000], 18745) @@ -75,7 +75,7 @@ def find_minimum_change(denominations: list[int], value: int) -> list[int]: if __name__ == "__main__": denominations = list() - value = 0 + value = "0" if ( input("Do you want to enter your denominations ? (yY/n): ").strip().lower() diff --git a/maths/triplet_sum.py b/maths/triplet_sum.py index 22fab17d3..af77ed145 100644 --- a/maths/triplet_sum.py +++ b/maths/triplet_sum.py @@ -19,7 +19,7 @@ def make_dataset() -> tuple[list[int], int]: dataset = make_dataset() -def triplet_sum1(arr: list[int], target: int) -> tuple[int, int, int]: +def triplet_sum1(arr: list[int], target: int) -> tuple[int, ...]: """ Returns a triplet in the array with sum equal to target, else (0, 0, 0). diff --git a/maths/two_sum.py b/maths/two_sum.py index 5209acbc7..12ad332d6 100644 --- a/maths/two_sum.py +++ b/maths/two_sum.py @@ -31,7 +31,7 @@ def two_sum(nums: list[int], target: int) -> list[int]: >>> two_sum([3 * i for i in range(10)], 19) [] """ - chk_map = {} + chk_map: dict[int, int] = {} for index, val in enumerate(nums): compl = target - val if compl in chk_map: From 4545270ace03411ec861361329345a36195b881d Mon Sep 17 00:00:00 2001 From: imp Date: Wed, 18 Aug 2021 18:44:26 +0800 Subject: [PATCH 012/726] [mypy] Fix type annotations for graphs (#4622) * Fix mypy error for frequent_pattern_graph_miner.py * Fix mypy error for markov_chain.py --- graphs/frequent_pattern_graph_miner.py | 2 +- graphs/markov_chain.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/graphs/frequent_pattern_graph_miner.py b/graphs/frequent_pattern_graph_miner.py index ff7063082..8f344b7bd 100644 --- a/graphs/frequent_pattern_graph_miner.py +++ b/graphs/frequent_pattern_graph_miner.py @@ -227,6 +227,6 @@ if __name__ == "__main__": support = get_support(cluster) graph = construct_graph(cluster, nodes) find_freq_subgraph_given_support(60, cluster, graph) - paths = [] + paths: list = [] freq_subgraph_edge_list = freq_subgraphs_edge_list(paths) print_all() diff --git a/graphs/markov_chain.py b/graphs/markov_chain.py index b93c408cd..0b6659822 100644 --- a/graphs/markov_chain.py +++ b/graphs/markov_chain.py @@ -35,6 +35,7 @@ class MarkovChainGraphUndirectedUnweighted: current_probability += self.connections[node][dest] if current_probability > random_value: return dest + return "" def get_transitions( From af0810fca133dde19b39fc7735572b6989ea269b Mon Sep 17 00:00:00 2001 From: imp Date: Wed, 18 Aug 2021 18:45:07 +0800 Subject: [PATCH 013/726] [mypy] Fix type annotations for maths (#4617) * Fix mypy errors for armstrong_numbers.py * Fix mypy errors for harmonic_series.py * Fix mypy errors for average_median.py --- maths/armstrong_numbers.py | 2 +- maths/average_median.py | 4 ++-- maths/series/harmonic_series.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/maths/armstrong_numbers.py b/maths/armstrong_numbers.py index ce8c62182..4e62737e1 100644 --- a/maths/armstrong_numbers.py +++ b/maths/armstrong_numbers.py @@ -9,7 +9,7 @@ Armstrong numbers are also called Narcissistic numbers and Pluperfect numbers. On-Line Encyclopedia of Integer Sequences entry: https://oeis.org/A005188 """ PASSING = (1, 153, 370, 371, 1634, 24678051, 115132219018763992565095597973971522401) -FAILING = (-153, -1, 0, 1.2, 200, "A", [], {}, None) +FAILING: tuple = (-153, -1, 0, 1.2, 200, "A", [], {}, None) def armstrong_number(n: int) -> bool: diff --git a/maths/average_median.py b/maths/average_median.py index 57e01368b..497bf0c3a 100644 --- a/maths/average_median.py +++ b/maths/average_median.py @@ -1,14 +1,14 @@ from typing import Union -def median(nums: Union[int, float]) -> Union[int, float]: +def median(nums: list) -> Union[int, float]: """ Find median of a list of numbers. Wiki: https://en.wikipedia.org/wiki/Median >>> median([0]) 0 - >>> median([4,1,3,2]) + >>> median([4, 1, 3, 2]) 2.5 >>> median([2, 70, 6, 50, 20, 8, 4]) 8 diff --git a/maths/series/harmonic_series.py b/maths/series/harmonic_series.py index 91b594458..d42d13d91 100644 --- a/maths/series/harmonic_series.py +++ b/maths/series/harmonic_series.py @@ -33,8 +33,8 @@ def harmonic_series(n_term: str) -> list: ['1'] """ if n_term == "": - return n_term - series = [] + return [] + series: list = [] for temp in range(int(n_term)): series.append(f"1/{temp + 1}" if series else "1") return series From 9cb5760e895179f8aaa97dd577442189064c724d Mon Sep 17 00:00:00 2001 From: SURYAPRATAP SINGH SURYAVANSHI <67123991+suryapratapsinghsuryavanshi@users.noreply.github.com> Date: Wed, 18 Aug 2021 17:35:41 +0530 Subject: [PATCH 014/726] add date_to_weekday finder method (#4599) * add date_to_weekday finder method * reformat date_to_weekday method * remove time * remove hardcode weekdays list * fix return type error * fixing fail issue * Finding the test failing issue * after testing the pre-commit in local environment --- other/date_to_weekday.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 other/date_to_weekday.py diff --git a/other/date_to_weekday.py b/other/date_to_weekday.py new file mode 100644 index 000000000..bb17130c0 --- /dev/null +++ b/other/date_to_weekday.py @@ -0,0 +1,27 @@ +from calendar import day_name +from datetime import datetime + + +def date_to_weekday(inp_date: str) -> str: + """ + It returns the day name of the given date string. + :param inp_date: + :return: String + >>> date_to_weekday("7/8/2035") + 'Tuesday' + >>> date_to_weekday("7/8/2021") + 'Saturday' + >>> date_to_weekday("1/1/2021") + 'Friday' + """ + 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" + date_time_obj: datetime.date = datetime.strptime(new_base_date, "%d/%m/%y %H:%M:%S") + out_put_day: int = date_time_obj.weekday() + return day_name[out_put_day] + + +if __name__ == "__main__": + print(date_to_weekday("1/1/2021"), end=" ") From 20a4fdf38465c2731100c3fbd1aac847cd0b9322 Mon Sep 17 00:00:00 2001 From: imp Date: Thu, 19 Aug 2021 20:08:20 +0800 Subject: [PATCH 015/726] [mypy] Fix type annotations for strings (#4637) * Fix mypy error for can_string_be_rearranged_as_pal * Fix mypy error for levenshtein_distance.py * Fix mypy error for word_patterns.py * Fix mypy error for word_occurrence.py --- strings/can_string_be_rearranged_as_palindrome.py | 2 +- strings/levenshtein_distance.py | 2 +- strings/word_occurrence.py | 2 +- strings/word_patterns.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/strings/can_string_be_rearranged_as_palindrome.py b/strings/can_string_be_rearranged_as_palindrome.py index 7fedc5877..ddc4828c7 100644 --- a/strings/can_string_be_rearranged_as_palindrome.py +++ b/strings/can_string_be_rearranged_as_palindrome.py @@ -43,7 +43,7 @@ def can_string_be_rearranged_as_palindrome(input_str: str = "") -> bool: return True lower_case_input_str = input_str.replace(" ", "").lower() # character_freq_dict: Stores the frequency of every character in the input string - character_freq_dict = {} + character_freq_dict: dict[str, int] = {} for character in lower_case_input_str: character_freq_dict[character] = character_freq_dict.get(character, 0) + 1 diff --git a/strings/levenshtein_distance.py b/strings/levenshtein_distance.py index 540a21c93..9f7a7e3e6 100644 --- a/strings/levenshtein_distance.py +++ b/strings/levenshtein_distance.py @@ -41,7 +41,7 @@ def levenshtein_distance(first_word: str, second_word: str) -> int: if len(second_word) == 0: return len(first_word) - previous_row = range(len(second_word) + 1) + previous_row = list(range(len(second_word) + 1)) for i, c1 in enumerate(first_word): diff --git a/strings/word_occurrence.py b/strings/word_occurrence.py index ef612e12d..4acfa41ad 100644 --- a/strings/word_occurrence.py +++ b/strings/word_occurrence.py @@ -14,7 +14,7 @@ def word_occurence(sentence: str) -> dict: >>> dict(word_occurence("Two spaces")) {'Two': 1, 'spaces': 1} """ - occurrence = defaultdict(int) + occurrence: dict = defaultdict(int) # Creating a dictionary containing count of each word for word in sentence.split(): occurrence[word] += 1 diff --git a/strings/word_patterns.py b/strings/word_patterns.py index d229954de..90b092a20 100644 --- a/strings/word_patterns.py +++ b/strings/word_patterns.py @@ -28,7 +28,7 @@ if __name__ == "__main__": with open("dictionary.txt") as in_file: wordList = in_file.read().splitlines() - all_patterns = {} + all_patterns: dict = {} for word in wordList: pattern = get_word_pattern(word) if pattern in all_patterns: From 4ed7c7f09c74c358f9c31d7a13a29285264bd261 Mon Sep 17 00:00:00 2001 From: Shiva Rama Krishna <45482631+srkchowdary2000@users.noreply.github.com> Date: Mon, 23 Aug 2021 16:05:20 +0530 Subject: [PATCH 016/726] =?UTF-8?q?Added=20Bor=C5=AFvka's=20algorithm.=20(?= =?UTF-8?q?#4645)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added Borůvka's algorithm. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. Solved Test Cases Errors. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. Solved Test Cases Errors. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. Solved Test Cases Errors. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. Solved Test Cases Errors. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. Solved Test Cases Errors. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. Solved Test Cases Errors. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. Solved Test Cases Errors.Removed WhiteSpaces. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. Code Changes. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. Code Changes. --- graphs/boruvka.py | 198 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 graphs/boruvka.py diff --git a/graphs/boruvka.py b/graphs/boruvka.py new file mode 100644 index 000000000..b95bcc398 --- /dev/null +++ b/graphs/boruvka.py @@ -0,0 +1,198 @@ +"""Borůvka's algorithm. + + Determines the minimum spanning tree(MST) of a graph using the Borůvka's algorithm. + Borůvka's algorithm is a greedy algorithm for finding a minimum spanning tree in a + graph,or a minimum spanning forest in the case of a graph that is not connected. + + The time complexity of this algorithm is O(ELogV), where E represents the number + of edges, while V represents the number of nodes. + + The space complexity of this algorithm is O(V + E), since we have to keep a couple + of lists whose sizes are equal to the number of nodes, as well as keep all the + edges of a graph inside of the data structure itself. + + Borůvka's algorithm gives us pretty much the same result as other MST Algorithms - + they all find the minimum spanning tree, and the time complexity is approximately + the same. + + One advantage that Borůvka's algorithm has compared to the alternatives is that it + doesn't need to presort the edges or maintain a priority queue in order to find the + minimum spanning tree. + Even though that doesn't help its complexity, since it still passes the edges logE + times, it is a bit more simple to code. + + Details: https://en.wikipedia.org/wiki/Bor%C5%AFvka%27s_algorithm +""" + + +class Graph: + def __init__(self, num_of_nodes: int) -> None: + """ + Arguments: + num_of_nodes - the number of nodes in the graph + Attributes: + m_v - the number of nodes in the graph. + m_edges - the list of edges. + m_component - the dictionary which stores the index of the component which + a node belongs to. + """ + + self.m_v = num_of_nodes + self.m_edges = [] + self.m_component = {} + + def add_edge(self, u_node: int, v_node: int, weight: int) -> None: + """Adds an edge in the format [first, second, edge weight] to graph.""" + + self.m_edges.append([u_node, v_node, weight]) + + def find_component(self, u_node: int) -> int: + """Propagates a new component throughout a given component.""" + + if self.m_component[u_node] == u_node: + return u_node + return self.find_component(self.m_component[u_node]) + + def set_component(self, u_node: int) -> None: + """Finds the component index of a given node""" + + if self.m_component[u_node] != u_node: + for k in self.m_component.keys(): + self.m_component[k] = self.find_component(k) + + def union(self, component_size: list, u_node: int, v_node: int) -> None: + """Union finds the roots of components for two nodes, compares the components + in terms of size, and attaches the smaller one to the larger one to form + single component""" + + if component_size[u_node] <= component_size[v_node]: + self.m_component[u_node] = v_node + component_size[v_node] += component_size[u_node] + self.set_component(u_node) + + elif component_size[u_node] >= component_size[v_node]: + self.m_component[v_node] = self.find_component(u_node) + component_size[u_node] += component_size[v_node] + self.set_component(v_node) + + def boruvka(self) -> None: + """Performs Borůvka's algorithm to find MST.""" + + # Initialize additional lists required to algorithm. + component_size = [] + mst_weight = 0 + + minimum_weight_edge = [-1] * self.m_v + + # A list of components (initialized to all of the nodes) + for node in range(self.m_v): + self.m_component.update({node: node}) + component_size.append(1) + + num_of_components = self.m_v + + while num_of_components > 1: + l_edges = len(self.m_edges) + for i in range(l_edges): + + u = self.m_edges[i][0] + v = self.m_edges[i][1] + w = self.m_edges[i][2] + + u_component = self.m_component[u] + v_component = self.m_component[v] + + if u_component != v_component: + """If the current minimum weight edge of component u doesn't + exist (is -1), or if it's greater than the edge we're + observing right now, we will assign the value of the edge + we're observing to it. + + If the current minimum weight edge of component v doesn't + exist (is -1), or if it's greater than the edge we're + observing right now, we will assign the value of the edge + we're observing to it""" + + if ( + minimum_weight_edge[u_component] == -1 + or minimum_weight_edge[u_component][2] > w + ): + minimum_weight_edge[u_component] = [u, v, w] + if ( + minimum_weight_edge[v_component] == -1 + or minimum_weight_edge[v_component][2] > w + ): + minimum_weight_edge[v_component] = [u, v, w] + + for node in range(self.m_v): + if minimum_weight_edge[node] != -1: + u = minimum_weight_edge[node][0] + v = minimum_weight_edge[node][1] + w = minimum_weight_edge[node][2] + + u_component = self.m_component[u] + v_component = self.m_component[v] + + if u_component != v_component: + mst_weight += w + self.union(component_size, u_component, v_component) + print( + "Added edge [" + + str(u) + + " - " + + str(v) + + "]\n" + + "Added weight: " + + str(w) + + "\n" + ) + num_of_components -= 1 + + minimum_weight_edge = [-1] * self.m_v + print("The total weight of the minimal spanning tree is: " + str(mst_weight)) + + +def test_vector() -> None: + """ + >>> g=Graph(8) + >>> g.add_edge(0, 1, 10) + >>> g.add_edge(0, 2, 6) + >>> g.add_edge(0, 3, 5) + >>> g.add_edge(1, 3, 15) + >>> g.add_edge(2, 3, 4) + >>> g.add_edge(3, 4, 8) + >>> g.add_edge(4, 5, 10) + >>> g.add_edge(4, 6, 6) + >>> g.add_edge(4, 7, 5) + >>> g.add_edge(5, 7, 15) + >>> g.add_edge(6, 7, 4) + >>> g.boruvka() + Added edge [0 - 3] + Added weight: 5 + + Added edge [0 - 1] + Added weight: 10 + + Added edge [2 - 3] + Added weight: 4 + + Added edge [4 - 7] + Added weight: 5 + + Added edge [4 - 5] + Added weight: 10 + + Added edge [6 - 7] + Added weight: 4 + + Added edge [3 - 4] + Added weight: 8 + + The total weight of the minimal spanning tree is: 46 + """ + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 78a5d3a5587ef649c2b4d2286cfb949886095467 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 24 Aug 2021 15:27:31 +0200 Subject: [PATCH 017/726] boruvka.py: A few simplifications and f-strings (#4660) * boruvka.py: A few simplifications and f-strings Python f-strings simplify the code and [should speed up execution](https://www.scivision.dev/python-f-string-speed). @srkchowdary2000 Your review, please. * updating DIRECTORY.md * fixup! Streamline the test Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 10 ++++++ graphs/boruvka.py | 82 ++++++++++++++++------------------------------- 2 files changed, 38 insertions(+), 54 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index adc9bb9e4..41485f6f0 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -97,6 +97,7 @@ * [Peak Signal To Noise Ratio](https://github.com/TheAlgorithms/Python/blob/master/compression/peak_signal_to_noise_ratio.py) ## Computer Vision + * [Cnn Classification](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/cnn_classification.py) * [Harris Corner](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/harris_corner.py) * [Mean Threshold](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/mean_threshold.py) @@ -300,6 +301,7 @@ * [Bfs Zero One Shortest Path](https://github.com/TheAlgorithms/Python/blob/master/graphs/bfs_zero_one_shortest_path.py) * [Bidirectional A Star](https://github.com/TheAlgorithms/Python/blob/master/graphs/bidirectional_a_star.py) * [Bidirectional Breadth First Search](https://github.com/TheAlgorithms/Python/blob/master/graphs/bidirectional_breadth_first_search.py) + * [Boruvka](https://github.com/TheAlgorithms/Python/blob/master/graphs/boruvka.py) * [Breadth First Search](https://github.com/TheAlgorithms/Python/blob/master/graphs/breadth_first_search.py) * [Breadth First Search 2](https://github.com/TheAlgorithms/Python/blob/master/graphs/breadth_first_search_2.py) * [Breadth First Search Shortest Path](https://github.com/TheAlgorithms/Python/blob/master/graphs/breadth_first_search_shortest_path.py) @@ -349,6 +351,7 @@ * [Djb2](https://github.com/TheAlgorithms/Python/blob/master/hashes/djb2.py) * [Enigma Machine](https://github.com/TheAlgorithms/Python/blob/master/hashes/enigma_machine.py) * [Hamming Code](https://github.com/TheAlgorithms/Python/blob/master/hashes/hamming_code.py) + * [Luhn](https://github.com/TheAlgorithms/Python/blob/master/hashes/luhn.py) * [Md5](https://github.com/TheAlgorithms/Python/blob/master/hashes/md5.py) * [Sdbm](https://github.com/TheAlgorithms/Python/blob/master/hashes/sdbm.py) * [Sha1](https://github.com/TheAlgorithms/Python/blob/master/hashes/sha1.py) @@ -421,10 +424,12 @@ * [Binomial Distribution](https://github.com/TheAlgorithms/Python/blob/master/maths/binomial_distribution.py) * [Bisection](https://github.com/TheAlgorithms/Python/blob/master/maths/bisection.py) * [Ceil](https://github.com/TheAlgorithms/Python/blob/master/maths/ceil.py) + * [Check Valid Ip Address](https://github.com/TheAlgorithms/Python/blob/master/maths/check_valid_ip_address.py) * [Chudnovsky Algorithm](https://github.com/TheAlgorithms/Python/blob/master/maths/chudnovsky_algorithm.py) * [Collatz Sequence](https://github.com/TheAlgorithms/Python/blob/master/maths/collatz_sequence.py) * [Combinations](https://github.com/TheAlgorithms/Python/blob/master/maths/combinations.py) * [Decimal Isolate](https://github.com/TheAlgorithms/Python/blob/master/maths/decimal_isolate.py) + * [Double Factorial Recursive](https://github.com/TheAlgorithms/Python/blob/master/maths/double_factorial_recursive.py) * [Entropy](https://github.com/TheAlgorithms/Python/blob/master/maths/entropy.py) * [Euclidean Distance](https://github.com/TheAlgorithms/Python/blob/master/maths/euclidean_distance.py) * [Euclidean Gcd](https://github.com/TheAlgorithms/Python/blob/master/maths/euclidean_gcd.py) @@ -539,6 +544,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) * [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) @@ -854,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) + * [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) * [Heap Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/heap_sort.py) @@ -893,6 +900,7 @@ ## Strings * [Aho Corasick](https://github.com/TheAlgorithms/Python/blob/master/strings/aho_corasick.py) + * [Alternative String Arrange](https://github.com/TheAlgorithms/Python/blob/master/strings/alternative_string_arrange.py) * [Anagrams](https://github.com/TheAlgorithms/Python/blob/master/strings/anagrams.py) * [Autocomplete Using Trie](https://github.com/TheAlgorithms/Python/blob/master/strings/autocomplete_using_trie.py) * [Boyer Moore Search](https://github.com/TheAlgorithms/Python/blob/master/strings/boyer_moore_search.py) @@ -902,6 +910,7 @@ * [Check Pangram](https://github.com/TheAlgorithms/Python/blob/master/strings/check_pangram.py) * [Detecting English Programmatically](https://github.com/TheAlgorithms/Python/blob/master/strings/detecting_english_programmatically.py) * [Frequency Finder](https://github.com/TheAlgorithms/Python/blob/master/strings/frequency_finder.py) + * [Indian Phone Validator](https://github.com/TheAlgorithms/Python/blob/master/strings/indian_phone_validator.py) * [Is Palindrome](https://github.com/TheAlgorithms/Python/blob/master/strings/is_palindrome.py) * [Jaro Winkler](https://github.com/TheAlgorithms/Python/blob/master/strings/jaro_winkler.py) * [Knuth Morris Pratt](https://github.com/TheAlgorithms/Python/blob/master/strings/knuth_morris_pratt.py) @@ -941,6 +950,7 @@ * [Instagram Crawler](https://github.com/TheAlgorithms/Python/blob/master/web_programming/instagram_crawler.py) * [Instagram Pic](https://github.com/TheAlgorithms/Python/blob/master/web_programming/instagram_pic.py) * [Instagram Video](https://github.com/TheAlgorithms/Python/blob/master/web_programming/instagram_video.py) + * [Random Anime Character](https://github.com/TheAlgorithms/Python/blob/master/web_programming/random_anime_character.py) * [Recaptcha Verification](https://github.com/TheAlgorithms/Python/blob/master/web_programming/recaptcha_verification.py) * [Slack Message](https://github.com/TheAlgorithms/Python/blob/master/web_programming/slack_message.py) * [Test Fetch Github Info](https://github.com/TheAlgorithms/Python/blob/master/web_programming/test_fetch_github_info.py) diff --git a/graphs/boruvka.py b/graphs/boruvka.py index b95bcc398..3fa5c6fd2 100644 --- a/graphs/boruvka.py +++ b/graphs/boruvka.py @@ -1,11 +1,12 @@ """Borůvka's algorithm. - Determines the minimum spanning tree(MST) of a graph using the Borůvka's algorithm. + Determines the minimum spanning tree (MST) of a graph using the Borůvka's algorithm. Borůvka's algorithm is a greedy algorithm for finding a minimum spanning tree in a - graph,or a minimum spanning forest in the case of a graph that is not connected. + connected graph, or a minimum spanning forest if a graph that is not connected. The time complexity of this algorithm is O(ELogV), where E represents the number of edges, while V represents the number of nodes. + O(number_of_edges Log number_of_nodes) The space complexity of this algorithm is O(V + E), since we have to keep a couple of lists whose sizes are equal to the number of nodes, as well as keep all the @@ -19,7 +20,7 @@ doesn't need to presort the edges or maintain a priority queue in order to find the minimum spanning tree. Even though that doesn't help its complexity, since it still passes the edges logE - times, it is a bit more simple to code. + times, it is a bit simpler to code. Details: https://en.wikipedia.org/wiki/Bor%C5%AFvka%27s_algorithm """ @@ -31,13 +32,13 @@ class Graph: Arguments: num_of_nodes - the number of nodes in the graph Attributes: - m_v - the number of nodes in the graph. + m_num_of_nodes - the number of nodes in the graph. m_edges - the list of edges. m_component - the dictionary which stores the index of the component which a node belongs to. """ - self.m_v = num_of_nodes + self.m_num_of_nodes = num_of_nodes self.m_edges = [] self.m_component = {} @@ -57,7 +58,7 @@ class Graph: """Finds the component index of a given node""" if self.m_component[u_node] != u_node: - for k in self.m_component.keys(): + for k in self.m_component: self.m_component[k] = self.find_component(k) def union(self, component_size: list, u_node: int, v_node: int) -> None: @@ -82,22 +83,18 @@ class Graph: component_size = [] mst_weight = 0 - minimum_weight_edge = [-1] * self.m_v + minimum_weight_edge = [-1] * self.m_num_of_nodes # A list of components (initialized to all of the nodes) - for node in range(self.m_v): + for node in range(self.m_num_of_nodes): self.m_component.update({node: node}) component_size.append(1) - num_of_components = self.m_v + num_of_components = self.m_num_of_nodes while num_of_components > 1: - l_edges = len(self.m_edges) - for i in range(l_edges): - - u = self.m_edges[i][0] - v = self.m_edges[i][1] - w = self.m_edges[i][2] + for edge in self.m_edges: + u, v, w = edge u_component = self.m_component[u] v_component = self.m_component[v] @@ -113,22 +110,16 @@ class Graph: observing right now, we will assign the value of the edge we're observing to it""" - if ( - minimum_weight_edge[u_component] == -1 - or minimum_weight_edge[u_component][2] > w - ): - minimum_weight_edge[u_component] = [u, v, w] - if ( - minimum_weight_edge[v_component] == -1 - or minimum_weight_edge[v_component][2] > w - ): - minimum_weight_edge[v_component] = [u, v, w] + for component in (u_component, v_component): + if ( + minimum_weight_edge[component] == -1 + or minimum_weight_edge[component][2] > w + ): + minimum_weight_edge[component] = [u, v, w] - for node in range(self.m_v): - if minimum_weight_edge[node] != -1: - u = minimum_weight_edge[node][0] - v = minimum_weight_edge[node][1] - w = minimum_weight_edge[node][2] + for edge in minimum_weight_edge: + if edge != -1: + u, v, w = edge u_component = self.m_component[u] v_component = self.m_component[v] @@ -136,36 +127,19 @@ class Graph: if u_component != v_component: mst_weight += w self.union(component_size, u_component, v_component) - print( - "Added edge [" - + str(u) - + " - " - + str(v) - + "]\n" - + "Added weight: " - + str(w) - + "\n" - ) + print(f"Added edge [{u} - {v}]\nAdded weight: {w}\n") num_of_components -= 1 - minimum_weight_edge = [-1] * self.m_v - print("The total weight of the minimal spanning tree is: " + str(mst_weight)) + minimum_weight_edge = [-1] * self.m_num_of_nodes + print(f"The total weight of the minimal spanning tree is: {mst_weight}") def test_vector() -> None: """ - >>> g=Graph(8) - >>> g.add_edge(0, 1, 10) - >>> g.add_edge(0, 2, 6) - >>> g.add_edge(0, 3, 5) - >>> g.add_edge(1, 3, 15) - >>> g.add_edge(2, 3, 4) - >>> g.add_edge(3, 4, 8) - >>> g.add_edge(4, 5, 10) - >>> g.add_edge(4, 6, 6) - >>> g.add_edge(4, 7, 5) - >>> g.add_edge(5, 7, 15) - >>> g.add_edge(6, 7, 4) + >>> g = Graph(8) + >>> for u_v_w in ((0, 1, 10), (0, 2, 6), (0, 3, 5), (1, 3, 15), (2, 3, 4), + ... (3, 4, 8), (4, 5, 10), (4, 6, 6), (4, 7, 5), (5, 7, 15), (6, 7, 4)): + ... g.add_edge(*u_v_w) >>> g.boruvka() Added edge [0 - 3] Added weight: 5 From 5e7eed610ce81fa96e033f4d2a1781ed8637cb41 Mon Sep 17 00:00:00 2001 From: imp Date: Wed, 25 Aug 2021 19:35:36 +0800 Subject: [PATCH 018/726] [mypy] Fix type annotations for strings (#4641) * Fix mypy error for min_cost_string_conversion.py * Fix mypy error for manacher.py * Fix mypy error for aho_corasick.py --- strings/aho_corasick.py | 22 +++++++++++++--------- strings/manacher.py | 25 +++++++++++++------------ strings/min_cost_string_conversion.py | 8 +++----- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/strings/aho_corasick.py b/strings/aho_corasick.py index b959dbd58..712cb338a 100644 --- a/strings/aho_corasick.py +++ b/strings/aho_corasick.py @@ -3,8 +3,8 @@ from typing import Dict, List, Union class Automaton: - def __init__(self, keywords: List[str]): - self.adlist = list() + def __init__(self, keywords: list[str]): + self.adlist: list[dict] = list() self.adlist.append( {"value": "", "next_states": [], "fail_state": 0, "output": []} ) @@ -22,9 +22,8 @@ class Automaton: def add_keyword(self, keyword: str) -> None: current_state = 0 for character in keyword: - if self.find_next_state(current_state, character): - current_state = self.find_next_state(current_state, character) - else: + next_state = self.find_next_state(current_state, character) + if next_state is None: self.adlist.append( { "value": character, @@ -35,10 +34,12 @@ class Automaton: ) self.adlist[current_state]["next_states"].append(len(self.adlist) - 1) current_state = len(self.adlist) - 1 + else: + current_state = next_state self.adlist[current_state]["output"].append(keyword) def set_fail_transitions(self) -> None: - q = deque() + q: deque = deque() for node in self.adlist[0]["next_states"]: q.append(node) self.adlist[node]["fail_state"] = 0 @@ -68,7 +69,9 @@ class Automaton: >>> A.search_in("whatever, err ... , wherever") {'what': [0], 'hat': [1], 'ver': [5, 25], 'er': [6, 10, 22, 26]} """ - result = dict() # returns a dict with keywords and list of its occurrences + result: dict = ( + dict() + ) # returns a dict with keywords and list of its occurrences current_state = 0 for i in range(len(string)): while ( @@ -76,10 +79,11 @@ class Automaton: and current_state != 0 ): current_state = self.adlist[current_state]["fail_state"] - current_state = self.find_next_state(current_state, string[i]) - if current_state is None: + next_state = self.find_next_state(current_state, string[i]) + if next_state is None: current_state = 0 else: + current_state = next_state for key in self.adlist[current_state]["output"]: if not (key in result): result[key] = [] diff --git a/strings/manacher.py b/strings/manacher.py index 5476e0683..e6ea71cde 100644 --- a/strings/manacher.py +++ b/strings/manacher.py @@ -35,27 +35,28 @@ def palindromic_string(input_string: str) -> str: length = [1 for i in range(len(new_input_string))] # for each character in new_string find corresponding palindromic string - for i in range(len(new_input_string)): - k = 1 if i > r else min(length[l + r - i] // 2, r - i + 1) + start = 0 + for j in range(len(new_input_string)): + k = 1 if j > r else min(length[l + r - j] // 2, r - j + 1) while ( - i - k >= 0 - and i + k < len(new_input_string) - and new_input_string[k + i] == new_input_string[i - k] + j - k >= 0 + and j + k < len(new_input_string) + and new_input_string[k + j] == new_input_string[j - k] ): k += 1 - length[i] = 2 * k - 1 + length[j] = 2 * k - 1 # does this string is ending after the previously explored end (that is r) ? # if yes the update the new r to the last index of this - if i + k - 1 > r: - l = i - k + 1 # noqa: E741 - r = i + k - 1 + if j + k - 1 > r: + l = j - k + 1 # noqa: E741 + r = j + k - 1 # update max_length and start position - if max_length < length[i]: - max_length = length[i] - start = i + if max_length < length[j]: + max_length = length[j] + start = j # create that string s = new_input_string[start - max_length // 2 : start + max_length // 2 + 1] diff --git a/strings/min_cost_string_conversion.py b/strings/min_cost_string_conversion.py index e990aaa26..147bc6fc7 100644 --- a/strings/min_cost_string_conversion.py +++ b/strings/min_cost_string_conversion.py @@ -1,5 +1,3 @@ -from typing import List, Tuple - """ Algorithm for calculating the most cost-efficient sequence for converting one string into another. @@ -18,7 +16,7 @@ def compute_transform_tables( replace_cost: int, delete_cost: int, insert_cost: int, -) -> Tuple[List[int], List[str]]: +) -> tuple[list[list[int]], list[list[str]]]: source_seq = list(source_string) destination_seq = list(destination_string) len_source_seq = len(source_seq) @@ -28,7 +26,7 @@ def compute_transform_tables( [0 for _ in range(len_destination_seq + 1)] for _ in range(len_source_seq + 1) ] ops = [ - [0 for _ in range(len_destination_seq + 1)] for _ in range(len_source_seq + 1) + ["0" for _ in range(len_destination_seq + 1)] for _ in range(len_source_seq + 1) ] for i in range(1, len_source_seq + 1): @@ -59,7 +57,7 @@ def compute_transform_tables( return costs, ops -def assemble_transformation(ops: List[str], i: int, j: int) -> List[str]: +def assemble_transformation(ops: list[list[str]], i: int, j: int) -> list[str]: if i == 0 and j == 0: return [] else: From 46e56fa6f2e473d1300846b2b96e56f498872400 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Fri, 27 Aug 2021 11:45:14 +0200 Subject: [PATCH 019/726] luhn.py: Favor list comprehensions over maps (#4663) * luhn.py: Favor list comprehensions over maps As discussed in CONTRIBUTING.md. * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- hashes/luhn.py | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/hashes/luhn.py b/hashes/luhn.py index 69e7b4ccf..81014120d 100644 --- a/hashes/luhn.py +++ b/hashes/luhn.py @@ -4,39 +4,34 @@ from typing import List def is_luhn(string: str) -> bool: """ - Perform Luhn validation on input string + Perform Luhn validation on an input string Algorithm: * Double every other digit starting from 2nd last digit. * Subtract 9 if number is greater than 9. * Sum the numbers * - >>> test_cases = [79927398710, 79927398711, 79927398712, 79927398713, + >>> test_cases = (79927398710, 79927398711, 79927398712, 79927398713, ... 79927398714, 79927398715, 79927398716, 79927398717, 79927398718, - ... 79927398719] - >>> test_cases = list(map(str, test_cases)) - >>> list(map(is_luhn, test_cases)) + ... 79927398719) + >>> [is_luhn(str(test_case)) for test_case in test_cases] [False, False, False, True, False, False, False, False, False, False] """ check_digit: int _vector: List[str] = list(string) __vector, check_digit = _vector[:-1], int(_vector[-1]) - vector: List[int] = [*map(int, __vector)] + vector: List[int] = [int(digit) for digit in __vector] vector.reverse() - for idx, i in enumerate(vector): - - if idx & 1 == 0: - doubled: int = vector[idx] * 2 + for i, digit in enumerate(vector): + if i & 1 == 0: + doubled: int = digit * 2 if doubled > 9: doubled -= 9 - check_digit += doubled else: - check_digit += i + check_digit += digit - if (check_digit) % 10 == 0: - return True - return False + return check_digit % 10 == 0 if __name__ == "__main__": @@ -44,3 +39,4 @@ if __name__ == "__main__": doctest.testmod() assert is_luhn("79927398713") + assert not is_luhn("79927398714") From 8e5c3536c728dd7451ca301dc2d5bfb3f68b0e1a Mon Sep 17 00:00:00 2001 From: arfy slowy Date: Sun, 29 Aug 2021 01:07:10 +0700 Subject: [PATCH 020/726] [fixed] unused variable, standalone running, import doctest module (#4673) * [fixed] unused variable, standalone running, import doctest module information [standalone running](https://www.geeksforgeeks.org/what-does-the-if-__name__-__main__-do/) Signed-off-by: slowy07 * Update other/fischer_yates_shuffle.py Co-authored-by: Christian Clauss * [fixed] change to tuple and fixing callfunction Signed-off-by: slowy07 * Update matrix/spiral_print.py Co-authored-by: Christian Clauss * Update matrix/spiral_print.py Co-authored-by: Christian Clauss * fixing Co-authored-by: Christian Clauss * [fixed] sprial matrix Signed-off-by: slowy07 * Update spiral_print.py * Update spiral_print.py * Update spiral_print.py * Update spiral_print.py Co-authored-by: Christian Clauss --- ...h_fibonacci_using_matrix_exponentiation.py | 3 ++ matrix/spiral_print.py | 34 +++++++++---------- other/fischer_yates_shuffle.py | 6 ++-- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/matrix/nth_fibonacci_using_matrix_exponentiation.py b/matrix/nth_fibonacci_using_matrix_exponentiation.py index 8c39de0f2..341a02e1a 100644 --- a/matrix/nth_fibonacci_using_matrix_exponentiation.py +++ b/matrix/nth_fibonacci_using_matrix_exponentiation.py @@ -88,4 +88,7 @@ def main(): if __name__ == "__main__": + import doctest + + doctest.testmod() main() diff --git a/matrix/spiral_print.py b/matrix/spiral_print.py index 21dab7615..6f699c1ab 100644 --- a/matrix/spiral_print.py +++ b/matrix/spiral_print.py @@ -4,36 +4,35 @@ This problem has been solved through recursive way. Matrix must satisfy below conditions i) matrix should be only one or two dimensional - ii)column of all the row should be equal + ii) number of column of all rows should be equal """ +from collections.abc import Iterable -def checkMatrix(a): + +def check_matrix(matrix): # must be - if type(a) == list and len(a) > 0: - if type(a[0]) == list: - prevLen = 0 - for i in a: - if prevLen == 0: - prevLen = len(i) - result = True - elif prevLen == len(i): + if matrix and isinstance(matrix, Iterable): + if isinstance(matrix[0], Iterable): + prev_len = 0 + for row in matrix: + if prev_len == 0: + prev_len = len(row) result = True else: - result = False + result = prev_len == len(row) else: result = True else: result = False + return result def spiralPrint(a): - - if checkMatrix(a) and len(a) > 0: - + if check_matrix(a) and len(a) > 0: matRow = len(a) - if type(a[0]) == list: + if isinstance(a[0], Iterable): matCol = len(a[0]) else: for dat in a: @@ -64,5 +63,6 @@ def spiralPrint(a): # driver code -a = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]] -spiralPrint(a) +if __name__ == "__main__": + a = ([1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]) + spiralPrint(a) diff --git a/other/fischer_yates_shuffle.py b/other/fischer_yates_shuffle.py index 6eec738c0..035fcb482 100644 --- a/other/fischer_yates_shuffle.py +++ b/other/fischer_yates_shuffle.py @@ -8,8 +8,8 @@ wikipedia/Fischer-Yates-Shuffle. import random -def FYshuffle(list): - for i in range(len(list)): +def fisher_yates_shuffle(data: list) -> list: + for _ in range(len(list)): a = random.randint(0, len(list) - 1) b = random.randint(0, len(list) - 1) list[a], list[b] = list[b], list[a] @@ -21,4 +21,4 @@ if __name__ == "__main__": strings = ["python", "says", "hello", "!"] print("Fisher-Yates Shuffle:") print("List", integers, strings) - print("FY Shuffle", FYshuffle(integers), FYshuffle(strings)) + print("FY Shuffle", fisher_yates_shuffle(integers), fisher_yates_shuffle(strings)) From 3acca3d1d188f89c6aa0fb4c0139ac62426ea296 Mon Sep 17 00:00:00 2001 From: Aswin Murali Date: Mon, 30 Aug 2021 13:36:59 +0530 Subject: [PATCH 021/726] Fix type annotations for integer_partition.py #4052 (#4689) --- dynamic_programming/integer_partition.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dynamic_programming/integer_partition.py b/dynamic_programming/integer_partition.py index 4eb06348c..8ed2e51bd 100644 --- a/dynamic_programming/integer_partition.py +++ b/dynamic_programming/integer_partition.py @@ -6,8 +6,8 @@ into k parts. These two facts together are used for this algorithm. """ -def partition(m): - memo = [[0 for _ in range(m)] for _ in range(m + 1)] +def partition(m: int) -> int: + memo: list[list[int]] = [[0 for _ in range(m)] for _ in range(m + 1)] for i in range(m + 1): memo[i][0] = 1 From 097f83023866d625a38c891a46ce3a70d73d7f63 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 31 Aug 2021 06:56:15 +0200 Subject: [PATCH 022/726] Avoid mutable default arguments (#4691) --- graphs/eulerian_path_and_circuit_for_undirected_graph.py | 4 ++-- graphs/frequent_pattern_graph_miner.py | 4 ++-- maths/radix2_fft.py | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/graphs/eulerian_path_and_circuit_for_undirected_graph.py b/graphs/eulerian_path_and_circuit_for_undirected_graph.py index 7850933b0..fa4f73abd 100644 --- a/graphs/eulerian_path_and_circuit_for_undirected_graph.py +++ b/graphs/eulerian_path_and_circuit_for_undirected_graph.py @@ -6,8 +6,8 @@ # using dfs for finding eulerian path traversal -def dfs(u, graph, visited_edge, path=[]): - path = path + [u] +def dfs(u, graph, visited_edge, path=None): + path = (path or []) + [u] for v in graph[u]: if visited_edge[u][v] is False: visited_edge[u][v], visited_edge[v][u] = True, True diff --git a/graphs/frequent_pattern_graph_miner.py b/graphs/frequent_pattern_graph_miner.py index 8f344b7bd..548ce3c54 100644 --- a/graphs/frequent_pattern_graph_miner.py +++ b/graphs/frequent_pattern_graph_miner.py @@ -168,11 +168,11 @@ def construct_graph(cluster, nodes): return graph -def myDFS(graph, start, end, path=[]): +def myDFS(graph, start, end, path=None): """ find different DFS walk from given node to Header node """ - path = path + [start] + path = (path or []) + [start] if start == end: paths.append(path) for node in graph[start]: diff --git a/maths/radix2_fft.py b/maths/radix2_fft.py index de87071e5..9fc9f843e 100644 --- a/maths/radix2_fft.py +++ b/maths/radix2_fft.py @@ -49,10 +49,10 @@ class FFT: A*B = 0*x^(-0+0j) + 1*x^(2+0j) + 2*x^(3+0j) + 3*x^(8+0j) + 4*x^(6+0j) + 5*x^(8+0j) """ - def __init__(self, polyA=[0], polyB=[0]): + def __init__(self, polyA=None, polyB=None): # Input as list - self.polyA = list(polyA)[:] - self.polyB = list(polyB)[:] + self.polyA = list(polyA or [0])[:] + self.polyB = list(polyB or [0])[:] # Remove leading zero coefficients while self.polyA[-1] == 0: From ef9827166e778879e0bc5847c4bcee6720073657 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 31 Aug 2021 07:56:19 +0200 Subject: [PATCH 023/726] Approve functions used as default arguments (#4699) * Approve functions used as default argumenets * The default value for **seed** is the result of a function call The default value for **seed** is the result of a function call which is not normally recommended and causes flake8-bugbear to raise a B008 error. However, in this case, it is accptable because `LinearCongruentialGenerator.__init__()` will only be called once per instance and it ensures that each instance will generate a unique sequence of numbers. * The default value for **backend** is the result of a function call The default value for **backend** is the result of a function call which is not normally recommended and causes flake8-bugbear to raise a B008 error. However, in this case, it is accptable because `Aer.get_backend()` is called when the function is definition and that same backend is then reused for function calls. * Update linear_congruential_generator.py * Update ripple_adder_classic.py * Update ripple_adder_classic.py * Update ripple_adder_classic.py * Update ripple_adder_classic.py * Update ripple_adder_classic.py --- other/linear_congruential_generator.py | 8 +++++++- quantum/ripple_adder_classic.py | 14 +++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/other/linear_congruential_generator.py b/other/linear_congruential_generator.py index f8b604b85..777ee6355 100644 --- a/other/linear_congruential_generator.py +++ b/other/linear_congruential_generator.py @@ -8,7 +8,13 @@ class LinearCongruentialGenerator: A pseudorandom number generator. """ - def __init__(self, multiplier, increment, modulo, seed=int(time())): + # The default value for **seed** is the result of a function call which is not + # normally recommended and causes flake8-bugbear to raise a B008 error. However, + # in this case, it is accptable because `LinearCongruentialGenerator.__init__()` + # will only be called once per instance and it ensures that each instance will + # generate a unique sequence of numbers. + + def __init__(self, multiplier, increment, modulo, seed=int(time())): # noqa: B008 """ These parameters are saved and used when nextNumber() is called. diff --git a/quantum/ripple_adder_classic.py b/quantum/ripple_adder_classic.py index dc0c2103b..8539a62af 100644 --- a/quantum/ripple_adder_classic.py +++ b/quantum/ripple_adder_classic.py @@ -53,8 +53,16 @@ def full_adder( circuit.cx(input1_loc, input2_loc) +# The default value for **backend** is the result of a function call which is not +# normally recommended and causes flake8-bugbear to raise a B008 error. However, +# in this case, this is accptable because `Aer.get_backend()` is called when the +# function is defined and that same backend is then reused for all function calls. + + def ripple_adder( - val1: int, val2: int, backend: BaseBackend = Aer.get_backend("qasm_simulator") + val1: int, + val2: int, + backend: BaseBackend = Aer.get_backend("qasm_simulator"), # noqa: B008 ) -> int: """ Quantum Equivalent of a Ripple Adder Circuit @@ -63,7 +71,7 @@ def ripple_adder( Currently only adds 'emulated' Classical Bits but nothing prevents us from doing this with hadamard'd bits :) - Only supports adding +ve Integers + Only supports adding positive integers >>> ripple_adder(3, 4) 7 @@ -99,7 +107,7 @@ def ripple_adder( res = execute(circuit, backend, shots=1).result() # The result is in binary. Convert it back to int - return int(list(res.get_counts().keys())[0], 2) + return int(list(res.get_counts())[0], 2) if __name__ == "__main__": From 757d4fb84f77865fc569aae4129999faf75c970f Mon Sep 17 00:00:00 2001 From: Kiran Hipparagi <49370990+KiranHipparagi@users.noreply.github.com> Date: Wed, 1 Sep 2021 01:36:49 +0530 Subject: [PATCH 024/726] Added Dutch National Flag algorithm #4636 (#4639) * Added Dutch national flag sort Algorithm * Changed file name to dnf_sort.py * Added descriptive name and type hint Added descriptive name and type hint for parameter with doctest for the function dnf_sort. * Added test cases * Added doctest cases * Update sorts/dnf_sort.py * Added doctest for dutch_national_flag_sort sorts/dnf_sort.py * Update sorts/dnf_sort.py * Added doctest for the function dutch_national_flag_sort * update file as per black code formatter * Update dnf_sort.py * Update and rename dnf_sort.py to dutch_national_flag_sort.py Co-authored-by: Christian Clauss --- sorts/dutch_national_flag_sort.py | 100 ++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 sorts/dutch_national_flag_sort.py diff --git a/sorts/dutch_national_flag_sort.py b/sorts/dutch_national_flag_sort.py new file mode 100644 index 000000000..79afefa73 --- /dev/null +++ b/sorts/dutch_national_flag_sort.py @@ -0,0 +1,100 @@ +""" +A pure implementation of Dutch national flag (DNF) sort algorithm in Python. +Dutch National Flag algorithm is an algorithm originally designed by Edsger Dijkstra. +It is the most optimal sort for 3 unique values (eg. 0, 1, 2) in a sequence. DNF can +sort a sequence of n size with [0 <= a[i] <= 2] at guaranteed O(n) complexity in a +single pass. + +The flag of the Netherlands consists of three colors: white, red, and blue. +The task is to randomly arrange balls of white, red, and blue in such a way that balls +of the same color are placed together. DNF sorts a sequence of 0, 1, and 2's in linear +time that does not consume any extra space. This algorithm can be implemented only on +a sequence that contains three unique elements. + +1) Time complexity is O(n). +2) Space complexity is O(1). + +More info on: https://en.wikipedia.org/wiki/Dutch_national_flag_problem + +For doctests run following command: +python3 -m doctest -v dutch_national_flag_sort.py + +For manual testing run: +python dnf_sort.py +""" + + +# Python program to sort a sequence containing only 0, 1 and 2 in a single pass. +red = 0 # The first color of the flag. +white = 1 # The second color of the flag. +blue = 2 # The third color of the flag. +colors = (red, white, blue) + + +def dutch_national_flag_sort(sequence: list) -> list: + """ + A pure Python implementation of Dutch National Flag sort algorithm. + :param data: 3 unique integer values (e.g., 0, 1, 2) in an sequence + :return: The same collection in ascending order + + >>> dutch_national_flag_sort([]) + [] + >>> dutch_national_flag_sort([0]) + [0] + >>> dutch_national_flag_sort([2, 1, 0, 0, 1, 2]) + [0, 0, 1, 1, 2, 2] + >>> dutch_national_flag_sort([0, 1, 1, 0, 1, 2, 1, 2, 0, 0, 0, 1]) + [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2] + >>> dutch_national_flag_sort("abacab") + Traceback (most recent call last): + ... + ValueError: The elements inside the sequence must contains only (0, 1, 2) values + >>> dutch_national_flag_sort("Abacab") + Traceback (most recent call last): + ... + ValueError: The elements inside the sequence must contains only (0, 1, 2) values + >>> dutch_national_flag_sort([3, 2, 3, 1, 3, 0, 3]) + Traceback (most recent call last): + ... + ValueError: The elements inside the sequence must contains only (0, 1, 2) values + >>> dutch_national_flag_sort([-1, 2, -1, 1, -1, 0, -1]) + Traceback (most recent call last): + ... + ValueError: The elements inside the sequence must contains only (0, 1, 2) values + >>> dutch_national_flag_sort([1.1, 2, 1.1, 1, 1.1, 0, 1.1]) + Traceback (most recent call last): + ... + ValueError: The elements inside the sequence must contains only (0, 1, 2) values + """ + if not sequence: + return [] + if len(sequence) == 1: + return list(sequence) + low = 0 + high = len(sequence) - 1 + mid = 0 + while mid <= high: + if sequence[mid] == colors[0]: + sequence[low], sequence[mid] = sequence[mid], sequence[low] + low += 1 + mid += 1 + elif sequence[mid] == colors[1]: + mid += 1 + elif sequence[mid] == colors[2]: + sequence[mid], sequence[high] = sequence[high], sequence[mid] + high -= 1 + else: + raise ValueError( + f"The elements inside the sequence must contains only {colors} values" + ) + return sequence + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + + user_input = input("Enter numbers separated by commas:\n").strip() + unsorted = [int(item.strip()) for item in user_input.split(",")] + print(f"{dutch_national_flag_sort(unsorted)}") From c1b15a86baabd110347bd4d478d88bc2820824e5 Mon Sep 17 00:00:00 2001 From: imp Date: Fri, 3 Sep 2021 17:49:23 +0800 Subject: [PATCH 025/726] [mypy] Fix type annotations for dynamic programming (#4687) * Fix mypy error for knapsack.py * Fix mypy error for longest_increasing_subsequence * Fix mypy error for fractional_knapsack_2.py --- dynamic_programming/fractional_knapsack_2.py | 17 +++++------------ dynamic_programming/knapsack.py | 2 +- .../longest_increasing_subsequence.py | 2 +- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/dynamic_programming/fractional_knapsack_2.py b/dynamic_programming/fractional_knapsack_2.py index cae577383..bd776723c 100644 --- a/dynamic_programming/fractional_knapsack_2.py +++ b/dynamic_programming/fractional_knapsack_2.py @@ -7,7 +7,7 @@ from __future__ import annotations def fractional_knapsack( value: list[int], weight: list[int], capacity: int -) -> tuple[int, list[int]]: +) -> tuple[float, list[float]]: """ >>> value = [1, 3, 5, 7, 9] >>> weight = [0.9, 0.7, 0.5, 0.3, 0.1] @@ -32,8 +32,8 @@ def fractional_knapsack( ratio = [v / w for v, w in zip(value, weight)] index.sort(key=lambda i: ratio[i], reverse=True) - max_value = 0 - fractions = [0] * len(value) + max_value: float = 0 + fractions: list[float] = [0] * len(value) for i in index: if weight[i] <= capacity: fractions[i] = 1 @@ -48,13 +48,6 @@ def fractional_knapsack( if __name__ == "__main__": - n = int(input("Enter number of items: ")) - value = input(f"Enter the values of the {n} item(s) in order: ").split() - value = [int(v) for v in value] - weight = input(f"Enter the positive weights of the {n} item(s) in order: ".split()) - weight = [int(w) for w in weight] - capacity = int(input("Enter maximum weight: ")) + import doctest - max_value, fractions = fractional_knapsack(value, weight, capacity) - print("The maximum value of items that can be carried:", max_value) - print("The fractions in which the items should be taken:", fractions) + doctest.testmod() diff --git a/dynamic_programming/knapsack.py b/dynamic_programming/knapsack.py index 69e54c00a..804d7d4f1 100644 --- a/dynamic_programming/knapsack.py +++ b/dynamic_programming/knapsack.py @@ -91,7 +91,7 @@ def knapsack_with_example_solution(W: int, wt: list, val: list): ) optimal_val, dp_table = knapsack(W, wt, val, num_items) - example_optional_set = set() + example_optional_set: set = set() _construct_solution(dp_table, wt, num_items, W, example_optional_set) return optimal_val, example_optional_set diff --git a/dynamic_programming/longest_increasing_subsequence.py b/dynamic_programming/longest_increasing_subsequence.py index f5ca8a2b5..a029f9be7 100644 --- a/dynamic_programming/longest_increasing_subsequence.py +++ b/dynamic_programming/longest_increasing_subsequence.py @@ -36,7 +36,7 @@ def longest_subsequence(array: list[int]) -> list[int]: # This function is recu pivot = array[0] isFound = False i = 1 - longest_subseq = [] + longest_subseq: list[int] = [] while not isFound and i < array_length: if array[i] < pivot: isFound = True From 5d5831bdd07fff31278c84c4e7b313d633abf752 Mon Sep 17 00:00:00 2001 From: Aviv Faraj <73610201+avivfaraj@users.noreply.github.com> Date: Mon, 6 Sep 2021 17:57:18 -0400 Subject: [PATCH 026/726] Physics new code (#4709) * added gamma_function * Add files via upload * Resolved issue with str.format And also changed output to math notation * Update gamma_function.py * Rename physics/gamma_function.py to maths/gamma_recursive.py * Fixes: #4709 Fixed issues for pre-commit test * Fixes: #4709 solved issues with doctests And comments * Fixes: #4709 Added failed tests to doctest * Align with Python's Standard Library math.gamma() Replicate the exceptions of https://docs.python.org/3/library/math.html#math.gamma * Update gamma_recursive.py * Update gamma_recursive.py * Update gamma_recursive.py * Update gamma_recursive.py Co-authored-by: Christian Clauss --- maths/gamma_recursive.py | 78 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 maths/gamma_recursive.py diff --git a/maths/gamma_recursive.py b/maths/gamma_recursive.py new file mode 100644 index 000000000..683d7adb1 --- /dev/null +++ b/maths/gamma_recursive.py @@ -0,0 +1,78 @@ +""" +Gamma function is a very useful tool in math and physics. +It helps calculating complex integral in a convenient way. +for more info: https://en.wikipedia.org/wiki/Gamma_function + +Python's Standard Library math.gamma() function overflows around gamma(171.624). +""" +from math import pi, sqrt + + +def gamma(num: float) -> float: + """ + Calculates the value of Gamma function of num + where num is either an integer (1, 2, 3..) or a half-integer (0.5, 1.5, 2.5 ...). + Implemented using recursion + Examples: + >>> from math import isclose, gamma as math_gamma + >>> gamma(0.5) + 1.7724538509055159 + >>> gamma(2) + 1.0 + >>> gamma(3.5) + 3.3233509704478426 + >>> gamma(171.5) + 9.483367566824795e+307 + >>> all(isclose(gamma(num), math_gamma(num)) for num in (0.5, 2, 3.5, 171.5)) + True + >>> gamma(0) + Traceback (most recent call last): + ... + ValueError: math domain error + >>> gamma(-1.1) + Traceback (most recent call last): + ... + ValueError: math domain error + >>> gamma(-4) + Traceback (most recent call last): + ... + ValueError: math domain error + >>> gamma(172) + Traceback (most recent call last): + ... + OverflowError: math range error + >>> gamma(1.1) + Traceback (most recent call last): + ... + NotImplementedError: num must be an integer or a half-integer + """ + if num <= 0: + raise ValueError("math domain error") + if num > 171.5: + raise OverflowError("math range error") + elif num - int(num) not in (0, 0.5): + raise NotImplementedError("num must be an integer or a half-integer") + elif num == 0.5: + return sqrt(pi) + else: + return 1.0 if num == 1 else (num - 1) * gamma(num - 1) + + +def test_gamma() -> None: + """ + >>> test_gamma() + """ + assert gamma(0.5) == sqrt(pi) + assert gamma(1) == 1.0 + assert gamma(2) == 1.0 + + +if __name__ == "__main__": + from doctest import testmod + + testmod() + num = 1 + while num: + num = float(input("Gamma of: ")) + print(f"gamma({num}) = {gamma(num)}") + print("\nEnter 0 to exit...") From cecf43d6481173e831af829da77911e1a3868a6c Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 7 Sep 2021 13:37:03 +0200 Subject: [PATCH 027/726] Pyupgrade to Python 3.9 (#4718) * Pyupgrade to Python 3.9 * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 3 ++- arithmetic_analysis/in_static_equilibrium.py | 4 +-- arithmetic_analysis/lu_decomposition.py | 4 +-- .../newton_forward_interpolation.py | 4 +-- arithmetic_analysis/newton_raphson.py | 5 ++-- backtracking/all_combinations.py | 12 ++++----- backtracking/all_permutations.py | 14 +++++----- backtracking/all_subsequences.py | 10 ++++--- backtracking/coloring.py | 7 +++-- backtracking/hamiltonian_cycle.py | 7 +++-- backtracking/knight_tour.py | 10 +++---- backtracking/minimax.py | 5 ++-- backtracking/n_queens.py | 8 +++--- backtracking/n_queens_math.py | 12 ++++----- backtracking/rat_in_maze.py | 6 ++--- backtracking/sudoku.py | 8 +++--- backtracking/sum_of_subsets.py | 14 +++++----- blockchain/chinese_remainder_theorem.py | 4 +-- blockchain/diophantine_equation.py | 6 ++--- blockchain/modular_division.py | 6 ++--- boolean_algebra/quine_mc_cluskey.py | 12 ++++----- cellular_automata/conways_game_of_life.py | 5 +--- ciphers/caesar_cipher.py | 9 ++++--- ciphers/decrypt_caesar_with_chi_squared.py | 7 +++-- ciphers/diffie.py | 4 +-- ciphers/shuffled_shift_cipher.py | 5 ++-- compression/huffman.py | 2 +- conversions/molecular_chemistry.py | 2 +- conversions/prefix_conversions.py | 11 ++++---- data_structures/binary_tree/avl_tree.py | 25 +++++++++--------- .../binary_tree/basic_binary_tree.py | 10 +++---- .../binary_search_tree_recursive.py | 24 ++++++++--------- .../binary_tree/binary_tree_traversals.py | 7 ++--- .../binary_tree/lazy_segment_tree.py | 5 ++-- .../binary_tree/merge_two_binary_trees.py | 10 +++---- data_structures/binary_tree/red_black_tree.py | 26 ++++++++++--------- data_structures/binary_tree/treap.py | 21 +++++++-------- data_structures/binary_tree/wavelet_tree.py | 7 +++-- data_structures/hashing/hash_table.py | 2 +- .../hashing/hash_table_with_linked_list.py | 2 +- data_structures/heap/heap.py | 12 +++++---- data_structures/heap/randomized_heap.py | 16 ++++++------ data_structures/heap/skew_heap.py | 14 +++++----- .../linked_list/merge_two_lists.py | 5 ++-- data_structures/linked_list/print_reverse.py | 4 +-- data_structures/linked_list/skip_list.py | 7 +++-- .../stacks/evaluate_postfix_notations.py | 7 ++--- data_structures/stacks/linked_stack.py | 6 +++-- data_structures/stacks/stack.py | 4 +-- divide_and_conquer/convex_hull.py | 19 +++++++------- divide_and_conquer/kth_order_statistic.py | 5 ++-- divide_and_conquer/mergesort.py | 6 ++--- divide_and_conquer/peak.py | 4 +-- electronics/electric_power.py | 5 ++-- electronics/ohms_law.py | 4 +-- graphs/basic_graphs.py | 8 +++--- graphs/bellman_ford.py | 8 +++--- graphs/bfs_zero_one_shortest_path.py | 14 +++++----- graphs/bidirectional_a_star.py | 7 ++--- graphs/bidirectional_breadth_first_search.py | 10 +++---- graphs/breadth_first_search.py | 7 +++-- graphs/breadth_first_search_shortest_path.py | 4 +-- graphs/depth_first_search.py | 5 +--- graphs/greedy_best_first.py | 8 +++--- graphs/minimum_spanning_tree_kruskal.py | 2 +- graphs/minimum_spanning_tree_prims2.py | 7 ++--- graphs/page_rank.py | 2 +- graphs/scc_kosaraju.py | 14 +++++----- hashes/luhn.py | 6 ++--- knapsack/knapsack.py | 5 ++-- linear_algebra/src/lib.py | 26 +++++++++---------- machine_learning/similarity_search.py | 5 ++-- maths/area_under_curve.py | 9 ++++--- maths/average_mean.py | 4 +-- maths/average_median.py | 4 +-- maths/entropy.py | 6 ++--- maths/euclidean_distance.py | 2 ++ maths/extended_euclidean_algorithm.py | 4 +-- maths/hardy_ramanujanalgo.py | 2 +- maths/line_length.py | 10 ++++--- maths/max_sum_sliding_window.py | 4 +-- maths/median_of_two_arrays.py | 4 +-- maths/numerical_integration.py | 9 ++++--- maths/sieve_of_eratosthenes.py | 5 ++-- maths/volume.py | 5 ++-- matrix/searching_in_sorted_matrix.py | 4 +-- other/date_to_weekday.py | 2 +- ...land.py => davisb_putnamb_logemannb_loveland.py} | 24 ++++++++--------- other/lfu_cache.py | 6 +++-- other/lru_cache.py | 6 +++-- project_euler/problem_001/sol1.py | 2 +- project_euler/problem_001/sol5.py | 2 +- project_euler/problem_006/sol3.py | 2 +- project_euler/problem_008/sol2.py | 5 +--- project_euler/problem_012/sol2.py | 2 +- project_euler/problem_013/sol1.py | 2 +- project_euler/problem_014/sol2.py | 6 ++--- project_euler/problem_020/sol2.py | 2 +- project_euler/problem_021/sol1.py | 8 +++--- project_euler/problem_033/sol1.py | 5 ++-- project_euler/problem_036/sol1.py | 5 ++-- project_euler/problem_038/sol1.py | 5 ++-- project_euler/problem_049/sol1.py | 2 +- project_euler/problem_050/sol1.py | 4 +-- project_euler/problem_051/sol1.py | 6 ++--- project_euler/problem_054/sol1.py | 4 +-- project_euler/problem_056/sol1.py | 8 +++--- project_euler/problem_059/sol1.py | 23 ++++++++-------- project_euler/problem_070/sol1.py | 4 +-- project_euler/problem_074/sol1.py | 2 +- project_euler/problem_077/sol1.py | 8 +++--- project_euler/problem_080/sol1.py | 2 +- project_euler/problem_081/sol1.py | 2 +- project_euler/problem_085/sol1.py | 5 ++-- project_euler/problem_089/sol1.py | 2 +- project_euler/problem_101/sol1.py | 18 ++++++------- project_euler/problem_102/sol1.py | 14 +++++----- project_euler/problem_107/sol1.py | 21 ++++++++------- project_euler/problem_119/sol1.py | 2 +- project_euler/problem_123/sol1.py | 5 ++-- project_euler/problem_180/sol1.py | 7 +++-- project_euler/problem_203/sol1.py | 12 ++++----- scheduling/first_come_first_served.py | 12 ++++----- scheduling/round_robin.py | 9 ++++--- scheduling/shortest_job_first.py | 12 ++++----- searches/binary_search.py | 19 +++++++------- searches/fibonacci_search.py | 2 +- searches/ternary_search.py | 8 +++--- sorts/bitonic_sort.py | 8 +++--- sorts/bucket_sort.py | 4 +-- sorts/msd_radix_sort.py | 10 +++---- sorts/patience_sort.py | 7 ++--- sorts/pigeon_sort.py | 4 +-- sorts/quick_sort.py | 6 ++--- sorts/radix_sort.py | 6 ++--- sorts/recursive_insertion_sort.py | 5 +--- sorts/slowsort.py | 7 ++--- strings/aho_corasick.py | 7 ++--- strings/boyer_moore_search.py | 4 +-- strings/knuth_morris_pratt.py | 4 +-- web_programming/emails_from_url.py | 5 ++-- web_programming/fetch_github_info.py | 6 +++-- 142 files changed, 523 insertions(+), 530 deletions(-) rename other/{davis–putnam–logemann–loveland.py => davisb_putnamb_logemannb_loveland.py} (94%) diff --git a/DIRECTORY.md b/DIRECTORY.md index 41485f6f0..0c00d5ca7 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -545,7 +545,7 @@ ## Other * [Activity Selection](https://github.com/TheAlgorithms/Python/blob/master/other/activity_selection.py) * [Date To Weekday](https://github.com/TheAlgorithms/Python/blob/master/other/date_to_weekday.py) - * [Davis–Putnam–Logemann–Loveland](https://github.com/TheAlgorithms/Python/blob/master/other/davis–putnam–logemann–loveland.py) + * [Davisb Putnamb Logemannb Loveland](https://github.com/TheAlgorithms/Python/blob/master/other/davisb_putnamb_logemannb_loveland.py) * [Dijkstra Bankers Algorithm](https://github.com/TheAlgorithms/Python/blob/master/other/dijkstra_bankers_algorithm.py) * [Doomsday](https://github.com/TheAlgorithms/Python/blob/master/other/doomsday.py) * [Fischer Yates Shuffle](https://github.com/TheAlgorithms/Python/blob/master/other/fischer_yates_shuffle.py) @@ -860,6 +860,7 @@ * [Counting Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/counting_sort.py) * [Cycle Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/cycle_sort.py) * [Double Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/double_sort.py) + * [Dutch National Flag Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/dutch_national_flag_sort.py) * [Exchange Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/exchange_sort.py) * [External Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/external_sort.py) * [Gnome Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/gnome_sort.py) diff --git a/arithmetic_analysis/in_static_equilibrium.py b/arithmetic_analysis/in_static_equilibrium.py index 7b5006a1a..6e8d1d043 100644 --- a/arithmetic_analysis/in_static_equilibrium.py +++ b/arithmetic_analysis/in_static_equilibrium.py @@ -1,14 +1,14 @@ """ Checks if a system of forces is in static equilibrium. """ -from typing import List +from __future__ import annotations from numpy import array, cos, cross, ndarray, radians, sin def polar_force( magnitude: float, angle: float, radian_mode: bool = False -) -> List[float]: +) -> list[float]: """ Resolves force along rectangular components. (force, angle) => (force_x, force_y) diff --git a/arithmetic_analysis/lu_decomposition.py b/arithmetic_analysis/lu_decomposition.py index 5bb631758..b488b1bb3 100644 --- a/arithmetic_analysis/lu_decomposition.py +++ b/arithmetic_analysis/lu_decomposition.py @@ -3,12 +3,12 @@ Reference: - https://en.wikipedia.org/wiki/LU_decomposition """ -from typing import Tuple +from __future__ import annotations import numpy as np -def lower_upper_decomposition(table: np.ndarray) -> Tuple[np.ndarray, np.ndarray]: +def lower_upper_decomposition(table: np.ndarray) -> tuple[np.ndarray, np.ndarray]: """Lower-Upper (LU) Decomposition Example: diff --git a/arithmetic_analysis/newton_forward_interpolation.py b/arithmetic_analysis/newton_forward_interpolation.py index 66cde4b73..490e0687f 100644 --- a/arithmetic_analysis/newton_forward_interpolation.py +++ b/arithmetic_analysis/newton_forward_interpolation.py @@ -1,7 +1,7 @@ # https://www.geeksforgeeks.org/newton-forward-backward-interpolation/ +from __future__ import annotations import math -from typing import List # for calculating u value @@ -22,7 +22,7 @@ def ucal(u: float, p: int) -> float: def main() -> None: n = int(input("enter the numbers of values: ")) - y: List[List[float]] = [] + y: list[list[float]] = [] for i in range(n): y.append([]) for i in range(n): diff --git a/arithmetic_analysis/newton_raphson.py b/arithmetic_analysis/newton_raphson.py index 146bb0aa5..1a8205386 100644 --- a/arithmetic_analysis/newton_raphson.py +++ b/arithmetic_analysis/newton_raphson.py @@ -2,15 +2,16 @@ # Author: Syed Haseeb Shah (github.com/QuantumNovice) # The Newton-Raphson method (also known as Newton's method) is a way to # quickly find a good approximation for the root of a real-valued function +from __future__ import annotations + from decimal import Decimal from math import * # noqa: F401, F403 -from typing import Union from sympy import diff def newton_raphson( - func: str, a: Union[float, Decimal], precision: float = 10 ** -10 + func: str, a: float | Decimal, precision: float = 10 ** -10 ) -> float: """Finds root from the point 'a' onwards by Newton-Raphson method >>> newton_raphson("sin(x)", 2) diff --git a/backtracking/all_combinations.py b/backtracking/all_combinations.py index 76462837c..bde60f032 100644 --- a/backtracking/all_combinations.py +++ b/backtracking/all_combinations.py @@ -3,16 +3,16 @@ numbers out of 1 ... n. We use backtracking to solve this problem. Time complexity: O(C(n,k)) which is O(n choose k) = O((n!/(k! * (n - k)!))) """ -from typing import List +from __future__ import annotations -def generate_all_combinations(n: int, k: int) -> List[List[int]]: +def generate_all_combinations(n: int, k: int) -> list[list[int]]: """ >>> generate_all_combinations(n=4, k=2) [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]] """ - result: List[List[int]] = [] + result: list[list[int]] = [] create_all_state(1, n, k, [], result) return result @@ -21,8 +21,8 @@ def create_all_state( increment: int, total_number: int, level: int, - current_list: List[int], - total_list: List[List[int]], + current_list: list[int], + total_list: list[list[int]], ) -> None: if level == 0: total_list.append(current_list[:]) @@ -34,7 +34,7 @@ def create_all_state( current_list.pop() -def print_all_state(total_list: List[List[int]]) -> None: +def print_all_state(total_list: list[list[int]]) -> None: for i in total_list: print(*i) diff --git a/backtracking/all_permutations.py b/backtracking/all_permutations.py index a0032c5ca..ff8a53e0d 100644 --- a/backtracking/all_permutations.py +++ b/backtracking/all_permutations.py @@ -5,18 +5,18 @@ Time complexity: O(n! * n), where n denotes the length of the given sequence. """ -from typing import List, Union +from __future__ import annotations -def generate_all_permutations(sequence: List[Union[int, str]]) -> None: +def generate_all_permutations(sequence: list[int | str]) -> None: create_state_space_tree(sequence, [], 0, [0 for i in range(len(sequence))]) def create_state_space_tree( - sequence: List[Union[int, str]], - current_sequence: List[Union[int, str]], + sequence: list[int | str], + current_sequence: list[int | str], index: int, - index_used: List[int], + index_used: list[int], ) -> None: """ Creates a state space tree to iterate through each branch using DFS. @@ -44,8 +44,8 @@ print("Enter the elements") sequence = list(map(int, input().split())) """ -sequence: List[Union[int, str]] = [3, 1, 2, 4] +sequence: list[int | str] = [3, 1, 2, 4] generate_all_permutations(sequence) -sequence_2: List[Union[int, str]] = ["A", "B", "C"] +sequence_2: list[int | str] = ["A", "B", "C"] generate_all_permutations(sequence_2) diff --git a/backtracking/all_subsequences.py b/backtracking/all_subsequences.py index 99db4ea46..c465fc542 100644 --- a/backtracking/all_subsequences.py +++ b/backtracking/all_subsequences.py @@ -5,15 +5,17 @@ of the given sequence. We use backtracking to solve this problem. Time complexity: O(2^n), where n denotes the length of the given sequence. """ -from typing import Any, List +from __future__ import annotations + +from typing import Any -def generate_all_subsequences(sequence: List[Any]) -> None: +def generate_all_subsequences(sequence: list[Any]) -> None: create_state_space_tree(sequence, [], 0) def create_state_space_tree( - sequence: List[Any], current_subsequence: List[Any], index: int + sequence: list[Any], current_subsequence: list[Any], index: int ) -> None: """ Creates a state space tree to iterate through each branch using DFS. @@ -32,7 +34,7 @@ def create_state_space_tree( if __name__ == "__main__": - seq: List[Any] = [3, 1, 2, 4] + seq: list[Any] = [3, 1, 2, 4] generate_all_subsequences(seq) seq.clear() diff --git a/backtracking/coloring.py b/backtracking/coloring.py index 3956b21a9..8bda4b587 100644 --- a/backtracking/coloring.py +++ b/backtracking/coloring.py @@ -5,11 +5,10 @@ Wikipedia: https://en.wikipedia.org/wiki/Graph_coloring """ -from typing import List def valid_coloring( - neighbours: List[int], colored_vertices: List[int], color: int + neighbours: list[int], colored_vertices: list[int], color: int ) -> bool: """ For each neighbour check if coloring constraint is satisfied @@ -35,7 +34,7 @@ def valid_coloring( def util_color( - graph: List[List[int]], max_colors: int, colored_vertices: List[int], index: int + graph: list[list[int]], max_colors: int, colored_vertices: list[int], index: int ) -> bool: """ Pseudo-Code @@ -86,7 +85,7 @@ def util_color( return False -def color(graph: List[List[int]], max_colors: int) -> List[int]: +def color(graph: list[list[int]], max_colors: int) -> list[int]: """ Wrapper function to call subroutine called util_color which will either return True or False. diff --git a/backtracking/hamiltonian_cycle.py b/backtracking/hamiltonian_cycle.py index 7be1ea350..19751b347 100644 --- a/backtracking/hamiltonian_cycle.py +++ b/backtracking/hamiltonian_cycle.py @@ -6,11 +6,10 @@ Wikipedia: https://en.wikipedia.org/wiki/Hamiltonian_path """ -from typing import List def valid_connection( - graph: List[List[int]], next_ver: int, curr_ind: int, path: List[int] + graph: list[list[int]], next_ver: int, curr_ind: int, path: list[int] ) -> bool: """ Checks whether it is possible to add next into path by validating 2 statements @@ -47,7 +46,7 @@ def valid_connection( return not any(vertex == next_ver for vertex in path) -def util_hamilton_cycle(graph: List[List[int]], path: List[int], curr_ind: int) -> bool: +def util_hamilton_cycle(graph: list[list[int]], path: list[int], curr_ind: int) -> bool: """ Pseudo-Code Base Case: @@ -108,7 +107,7 @@ def util_hamilton_cycle(graph: List[List[int]], path: List[int], curr_ind: int) return False -def hamilton_cycle(graph: List[List[int]], start_index: int = 0) -> List[int]: +def hamilton_cycle(graph: list[list[int]], start_index: int = 0) -> list[int]: r""" Wrapper function to call subroutine called util_hamilton_cycle, which will either return array of vertices indicating hamiltonian cycle diff --git a/backtracking/knight_tour.py b/backtracking/knight_tour.py index 8e6613e07..6e9b31bd1 100644 --- a/backtracking/knight_tour.py +++ b/backtracking/knight_tour.py @@ -1,9 +1,9 @@ # Knight Tour Intro: https://www.youtube.com/watch?v=ab_dY3dZFHM -from typing import List, Tuple +from __future__ import annotations -def get_valid_pos(position: Tuple[int, int], n: int) -> List[Tuple[int, int]]: +def get_valid_pos(position: tuple[int, int], n: int) -> list[tuple[int, int]]: """ Find all the valid positions a knight can move to from the current position. @@ -32,7 +32,7 @@ def get_valid_pos(position: Tuple[int, int], n: int) -> List[Tuple[int, int]]: return permissible_positions -def is_complete(board: List[List[int]]) -> bool: +def is_complete(board: list[list[int]]) -> bool: """ Check if the board (matrix) has been completely filled with non-zero values. @@ -47,7 +47,7 @@ def is_complete(board: List[List[int]]) -> bool: def open_knight_tour_helper( - board: List[List[int]], pos: Tuple[int, int], curr: int + board: list[list[int]], pos: tuple[int, int], curr: int ) -> bool: """ Helper function to solve knight tour problem. @@ -68,7 +68,7 @@ def open_knight_tour_helper( return False -def open_knight_tour(n: int) -> List[List[int]]: +def open_knight_tour(n: int) -> list[list[int]]: """ Find the solution for the knight tour problem for a board of size n. Raises ValueError if the tour cannot be performed for the given size. diff --git a/backtracking/minimax.py b/backtracking/minimax.py index dda29b47d..6e310131e 100644 --- a/backtracking/minimax.py +++ b/backtracking/minimax.py @@ -7,12 +7,13 @@ if move is of maximizer return true else false leaves of game tree is stored in scores[] height is maximum height of Game tree """ +from __future__ import annotations + import math -from typing import List def minimax( - depth: int, node_index: int, is_max: bool, scores: List[int], height: float + depth: int, node_index: int, is_max: bool, scores: list[int], height: float ) -> int: """ >>> import math diff --git a/backtracking/n_queens.py b/backtracking/n_queens.py index 29b8d819a..b8ace5978 100644 --- a/backtracking/n_queens.py +++ b/backtracking/n_queens.py @@ -7,12 +7,12 @@ diagonal lines. """ -from typing import List +from __future__ import annotations solution = [] -def isSafe(board: List[List[int]], row: int, column: int) -> bool: +def isSafe(board: list[list[int]], row: int, column: int) -> bool: """ This function returns a boolean value True if it is safe to place a queen there considering the current state of the board. @@ -40,7 +40,7 @@ def isSafe(board: List[List[int]], row: int, column: int) -> bool: return True -def solve(board: List[List[int]], row: int) -> bool: +def solve(board: list[list[int]], row: int) -> bool: """ It creates a state space tree and calls the safe function until it receives a False Boolean and terminates that branch and backtracks to the next @@ -70,7 +70,7 @@ def solve(board: List[List[int]], row: int) -> bool: return False -def printboard(board: List[List[int]]) -> None: +def printboard(board: list[list[int]]) -> None: """ Prints the boards that have a successful combination. """ diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index a8651c5c3..c12aa6c33 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -75,14 +75,14 @@ Applying this two formulas we can check if a queen in some position is being att for another one or vice versa. """ -from typing import List +from __future__ import annotations def depth_first_search( - possible_board: List[int], - diagonal_right_collisions: List[int], - diagonal_left_collisions: List[int], - boards: List[List[str]], + possible_board: list[int], + diagonal_right_collisions: list[int], + diagonal_left_collisions: list[int], + boards: list[list[str]], n: int, ) -> None: """ @@ -139,7 +139,7 @@ def depth_first_search( def n_queens_solution(n: int) -> None: - boards: List[List[str]] = [] + boards: list[list[str]] = [] depth_first_search([], [], [], boards, n) # Print all the boards diff --git a/backtracking/rat_in_maze.py b/backtracking/rat_in_maze.py index cd2a8f41d..2860880db 100644 --- a/backtracking/rat_in_maze.py +++ b/backtracking/rat_in_maze.py @@ -1,7 +1,7 @@ -from typing import List +from __future__ import annotations -def solve_maze(maze: List[List[int]]) -> bool: +def solve_maze(maze: list[list[int]]) -> bool: """ This method solves the "rat in maze" problem. In this problem we have some n by n matrix, a start point and an end point. @@ -70,7 +70,7 @@ def solve_maze(maze: List[List[int]]) -> bool: return solved -def run_maze(maze: List[List[int]], i: int, j: int, solutions: List[List[int]]) -> bool: +def run_maze(maze: list[list[int]], i: int, j: int, solutions: list[list[int]]) -> bool: """ This method is recursive starting from (i, j) and going in one of four directions: up, down, left, right. diff --git a/backtracking/sudoku.py b/backtracking/sudoku.py index 593fa52d6..698dedcc2 100644 --- a/backtracking/sudoku.py +++ b/backtracking/sudoku.py @@ -9,9 +9,9 @@ function on the next column to see if it returns True. if yes, we have solved the puzzle. else, we backtrack and place another number in that cell and repeat this process. """ -from typing import List, Optional, Tuple +from __future__ import annotations -Matrix = List[List[int]] +Matrix = list[list[int]] # assigning initial values to the grid initial_grid: Matrix = [ @@ -59,7 +59,7 @@ def is_safe(grid: Matrix, row: int, column: int, n: int) -> bool: return True -def find_empty_location(grid: Matrix) -> Optional[Tuple[int, int]]: +def find_empty_location(grid: Matrix) -> tuple[int, int] | None: """ This function finds an empty location so that we can assign a number for that particular row and column. @@ -71,7 +71,7 @@ def find_empty_location(grid: Matrix) -> Optional[Tuple[int, int]]: return None -def sudoku(grid: Matrix) -> Optional[Matrix]: +def sudoku(grid: Matrix) -> Matrix | None: """ Takes a partially filled-in grid and attempts to assign values to all unassigned locations in such a way to meet the requirements diff --git a/backtracking/sum_of_subsets.py b/backtracking/sum_of_subsets.py index f695b8f7a..8348544c0 100644 --- a/backtracking/sum_of_subsets.py +++ b/backtracking/sum_of_subsets.py @@ -6,12 +6,12 @@ Summation of the chosen numbers must be equal to given number M and one number can be used only once. """ -from typing import List +from __future__ import annotations -def generate_sum_of_subsets_soln(nums: List[int], max_sum: int) -> List[List[int]]: - result: List[List[int]] = [] - path: List[int] = [] +def generate_sum_of_subsets_soln(nums: list[int], max_sum: int) -> list[list[int]]: + result: list[list[int]] = [] + path: list[int] = [] num_index = 0 remaining_nums_sum = sum(nums) create_state_space_tree(nums, max_sum, num_index, path, result, remaining_nums_sum) @@ -19,11 +19,11 @@ def generate_sum_of_subsets_soln(nums: List[int], max_sum: int) -> List[List[int def create_state_space_tree( - nums: List[int], + nums: list[int], max_sum: int, num_index: int, - path: List[int], - result: List[List[int]], + path: list[int], + result: list[list[int]], remaining_nums_sum: int, ) -> None: """ diff --git a/blockchain/chinese_remainder_theorem.py b/blockchain/chinese_remainder_theorem.py index b50147ac1..54d861dd9 100644 --- a/blockchain/chinese_remainder_theorem.py +++ b/blockchain/chinese_remainder_theorem.py @@ -11,11 +11,11 @@ Algorithm : 1. Use extended euclid algorithm to find x,y such that a*x + b*y = 1 2. Take n = ra*by + rb*ax """ -from typing import Tuple +from __future__ import annotations # Extended Euclid -def extended_euclid(a: int, b: int) -> Tuple[int, int]: +def extended_euclid(a: int, b: int) -> tuple[int, int]: """ >>> extended_euclid(10, 6) (-1, 2) diff --git a/blockchain/diophantine_equation.py b/blockchain/diophantine_equation.py index 7df674cb1..22b0cad75 100644 --- a/blockchain/diophantine_equation.py +++ b/blockchain/diophantine_equation.py @@ -1,7 +1,7 @@ -from typing import Tuple +from __future__ import annotations -def diophantine(a: int, b: int, c: int) -> Tuple[float, float]: +def diophantine(a: int, b: int, c: int) -> tuple[float, float]: """ Diophantine Equation : Given integers a,b,c ( at least one of a and b != 0), the diophantine equation a*x + b*y = c has a solution (where x and y are integers) @@ -95,7 +95,7 @@ def greatest_common_divisor(a: int, b: int) -> int: return b -def extended_gcd(a: int, b: int) -> Tuple[int, int, int]: +def extended_gcd(a: int, b: int) -> tuple[int, int, int]: """ Extended Euclid's Algorithm : If d divides a and b and d = a*x + b*y for integers x and y, then d = gcd(a,b) diff --git a/blockchain/modular_division.py b/blockchain/modular_division.py index 4f7f50a92..a9d0f65c5 100644 --- a/blockchain/modular_division.py +++ b/blockchain/modular_division.py @@ -1,4 +1,4 @@ -from typing import Tuple +from __future__ import annotations def modular_division(a: int, b: int, n: int) -> int: @@ -73,7 +73,7 @@ def modular_division2(a: int, b: int, n: int) -> int: return x -def extended_gcd(a: int, b: int) -> Tuple[int, int, int]: +def extended_gcd(a: int, b: int) -> tuple[int, int, int]: """ Extended Euclid's Algorithm : If d divides a and b and d = a*x + b*y for integers x and y, then d = gcd(a,b) @@ -101,7 +101,7 @@ def extended_gcd(a: int, b: int) -> Tuple[int, int, int]: return (d, x, y) -def extended_euclid(a: int, b: int) -> Tuple[int, int]: +def extended_euclid(a: int, b: int) -> tuple[int, int]: """ Extended Euclid >>> extended_euclid(10, 6) diff --git a/boolean_algebra/quine_mc_cluskey.py b/boolean_algebra/quine_mc_cluskey.py index 70cdf25a7..9cc99b1ee 100644 --- a/boolean_algebra/quine_mc_cluskey.py +++ b/boolean_algebra/quine_mc_cluskey.py @@ -1,4 +1,4 @@ -from typing import List +from __future__ import annotations def compare_string(string1: str, string2: str) -> str: @@ -22,7 +22,7 @@ def compare_string(string1: str, string2: str) -> str: return "".join(l1) -def check(binary: List[str]) -> List[str]: +def check(binary: list[str]) -> list[str]: """ >>> check(['0.00.01.5']) ['0.00.01.5'] @@ -46,7 +46,7 @@ def check(binary: List[str]) -> List[str]: binary = list(set(temp)) -def decimal_to_binary(no_of_variable: int, minterms: List[float]) -> List[str]: +def decimal_to_binary(no_of_variable: int, minterms: list[float]) -> list[str]: """ >>> decimal_to_binary(3,[1.5]) ['0.00.01.5'] @@ -82,7 +82,7 @@ def is_for_table(string1: str, string2: str, count: int) -> bool: return False -def selection(chart: List[List[int]], prime_implicants: List[str]) -> List[str]: +def selection(chart: list[list[int]], prime_implicants: list[str]) -> list[str]: """ >>> selection([[1]],['0.00.01.5']) ['0.00.01.5'] @@ -130,8 +130,8 @@ def selection(chart: List[List[int]], prime_implicants: List[str]) -> List[str]: def prime_implicant_chart( - prime_implicants: List[str], binary: List[str] -) -> List[List[int]]: + prime_implicants: list[str], binary: list[str] +) -> list[list[int]]: """ >>> prime_implicant_chart(['0.00.01.5'],['0.00.01.5']) [[1]] diff --git a/cellular_automata/conways_game_of_life.py b/cellular_automata/conways_game_of_life.py index 321baa3a3..079fb4d04 100644 --- a/cellular_automata/conways_game_of_life.py +++ b/cellular_automata/conways_game_of_life.py @@ -2,11 +2,8 @@ Conway's Game of Life implemented in Python. https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life """ - from __future__ import annotations -from typing import List - from PIL import Image # Define glider example @@ -25,7 +22,7 @@ GLIDER = [ BLINKER = [[0, 1, 0], [0, 1, 0], [0, 1, 0]] -def new_generation(cells: List[List[int]]) -> List[List[int]]: +def new_generation(cells: list[list[int]]) -> list[list[int]]: """ Generates the next generation for a given state of Conway's Game of Life. >>> new_generation(BLINKER) diff --git a/ciphers/caesar_cipher.py b/ciphers/caesar_cipher.py index 4b2f76c7d..8cd9fab58 100644 --- a/ciphers/caesar_cipher.py +++ b/ciphers/caesar_cipher.py @@ -1,8 +1,9 @@ +from __future__ import annotations + from string import ascii_letters -from typing import Dict, Optional -def encrypt(input_string: str, key: int, alphabet: Optional[str] = None) -> str: +def encrypt(input_string: str, key: int, alphabet: str | None = None) -> str: """ encrypt ======= @@ -80,7 +81,7 @@ def encrypt(input_string: str, key: int, alphabet: Optional[str] = None) -> str: return result -def decrypt(input_string: str, key: int, alphabet: Optional[str] = None) -> str: +def decrypt(input_string: str, key: int, alphabet: str | None = None) -> str: """ decrypt ======= @@ -145,7 +146,7 @@ def decrypt(input_string: str, key: int, alphabet: Optional[str] = None) -> str: return encrypt(input_string, key, alphabet) -def brute_force(input_string: str, alphabet: Optional[str] = None) -> Dict[int, str]: +def brute_force(input_string: str, alphabet: str | None = None) -> dict[int, str]: """ brute_force =========== diff --git a/ciphers/decrypt_caesar_with_chi_squared.py b/ciphers/decrypt_caesar_with_chi_squared.py index 7e3705b8f..89477914a 100644 --- a/ciphers/decrypt_caesar_with_chi_squared.py +++ b/ciphers/decrypt_caesar_with_chi_squared.py @@ -1,12 +1,11 @@ #!/usr/bin/env python3 - -from typing import Optional +from __future__ import annotations def decrypt_caesar_with_chi_squared( ciphertext: str, - cipher_alphabet: Optional[list[str]] = None, - frequencies_dict: Optional[dict[str, float]] = None, + cipher_alphabet: list[str] | None = None, + frequencies_dict: dict[str, float] | None = None, case_sensetive: bool = False, ) -> tuple[int, float, str]: """ diff --git a/ciphers/diffie.py b/ciphers/diffie.py index a23a8104a..4ff90be00 100644 --- a/ciphers/diffie.py +++ b/ciphers/diffie.py @@ -1,7 +1,7 @@ -from typing import Optional +from __future__ import annotations -def find_primitive(n: int) -> Optional[int]: +def find_primitive(n: int) -> int | None: for r in range(1, n): li = [] for x in range(n - 1): diff --git a/ciphers/shuffled_shift_cipher.py b/ciphers/shuffled_shift_cipher.py index 01d099641..3b84f97f6 100644 --- a/ciphers/shuffled_shift_cipher.py +++ b/ciphers/shuffled_shift_cipher.py @@ -1,6 +1,7 @@ +from __future__ import annotations + import random import string -from typing import Optional class ShuffledShiftCipher: @@ -27,7 +28,7 @@ class ShuffledShiftCipher: cip2 = ShuffledShiftCipher() """ - def __init__(self, passcode: Optional[str] = None) -> None: + def __init__(self, passcode: str | None = None) -> None: """ Initializes a cipher object with a passcode as it's entity Note: No new passcode is generated if user provides a passcode diff --git a/compression/huffman.py b/compression/huffman.py index b6cc4de1e..8f37a53ce 100644 --- a/compression/huffman.py +++ b/compression/huffman.py @@ -30,7 +30,7 @@ def parse_file(file_path): if not c: break chars[c] = chars[c] + 1 if c in chars.keys() else 1 - return sorted([Letter(c, f) for c, f in chars.items()], key=lambda l: l.freq) + return sorted((Letter(c, f) for c, f in chars.items()), key=lambda l: l.freq) def build_tree(letters): diff --git a/conversions/molecular_chemistry.py b/conversions/molecular_chemistry.py index 8c6845996..0024eb5cb 100644 --- a/conversions/molecular_chemistry.py +++ b/conversions/molecular_chemistry.py @@ -20,7 +20,7 @@ def molarity_to_normality(nfactor: int, moles: float, volume: float) -> float: >>> molarity_to_normality(4, 11.4, 5.7) 8 """ - return round((float(moles / volume) * nfactor)) + return round(float(moles / volume) * nfactor) def moles_to_pressure(volume: float, moles: float, temperature: float) -> float: diff --git a/conversions/prefix_conversions.py b/conversions/prefix_conversions.py index 78db4a917..a77556433 100644 --- a/conversions/prefix_conversions.py +++ b/conversions/prefix_conversions.py @@ -1,8 +1,9 @@ """ Convert International System of Units (SI) and Binary prefixes """ +from __future__ import annotations + from enum import Enum -from typing import Union class SI_Unit(Enum): @@ -41,8 +42,8 @@ class Binary_Unit(Enum): def convert_si_prefix( known_amount: float, - known_prefix: Union[str, SI_Unit], - unknown_prefix: Union[str, SI_Unit], + known_prefix: str | SI_Unit, + unknown_prefix: str | SI_Unit, ) -> float: """ Wikipedia reference: https://en.wikipedia.org/wiki/Binary_prefix @@ -70,8 +71,8 @@ def convert_si_prefix( def convert_binary_prefix( known_amount: float, - known_prefix: Union[str, Binary_Unit], - unknown_prefix: Union[str, Binary_Unit], + known_prefix: str | Binary_Unit, + unknown_prefix: str | Binary_Unit, ) -> float: """ Wikipedia reference: https://en.wikipedia.org/wiki/Metric_prefix diff --git a/data_structures/binary_tree/avl_tree.py b/data_structures/binary_tree/avl_tree.py index e0d3e4d43..1ab13777b 100644 --- a/data_structures/binary_tree/avl_tree.py +++ b/data_structures/binary_tree/avl_tree.py @@ -5,15 +5,16 @@ python3 -m doctest -v avl_tree.py For testing run: python avl_tree.py """ +from __future__ import annotations import math import random -from typing import Any, List, Optional +from typing import Any class my_queue: def __init__(self) -> None: - self.data: List[Any] = [] + self.data: list[Any] = [] self.head: int = 0 self.tail: int = 0 @@ -41,17 +42,17 @@ class my_queue: class my_node: def __init__(self, data: Any) -> None: self.data = data - self.left: Optional[my_node] = None - self.right: Optional[my_node] = None + self.left: my_node | None = None + self.right: my_node | None = None self.height: int = 1 def get_data(self) -> Any: return self.data - def get_left(self) -> Optional["my_node"]: + def get_left(self) -> my_node | None: return self.left - def get_right(self) -> Optional["my_node"]: + def get_right(self) -> my_node | None: return self.right def get_height(self) -> int: @@ -61,11 +62,11 @@ class my_node: self.data = data return - def set_left(self, node: Optional["my_node"]) -> None: + def set_left(self, node: my_node | None) -> None: self.left = node return - def set_right(self, node: Optional["my_node"]) -> None: + def set_right(self, node: my_node | None) -> None: self.right = node return @@ -74,7 +75,7 @@ class my_node: return -def get_height(node: Optional["my_node"]) -> int: +def get_height(node: my_node | None) -> int: if node is None: return 0 return node.get_height() @@ -149,7 +150,7 @@ def rl_rotation(node: my_node) -> my_node: return left_rotation(node) -def insert_node(node: Optional["my_node"], data: Any) -> Optional["my_node"]: +def insert_node(node: my_node | None, data: Any) -> my_node | None: if node is None: return my_node(data) if data < node.get_data(): @@ -197,7 +198,7 @@ def get_leftMost(root: my_node) -> Any: return root.get_data() -def del_node(root: my_node, data: Any) -> Optional["my_node"]: +def del_node(root: my_node, data: Any) -> my_node | None: left_child = root.get_left() right_child = root.get_right() if root.get_data() == data: @@ -275,7 +276,7 @@ class AVLtree: """ def __init__(self) -> None: - self.root: Optional[my_node] = None + self.root: my_node | None = None def get_height(self) -> int: return get_height(self.root) diff --git a/data_structures/binary_tree/basic_binary_tree.py b/data_structures/binary_tree/basic_binary_tree.py index 575b157ee..65dccf247 100644 --- a/data_structures/binary_tree/basic_binary_tree.py +++ b/data_structures/binary_tree/basic_binary_tree.py @@ -1,4 +1,4 @@ -from typing import Optional +from __future__ import annotations class Node: @@ -8,11 +8,11 @@ class Node: def __init__(self, data: int) -> None: self.data = data - self.left: Optional[Node] = None - self.right: Optional[Node] = None + self.left: Node | None = None + self.right: Node | None = None -def display(tree: Optional[Node]) -> None: # In Order traversal of the tree +def display(tree: Node | None) -> None: # In Order traversal of the tree """ >>> root = Node(1) >>> root.left = Node(0) @@ -30,7 +30,7 @@ def display(tree: Optional[Node]) -> None: # In Order traversal of the tree display(tree.right) -def depth_of_tree(tree: Optional[Node]) -> int: +def depth_of_tree(tree: Node | None) -> int: """ Recursive function that returns the depth of a binary tree. diff --git a/data_structures/binary_tree/binary_search_tree_recursive.py b/data_structures/binary_tree/binary_search_tree_recursive.py index a05e28a7b..4bdf4e33d 100644 --- a/data_structures/binary_tree/binary_search_tree_recursive.py +++ b/data_structures/binary_tree/binary_search_tree_recursive.py @@ -7,21 +7,23 @@ python -m unittest binary_search_tree_recursive.py To run an example: python binary_search_tree_recursive.py """ +from __future__ import annotations + import unittest -from typing import Iterator, Optional +from typing import Iterator class Node: - def __init__(self, label: int, parent: Optional["Node"]) -> None: + def __init__(self, label: int, parent: Node | None) -> None: self.label = label self.parent = parent - self.left: Optional[Node] = None - self.right: Optional[Node] = None + self.left: Node | None = None + self.right: Node | None = None class BinarySearchTree: def __init__(self) -> None: - self.root: Optional[Node] = None + self.root: Node | None = None def empty(self) -> None: """ @@ -66,9 +68,7 @@ class BinarySearchTree: """ self.root = self._put(self.root, label) - def _put( - self, node: Optional[Node], label: int, parent: Optional[Node] = None - ) -> Node: + def _put(self, node: Node | None, label: int, parent: Node | None = None) -> Node: if node is None: node = Node(label, parent) else: @@ -98,7 +98,7 @@ class BinarySearchTree: """ return self._search(self.root, label) - def _search(self, node: Optional[Node], label: int) -> Node: + def _search(self, node: Node | None, label: int) -> Node: if node is None: raise Exception(f"Node with label {label} does not exist") else: @@ -140,7 +140,7 @@ class BinarySearchTree: else: self._reassign_nodes(node, None) - def _reassign_nodes(self, node: Node, new_children: Optional[Node]) -> None: + def _reassign_nodes(self, node: Node, new_children: Node | None) -> None: if new_children: new_children.parent = node.parent @@ -244,7 +244,7 @@ class BinarySearchTree: """ return self._inorder_traversal(self.root) - def _inorder_traversal(self, node: Optional[Node]) -> Iterator[Node]: + def _inorder_traversal(self, node: Node | None) -> Iterator[Node]: if node is not None: yield from self._inorder_traversal(node.left) yield node @@ -266,7 +266,7 @@ class BinarySearchTree: """ return self._preorder_traversal(self.root) - def _preorder_traversal(self, node: Optional[Node]) -> Iterator[Node]: + def _preorder_traversal(self, node: Node | None) -> Iterator[Node]: if node is not None: yield node yield from self._preorder_traversal(node.left) diff --git a/data_structures/binary_tree/binary_tree_traversals.py b/data_structures/binary_tree/binary_tree_traversals.py index 7857880da..de9e9d60d 100644 --- a/data_structures/binary_tree/binary_tree_traversals.py +++ b/data_structures/binary_tree/binary_tree_traversals.py @@ -1,13 +1,14 @@ # https://en.wikipedia.org/wiki/Tree_traversal +from __future__ import annotations + from dataclasses import dataclass -from typing import Optional @dataclass class Node: data: int - left: Optional["Node"] = None - right: Optional["Node"] = None + left: Node | None = None + right: Node | None = None def make_tree() -> Node: diff --git a/data_structures/binary_tree/lazy_segment_tree.py b/data_structures/binary_tree/lazy_segment_tree.py index 9066db294..94329cb43 100644 --- a/data_structures/binary_tree/lazy_segment_tree.py +++ b/data_structures/binary_tree/lazy_segment_tree.py @@ -1,7 +1,6 @@ from __future__ import annotations import math -from typing import List, Union class SegmentTree: @@ -38,7 +37,7 @@ class SegmentTree: return idx * 2 + 1 def build( - self, idx: int, left_element: int, right_element: int, A: List[int] + self, idx: int, left_element: int, right_element: int, A: list[int] ) -> None: if left_element == right_element: self.segment_tree[idx] = A[left_element - 1] @@ -89,7 +88,7 @@ class SegmentTree: # query with O(lg n) def query( self, idx: int, left_element: int, right_element: int, a: int, b: int - ) -> Union[int, float]: + ) -> int | float: """ query(1, 1, size, a, b) for query max of [a,b] >>> A = [1, 2, -4, 7, 3, -5, 6, 11, -20, 9, 14, 15, 5, 2, -8] diff --git a/data_structures/binary_tree/merge_two_binary_trees.py b/data_structures/binary_tree/merge_two_binary_trees.py index 6b202adb3..d169e0e75 100644 --- a/data_structures/binary_tree/merge_two_binary_trees.py +++ b/data_structures/binary_tree/merge_two_binary_trees.py @@ -5,7 +5,7 @@ The rule for merging is that if two nodes overlap, then put the value sum of both nodes to the new value of the merged node. Otherwise, the NOT null node will be used as the node of new tree. """ -from typing import Optional +from __future__ import annotations class Node: @@ -15,11 +15,11 @@ class Node: def __init__(self, value: int = 0) -> None: self.value = value - self.left: Optional[Node] = None - self.right: Optional[Node] = None + self.left: Node | None = None + self.right: Node | None = None -def merge_two_binary_trees(tree1: Optional[Node], tree2: Optional[Node]) -> Node: +def merge_two_binary_trees(tree1: Node | None, tree2: Node | None) -> Node: """ Returns root node of the merged tree. @@ -52,7 +52,7 @@ def merge_two_binary_trees(tree1: Optional[Node], tree2: Optional[Node]) -> Node return tree1 -def print_preorder(root: Optional[Node]) -> None: +def print_preorder(root: Node | None) -> None: """ Print pre-order traversal of the tree. diff --git a/data_structures/binary_tree/red_black_tree.py b/data_structures/binary_tree/red_black_tree.py index de971a712..e27757f20 100644 --- a/data_structures/binary_tree/red_black_tree.py +++ b/data_structures/binary_tree/red_black_tree.py @@ -2,7 +2,9 @@ python/black : true flake8 : passed """ -from typing import Iterator, Optional +from __future__ import annotations + +from typing import Iterator class RedBlackTree: @@ -21,11 +23,11 @@ class RedBlackTree: def __init__( self, - label: Optional[int] = None, + label: int | None = None, color: int = 0, - parent: Optional["RedBlackTree"] = None, - left: Optional["RedBlackTree"] = None, - right: Optional["RedBlackTree"] = None, + parent: RedBlackTree | None = None, + left: RedBlackTree | None = None, + right: RedBlackTree | None = None, ) -> None: """Initialize a new Red-Black Tree node with the given values: label: The value associated with this node @@ -42,7 +44,7 @@ class RedBlackTree: # Here are functions which are specific to red-black trees - def rotate_left(self) -> "RedBlackTree": + def rotate_left(self) -> RedBlackTree: """Rotate the subtree rooted at this node to the left and returns the new root to this subtree. Performing one rotation can be done in O(1). @@ -62,7 +64,7 @@ class RedBlackTree: right.parent = parent return right - def rotate_right(self) -> "RedBlackTree": + def rotate_right(self) -> RedBlackTree: """Rotate the subtree rooted at this node to the right and returns the new root to this subtree. Performing one rotation can be done in O(1). @@ -82,7 +84,7 @@ class RedBlackTree: left.parent = parent return left - def insert(self, label: int) -> "RedBlackTree": + def insert(self, label: int) -> RedBlackTree: """Inserts label into the subtree rooted at self, performs any rotations necessary to maintain balance, and then returns the new root to this subtree (likely self). @@ -139,7 +141,7 @@ class RedBlackTree: self.grandparent.color = 1 self.grandparent._insert_repair() - def remove(self, label: int) -> "RedBlackTree": + def remove(self, label: int) -> RedBlackTree: """Remove label from this tree.""" if self.label == label: if self.left and self.right: @@ -337,7 +339,7 @@ class RedBlackTree: """ return self.search(label) is not None - def search(self, label: int) -> "RedBlackTree": + def search(self, label: int) -> RedBlackTree: """Search through the tree for label, returning its node if it's found, and None otherwise. This method is guaranteed to run in O(log(n)) time. @@ -411,7 +413,7 @@ class RedBlackTree: return self.label @property - def grandparent(self) -> "RedBlackTree": + def grandparent(self) -> RedBlackTree: """Get the current node's grandparent, or None if it doesn't exist.""" if self.parent is None: return None @@ -419,7 +421,7 @@ class RedBlackTree: return self.parent.parent @property - def sibling(self) -> "RedBlackTree": + def sibling(self) -> RedBlackTree: """Get the current node's sibling, or None if it doesn't exist.""" if self.parent is None: return None diff --git a/data_structures/binary_tree/treap.py b/data_structures/binary_tree/treap.py index a09dcc928..0526b139b 100644 --- a/data_structures/binary_tree/treap.py +++ b/data_structures/binary_tree/treap.py @@ -1,9 +1,6 @@ -# flake8: noqa - from __future__ import annotations from random import random -from typing import Optional, Tuple class Node: @@ -12,11 +9,11 @@ class Node: Treap is a binary tree by value and heap by priority """ - def __init__(self, value: Optional[int] = None): + def __init__(self, value: int | None = None): self.value = value self.prior = random() - self.left: Optional[Node] = None - self.right: Optional[Node] = None + self.left: Node | None = None + self.right: Node | None = None def __repr__(self) -> str: from pprint import pformat @@ -35,7 +32,7 @@ class Node: return value + left + right -def split(root: Optional[Node], value: int) -> Tuple[Optional[Node], Optional[Node]]: +def split(root: Node | None, value: int) -> tuple[Node | None, Node | None]: """ We split current tree into 2 trees with value: @@ -64,7 +61,7 @@ def split(root: Optional[Node], value: int) -> Tuple[Optional[Node], Optional[No return root, right -def merge(left: Optional[Node], right: Optional[Node]) -> Optional[Node]: +def merge(left: Node | None, right: Node | None) -> Node | None: """ We merge 2 trees into one. Note: all left tree's values must be less than all right tree's @@ -86,7 +83,7 @@ def merge(left: Optional[Node], right: Optional[Node]) -> Optional[Node]: return right -def insert(root: Optional[Node], value: int) -> Optional[Node]: +def insert(root: Node | None, value: int) -> Node | None: """ Insert element @@ -99,7 +96,7 @@ def insert(root: Optional[Node], value: int) -> Optional[Node]: return merge(merge(left, node), right) -def erase(root: Optional[Node], value: int) -> Optional[Node]: +def erase(root: Node | None, value: int) -> Node | None: """ Erase element @@ -112,7 +109,7 @@ def erase(root: Optional[Node], value: int) -> Optional[Node]: return merge(left, right) -def inorder(root: Optional[Node]) -> None: +def inorder(root: Node | None) -> None: """ Just recursive print of a tree """ @@ -124,7 +121,7 @@ def inorder(root: Optional[Node]) -> None: inorder(root.right) -def interactTreap(root: Optional[Node], args: str) -> Optional[Node]: +def interactTreap(root: Node | None, args: str) -> Node | None: """ Commands: + value to add value into treap diff --git a/data_structures/binary_tree/wavelet_tree.py b/data_structures/binary_tree/wavelet_tree.py index 1607244f7..173a88ab7 100644 --- a/data_structures/binary_tree/wavelet_tree.py +++ b/data_structures/binary_tree/wavelet_tree.py @@ -7,8 +7,7 @@ such as the with segment trees or fenwick trees. You can read more about them he 2. https://www.youtube.com/watch?v=4aSv9PcecDw&t=811s 3. https://www.youtube.com/watch?v=CybAgVF-MMc&t=1178s """ - -from typing import Optional +from __future__ import annotations test_array = [2, 1, 4, 5, 6, 0, 8, 9, 1, 2, 0, 6, 4, 2, 0, 6, 5, 3, 2, 7] @@ -18,8 +17,8 @@ class Node: self.minn: int = -1 self.maxx: int = -1 self.map_left: list[int] = [-1] * length - self.left: Optional[Node] = None - self.right: Optional[Node] = None + self.left: Node | None = None + self.right: Node | None = None def __repr__(self) -> str: """ diff --git a/data_structures/hashing/hash_table.py b/data_structures/hashing/hash_table.py index fd9e6eec1..f4422de53 100644 --- a/data_structures/hashing/hash_table.py +++ b/data_structures/hashing/hash_table.py @@ -19,7 +19,7 @@ class HashTable: return self._keys def balanced_factor(self): - return sum([1 for slot in self.values if slot is not None]) / ( + return sum(1 for slot in self.values if slot is not None) / ( self.size_table * self.charge_factor ) diff --git a/data_structures/hashing/hash_table_with_linked_list.py b/data_structures/hashing/hash_table_with_linked_list.py index fe838268f..f404c5251 100644 --- a/data_structures/hashing/hash_table_with_linked_list.py +++ b/data_structures/hashing/hash_table_with_linked_list.py @@ -14,7 +14,7 @@ class HashTableWithLinkedList(HashTable): def balanced_factor(self): return ( - sum([self.charge_factor - len(slot) for slot in self.values]) + sum(self.charge_factor - len(slot) for slot in self.values) / self.size_table * self.charge_factor ) diff --git a/data_structures/heap/heap.py b/data_structures/heap/heap.py index 65a70e468..550439edd 100644 --- a/data_structures/heap/heap.py +++ b/data_structures/heap/heap.py @@ -1,4 +1,6 @@ -from typing import Iterable, List, Optional +from __future__ import annotations + +from typing import Iterable class Heap: @@ -25,19 +27,19 @@ class Heap: """ def __init__(self) -> None: - self.h: List[float] = [] + self.h: list[float] = [] self.heap_size: int = 0 def __repr__(self) -> str: return str(self.h) - def parent_index(self, child_idx: int) -> Optional[int]: + def parent_index(self, child_idx: int) -> int | None: """return the parent index of given child""" if child_idx > 0: return (child_idx - 1) // 2 return None - def left_child_idx(self, parent_idx: int) -> Optional[int]: + def left_child_idx(self, parent_idx: int) -> int | None: """ return the left child index if the left child exists. if not, return None. @@ -47,7 +49,7 @@ class Heap: return left_child_index return None - def right_child_idx(self, parent_idx: int) -> Optional[int]: + def right_child_idx(self, parent_idx: int) -> int | None: """ return the right child index if the right child exists. if not, return None. diff --git a/data_structures/heap/randomized_heap.py b/data_structures/heap/randomized_heap.py index 0ddc2272e..f584f5cb3 100644 --- a/data_structures/heap/randomized_heap.py +++ b/data_structures/heap/randomized_heap.py @@ -3,7 +3,7 @@ from __future__ import annotations import random -from typing import Generic, Iterable, List, Optional, TypeVar +from typing import Generic, Iterable, TypeVar T = TypeVar("T") @@ -16,8 +16,8 @@ class RandomizedHeapNode(Generic[T]): def __init__(self, value: T) -> None: self._value: T = value - self.left: Optional[RandomizedHeapNode[T]] = None - self.right: Optional[RandomizedHeapNode[T]] = None + self.left: RandomizedHeapNode[T] | None = None + self.right: RandomizedHeapNode[T] | None = None @property def value(self) -> T: @@ -26,8 +26,8 @@ class RandomizedHeapNode(Generic[T]): @staticmethod def merge( - root1: Optional[RandomizedHeapNode[T]], root2: Optional[RandomizedHeapNode[T]] - ) -> Optional[RandomizedHeapNode[T]]: + root1: RandomizedHeapNode[T] | None, root2: RandomizedHeapNode[T] | None + ) -> RandomizedHeapNode[T] | None: """Merge 2 nodes together.""" if not root1: return root2 @@ -69,13 +69,13 @@ class RandomizedHeap(Generic[T]): [-1, 0, 1] """ - def __init__(self, data: Optional[Iterable[T]] = ()) -> None: + def __init__(self, data: Iterable[T] | None = ()) -> None: """ >>> rh = RandomizedHeap([3, 1, 3, 7]) >>> rh.to_sorted_list() [1, 3, 3, 7] """ - self._root: Optional[RandomizedHeapNode[T]] = None + self._root: RandomizedHeapNode[T] | None = None for item in data: self.insert(item) @@ -151,7 +151,7 @@ class RandomizedHeap(Generic[T]): """ self._root = None - def to_sorted_list(self) -> List[T]: + def to_sorted_list(self) -> list[T]: """ Returns sorted list containing all the values in the heap. diff --git a/data_structures/heap/skew_heap.py b/data_structures/heap/skew_heap.py index 417a383f7..b59441389 100644 --- a/data_structures/heap/skew_heap.py +++ b/data_structures/heap/skew_heap.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Generic, Iterable, Iterator, Optional, TypeVar +from typing import Generic, Iterable, Iterator, TypeVar T = TypeVar("T") @@ -15,8 +15,8 @@ class SkewNode(Generic[T]): def __init__(self, value: T) -> None: self._value: T = value - self.left: Optional[SkewNode[T]] = None - self.right: Optional[SkewNode[T]] = None + self.left: SkewNode[T] | None = None + self.right: SkewNode[T] | None = None @property def value(self) -> T: @@ -25,8 +25,8 @@ class SkewNode(Generic[T]): @staticmethod def merge( - root1: Optional[SkewNode[T]], root2: Optional[SkewNode[T]] - ) -> Optional[SkewNode[T]]: + root1: SkewNode[T] | None, root2: SkewNode[T] | None + ) -> SkewNode[T] | None: """Merge 2 nodes together.""" if not root1: return root2 @@ -69,13 +69,13 @@ class SkewHeap(Generic[T]): [-1, 0, 1] """ - def __init__(self, data: Optional[Iterable[T]] = ()) -> None: + def __init__(self, data: Iterable[T] | None = ()) -> None: """ >>> sh = SkewHeap([3, 1, 3, 7]) >>> list(sh) [1, 3, 3, 7] """ - self._root: Optional[SkewNode[T]] = None + self._root: SkewNode[T] | None = None for item in data: self.insert(item) diff --git a/data_structures/linked_list/merge_two_lists.py b/data_structures/linked_list/merge_two_lists.py index 96ec6b8ab..43dd46186 100644 --- a/data_structures/linked_list/merge_two_lists.py +++ b/data_structures/linked_list/merge_two_lists.py @@ -5,7 +5,6 @@ from __future__ import annotations from collections.abc import Iterable, Iterator from dataclasses import dataclass -from typing import Optional test_data_odd = (3, 9, -11, 0, 7, 5, 1, -1) test_data_even = (4, 6, 2, 0, 8, 10, 3, -2) @@ -14,12 +13,12 @@ test_data_even = (4, 6, 2, 0, 8, 10, 3, -2) @dataclass class Node: data: int - next: Optional[Node] + next: Node | None class SortedLinkedList: def __init__(self, ints: Iterable[int]) -> None: - self.head: Optional[Node] = None + self.head: Node | None = None for i in reversed(sorted(ints)): self.head = Node(i, self.head) diff --git a/data_structures/linked_list/print_reverse.py b/data_structures/linked_list/print_reverse.py index c46f228e7..f83d5607f 100644 --- a/data_structures/linked_list/print_reverse.py +++ b/data_structures/linked_list/print_reverse.py @@ -1,4 +1,4 @@ -from typing import List +from __future__ import annotations class Node: @@ -16,7 +16,7 @@ class Node: return "->".join(string_rep) -def make_linked_list(elements_list: List): +def make_linked_list(elements_list: list): """Creates a Linked List from the elements of the given sequence (list/tuple) and returns the head of the Linked List. >>> make_linked_list([]) diff --git a/data_structures/linked_list/skip_list.py b/data_structures/linked_list/skip_list.py index 8f06e6193..ee0b44607 100644 --- a/data_structures/linked_list/skip_list.py +++ b/data_structures/linked_list/skip_list.py @@ -2,11 +2,10 @@ Based on "Skip Lists: A Probabilistic Alternative to Balanced Trees" by William Pugh https://epaperpress.com/sortsearch/download/skiplist.pdf """ - from __future__ import annotations from random import random -from typing import Generic, Optional, TypeVar +from typing import Generic, TypeVar KT = TypeVar("KT") VT = TypeVar("VT") @@ -124,7 +123,7 @@ class SkipList(Generic[KT, VT]): return level - def _locate_node(self, key) -> tuple[Optional[Node[KT, VT]], list[Node[KT, VT]]]: + def _locate_node(self, key) -> tuple[Node[KT, VT] | None, list[Node[KT, VT]]]: """ :param key: Searched key, :return: Tuple with searched node (or None if given key is not present) @@ -222,7 +221,7 @@ class SkipList(Generic[KT, VT]): else: update_node.forward[i] = new_node - def find(self, key: VT) -> Optional[VT]: + def find(self, key: VT) -> VT | None: """ :param key: Search key. :return: Value associated with given key or None if given key is not present. diff --git a/data_structures/stacks/evaluate_postfix_notations.py b/data_structures/stacks/evaluate_postfix_notations.py index 2a4baf9d6..51ea353b1 100644 --- a/data_structures/stacks/evaluate_postfix_notations.py +++ b/data_structures/stacks/evaluate_postfix_notations.py @@ -1,5 +1,3 @@ -from typing import Any, List - """ The Reverse Polish Nation also known as Polish postfix notation or simply postfix notation. @@ -8,6 +6,9 @@ Classic examples of simple stack implementations Valid operators are +, -, *, /. Each operand may be an integer or another expression. """ +from __future__ import annotations + +from typing import Any def evaluate_postfix(postfix_notation: list) -> int: @@ -23,7 +24,7 @@ def evaluate_postfix(postfix_notation: list) -> int: return 0 operations = {"+", "-", "*", "/"} - stack: List[Any] = [] + stack: list[Any] = [] for token in postfix_notation: if token in operations: diff --git a/data_structures/stacks/linked_stack.py b/data_structures/stacks/linked_stack.py index 0b9c9d45e..85b59a940 100644 --- a/data_structures/stacks/linked_stack.py +++ b/data_structures/stacks/linked_stack.py @@ -1,5 +1,7 @@ """ A Stack using a linked list like structure """ -from typing import Any, Optional +from __future__ import annotations + +from typing import Any class Node: @@ -42,7 +44,7 @@ class LinkedStack: """ def __init__(self) -> None: - self.top: Optional[Node] = None + self.top: Node | None = None def __iter__(self): node = self.top diff --git a/data_structures/stacks/stack.py b/data_structures/stacks/stack.py index 245d39b32..c62412150 100644 --- a/data_structures/stacks/stack.py +++ b/data_structures/stacks/stack.py @@ -1,4 +1,4 @@ -from typing import List +from __future__ import annotations class StackOverflowError(BaseException): @@ -15,7 +15,7 @@ class Stack: """ def __init__(self, limit: int = 10): - self.stack: List[int] = [] + self.stack: list[int] = [] self.limit = limit def __bool__(self) -> bool: diff --git a/divide_and_conquer/convex_hull.py b/divide_and_conquer/convex_hull.py index 9c096f671..63f8dbb20 100644 --- a/divide_and_conquer/convex_hull.py +++ b/divide_and_conquer/convex_hull.py @@ -12,8 +12,9 @@ There are other several other algorithms for the convex hull problem which have not been implemented here, yet. """ +from __future__ import annotations -from typing import Iterable, List, Set, Union +from typing import Iterable class Point: @@ -84,8 +85,8 @@ class Point: def _construct_points( - list_of_tuples: Union[List[Point], List[List[float]], Iterable[List[float]]] -) -> List[Point]: + list_of_tuples: list[Point] | list[list[float]] | Iterable[list[float]], +) -> list[Point]: """ constructs a list of points from an array-like object of numbers @@ -114,7 +115,7 @@ def _construct_points( [] """ - points: List[Point] = [] + points: list[Point] = [] if list_of_tuples: for p in list_of_tuples: if isinstance(p, Point): @@ -130,7 +131,7 @@ def _construct_points( return points -def _validate_input(points: Union[List[Point], List[List[float]]]) -> List[Point]: +def _validate_input(points: list[Point] | list[list[float]]) -> list[Point]: """ validates an input instance before a convex-hull algorithms uses it @@ -218,7 +219,7 @@ def _det(a: Point, b: Point, c: Point) -> float: return det -def convex_hull_bf(points: List[Point]) -> List[Point]: +def convex_hull_bf(points: list[Point]) -> list[Point]: """ Constructs the convex hull of a set of 2D points using a brute force algorithm. The algorithm basically considers all combinations of points (i, j) and uses the @@ -291,7 +292,7 @@ def convex_hull_bf(points: List[Point]) -> List[Point]: return sorted(convex_set) -def convex_hull_recursive(points: List[Point]) -> List[Point]: +def convex_hull_recursive(points: list[Point]) -> list[Point]: """ Constructs the convex hull of a set of 2D points using a divide-and-conquer strategy The algorithm exploits the geometric properties of the problem by repeatedly @@ -362,7 +363,7 @@ def convex_hull_recursive(points: List[Point]) -> List[Point]: def _construct_hull( - points: List[Point], left: Point, right: Point, convex_set: Set[Point] + points: list[Point], left: Point, right: Point, convex_set: set[Point] ) -> None: """ @@ -405,7 +406,7 @@ def _construct_hull( _construct_hull(candidate_points, extreme_point, right, convex_set) -def convex_hull_melkman(points: List[Point]) -> List[Point]: +def convex_hull_melkman(points: list[Point]) -> list[Point]: """ Constructs the convex hull of a set of 2D points using the melkman algorithm. The algorithm works by iteratively inserting points of a simple polygonal chain diff --git a/divide_and_conquer/kth_order_statistic.py b/divide_and_conquer/kth_order_statistic.py index f6e81a306..666ad1a39 100644 --- a/divide_and_conquer/kth_order_statistic.py +++ b/divide_and_conquer/kth_order_statistic.py @@ -8,8 +8,9 @@ This is a divide and conquer algorithm that can find a solution in O(n) time. For more information of this algorithm: https://web.stanford.edu/class/archive/cs/cs161/cs161.1138/lectures/08/Small08.pdf """ +from __future__ import annotations + from random import choice -from typing import List def random_pivot(lst): @@ -21,7 +22,7 @@ def random_pivot(lst): return choice(lst) -def kth_number(lst: List[int], k: int) -> int: +def kth_number(lst: list[int], k: int) -> int: """ Return the kth smallest number in lst. >>> kth_number([2, 1, 3, 4, 5], 3) diff --git a/divide_and_conquer/mergesort.py b/divide_and_conquer/mergesort.py index 46a46941c..628080cef 100644 --- a/divide_and_conquer/mergesort.py +++ b/divide_and_conquer/mergesort.py @@ -1,7 +1,7 @@ -from typing import List +from __future__ import annotations -def merge(left_half: List, right_half: List) -> List: +def merge(left_half: list, right_half: list) -> list: """Helper function for mergesort. >>> left_half = [-2] @@ -57,7 +57,7 @@ def merge(left_half: List, right_half: List) -> List: return sorted_array -def merge_sort(array: List) -> List: +def merge_sort(array: list) -> list: """Returns a list of sorted array elements using merge sort. >>> from random import shuffle diff --git a/divide_and_conquer/peak.py b/divide_and_conquer/peak.py index f94f83ed3..e60f28bfb 100644 --- a/divide_and_conquer/peak.py +++ b/divide_and_conquer/peak.py @@ -7,10 +7,10 @@ to find the maximum of the array. (From Kleinberg and Tardos. Algorithm Design. Addison Wesley 2006: Chapter 5 Solved Exercise 1) """ -from typing import List +from __future__ import annotations -def peak(lst: List[int]) -> int: +def peak(lst: list[int]) -> int: """ Return the peak value of `lst`. >>> peak([1, 2, 3, 4, 5, 4, 3, 2, 1]) diff --git a/electronics/electric_power.py b/electronics/electric_power.py index e4e685bbd..ac673d7e3 100644 --- a/electronics/electric_power.py +++ b/electronics/electric_power.py @@ -1,9 +1,10 @@ # https://en.m.wikipedia.org/wiki/Electric_power +from __future__ import annotations + from collections import namedtuple -from typing import Tuple -def electric_power(voltage: float, current: float, power: float) -> Tuple: +def electric_power(voltage: float, current: float, power: float) -> tuple: """ This function can calculate any one of the three (voltage, current, power), fundamental value of electrical system. diff --git a/electronics/ohms_law.py b/electronics/ohms_law.py index 41bffa9f8..66e737c1f 100644 --- a/electronics/ohms_law.py +++ b/electronics/ohms_law.py @@ -1,8 +1,8 @@ # https://en.wikipedia.org/wiki/Ohm%27s_law -from typing import Dict +from __future__ import annotations -def ohms_law(voltage: float, current: float, resistance: float) -> Dict[str, float]: +def ohms_law(voltage: float, current: float, resistance: float) -> dict[str, float]: """ Apply Ohm's Law, on any two given electrical values, which can be voltage, current, and resistance, and then in a Python dict return name/value pair of the zero value. diff --git a/graphs/basic_graphs.py b/graphs/basic_graphs.py index 9cd6dd0f9..db0ef8e7b 100644 --- a/graphs/basic_graphs.py +++ b/graphs/basic_graphs.py @@ -13,7 +13,7 @@ def initialize_unweighted_directed_graph( graph[i + 1] = [] for e in range(edge_count): - x, y = [int(i) for i in _input(f"Edge {e + 1}: ")] + x, y = (int(i) for i in _input(f"Edge {e + 1}: ")) graph[x].append(y) return graph @@ -26,7 +26,7 @@ def initialize_unweighted_undirected_graph( graph[i + 1] = [] for e in range(edge_count): - x, y = [int(i) for i in _input(f"Edge {e + 1}: ")] + x, y = (int(i) for i in _input(f"Edge {e + 1}: ")) graph[x].append(y) graph[y].append(x) return graph @@ -40,14 +40,14 @@ def initialize_weighted_undirected_graph( graph[i + 1] = [] for e in range(edge_count): - x, y, w = [int(i) for i in _input(f"Edge {e + 1}: ")] + x, y, w = (int(i) for i in _input(f"Edge {e + 1}: ")) graph[x].append((y, w)) graph[y].append((x, w)) return graph if __name__ == "__main__": - n, m = [int(i) for i in _input("Number of nodes and edges: ")] + n, m = (int(i) for i in _input("Number of nodes and edges: ")) graph_choice = int( _input( diff --git a/graphs/bellman_ford.py b/graphs/bellman_ford.py index d6d6b2ac7..0f654a510 100644 --- a/graphs/bellman_ford.py +++ b/graphs/bellman_ford.py @@ -11,7 +11,7 @@ def check_negative_cycle( graph: list[dict[str, int]], distance: list[float], edge_count: int ): for j in range(edge_count): - u, v, w = [graph[j][k] for k in ["src", "dst", "weight"]] + u, v, w = (graph[j][k] for k in ["src", "dst", "weight"]) if distance[u] != float("inf") and distance[u] + w < distance[v]: return True return False @@ -38,7 +38,7 @@ def bellman_ford( for i in range(vertex_count - 1): for j in range(edge_count): - u, v, w = [graph[j][k] for k in ["src", "dst", "weight"]] + u, v, w = (graph[j][k] for k in ["src", "dst", "weight"]) if distance[u] != float("inf") and distance[u] + w < distance[v]: distance[v] = distance[u] + w @@ -62,10 +62,10 @@ if __name__ == "__main__": for i in range(E): print("Edge ", i + 1) - src, dest, weight = [ + src, dest, weight = ( int(x) for x in input("Enter source, destination, weight: ").strip().split(" ") - ] + ) graph[i] = {"src": src, "dst": dest, "weight": weight} source = int(input("\nEnter shortest path source:").strip()) diff --git a/graphs/bfs_zero_one_shortest_path.py b/graphs/bfs_zero_one_shortest_path.py index a68b5602c..78047c5d2 100644 --- a/graphs/bfs_zero_one_shortest_path.py +++ b/graphs/bfs_zero_one_shortest_path.py @@ -1,13 +1,13 @@ -from collections import deque -from collections.abc import Iterator -from dataclasses import dataclass -from typing import Optional, Union - """ Finding the shortest path in 0-1-graph in O(E + V) which is faster than dijkstra. 0-1-graph is the weighted graph with the weights equal to 0 or 1. Link: https://codeforces.com/blog/entry/22276 """ +from __future__ import annotations + +from collections import deque +from collections.abc import Iterator +from dataclasses import dataclass @dataclass @@ -59,7 +59,7 @@ class AdjacencyList: self._graph[from_vertex].append(Edge(to_vertex, weight)) - def get_shortest_path(self, start_vertex: int, finish_vertex: int) -> Optional[int]: + def get_shortest_path(self, start_vertex: int, finish_vertex: int) -> int | None: """ Return the shortest distance from start_vertex to finish_vertex in 0-1-graph. 1 1 1 @@ -107,7 +107,7 @@ class AdjacencyList: ValueError: No path from start_vertex to finish_vertex. """ queue = deque([start_vertex]) - distances: list[Union[int, None]] = [None] * self.size + distances: list[int | None] = [None] * self.size distances[start_vertex] = 0 while queue: diff --git a/graphs/bidirectional_a_star.py b/graphs/bidirectional_a_star.py index 729d8957b..071f1cd68 100644 --- a/graphs/bidirectional_a_star.py +++ b/graphs/bidirectional_a_star.py @@ -1,15 +1,12 @@ """ https://en.wikipedia.org/wiki/Bidirectional_search """ - from __future__ import annotations import time from math import sqrt # 1 for manhattan, 0 for euclidean -from typing import Optional - HEURISTIC = 0 grid = [ @@ -50,7 +47,7 @@ class Node: goal_x: int, goal_y: int, g_cost: int, - parent: Optional[Node], + parent: Node | None, ) -> None: self.pos_x = pos_x self.pos_y = pos_y @@ -157,7 +154,7 @@ class AStar: ) return successors - def retrace_path(self, node: Optional[Node]) -> list[TPosition]: + def retrace_path(self, node: Node | None) -> list[TPosition]: """ Retrace the path from parents to parents until start node """ diff --git a/graphs/bidirectional_breadth_first_search.py b/graphs/bidirectional_breadth_first_search.py index 9b84ab21b..27e4f0b16 100644 --- a/graphs/bidirectional_breadth_first_search.py +++ b/graphs/bidirectional_breadth_first_search.py @@ -1,11 +1,9 @@ """ https://en.wikipedia.org/wiki/Bidirectional_search """ - from __future__ import annotations import time -from typing import Optional Path = list[tuple[int, int]] @@ -24,7 +22,7 @@ delta = [[-1, 0], [0, -1], [1, 0], [0, 1]] # up, left, down, right class Node: def __init__( - self, pos_x: int, pos_y: int, goal_x: int, goal_y: int, parent: Optional[Node] + self, pos_x: int, pos_y: int, goal_x: int, goal_y: int, parent: Node | None ): self.pos_x = pos_x self.pos_y = pos_y @@ -57,7 +55,7 @@ class BreadthFirstSearch: self.node_queue = [self.start] self.reached = False - def search(self) -> Optional[Path]: + def search(self) -> Path | None: while self.node_queue: current_node = self.node_queue.pop(0) @@ -93,7 +91,7 @@ class BreadthFirstSearch: ) return successors - def retrace_path(self, node: Optional[Node]) -> Path: + def retrace_path(self, node: Node | None) -> Path: """ Retrace the path from parents to parents until start node """ @@ -125,7 +123,7 @@ class BidirectionalBreadthFirstSearch: self.bwd_bfs = BreadthFirstSearch(goal, start) self.reached = False - def search(self) -> Optional[Path]: + def search(self) -> Path | None: while self.fwd_bfs.node_queue or self.bwd_bfs.node_queue: current_fwd_node = self.fwd_bfs.node_queue.pop(0) current_bwd_node = self.bwd_bfs.node_queue.pop(0) diff --git a/graphs/breadth_first_search.py b/graphs/breadth_first_search.py index 305db01e1..7c626429e 100644 --- a/graphs/breadth_first_search.py +++ b/graphs/breadth_first_search.py @@ -1,13 +1,12 @@ #!/usr/bin/python """ Author: OMKAR PATHAK """ - -from typing import Dict, List, Set +from __future__ import annotations class Graph: def __init__(self) -> None: - self.vertices: Dict[int, List[int]] = {} + self.vertices: dict[int, list[int]] = {} def print_graph(self) -> None: """ @@ -35,7 +34,7 @@ class Graph: else: self.vertices[from_vertex] = [to_vertex] - def bfs(self, start_vertex: int) -> Set[int]: + def bfs(self, start_vertex: int) -> set[int]: """ >>> g = Graph() >>> g.add_edge(0, 1) diff --git a/graphs/breadth_first_search_shortest_path.py b/graphs/breadth_first_search_shortest_path.py index 48f8ab1a4..697a8c634 100644 --- a/graphs/breadth_first_search_shortest_path.py +++ b/graphs/breadth_first_search_shortest_path.py @@ -3,8 +3,6 @@ from a given source node to a target node in an unweighted graph. """ from __future__ import annotations -from typing import Optional - graph = { "A": ["B", "C", "E"], "B": ["A", "D", "E"], @@ -24,7 +22,7 @@ class Graph: """ self.graph = graph # mapping node to its parent in resulting breadth first tree - self.parent: dict[str, Optional[str]] = {} + self.parent: dict[str, str | None] = {} self.source_vertex = source_vertex def breath_first_search(self) -> None: diff --git a/graphs/depth_first_search.py b/graphs/depth_first_search.py index 5d74a6db9..f20a503ca 100644 --- a/graphs/depth_first_search.py +++ b/graphs/depth_first_search.py @@ -1,11 +1,8 @@ """Non recursive implementation of a DFS algorithm.""" - from __future__ import annotations -from typing import Set - -def depth_first_search(graph: dict, start: str) -> Set[str]: +def depth_first_search(graph: dict, start: str) -> set[str]: """Depth First Search on Graph :param graph: directed graph in dictionary format :param start: starting vertex as a string diff --git a/graphs/greedy_best_first.py b/graphs/greedy_best_first.py index d5e80247a..d49e65b9d 100644 --- a/graphs/greedy_best_first.py +++ b/graphs/greedy_best_first.py @@ -4,8 +4,6 @@ https://en.wikipedia.org/wiki/Best-first_search#Greedy_BFS from __future__ import annotations -from typing import Optional - Path = list[tuple[int, int]] grid = [ @@ -44,7 +42,7 @@ class Node: goal_x: int, goal_y: int, g_cost: float, - parent: Optional[Node], + parent: Node | None, ): self.pos_x = pos_x self.pos_y = pos_y @@ -93,7 +91,7 @@ class GreedyBestFirst: self.reached = False - def search(self) -> Optional[Path]: + def search(self) -> Path | None: """ Search for the path, if a path is not found, only the starting position is returned @@ -156,7 +154,7 @@ class GreedyBestFirst: ) return successors - def retrace_path(self, node: Optional[Node]) -> Path: + def retrace_path(self, node: Node | None) -> Path: """ Retrace the path from parents to parents until start node """ diff --git a/graphs/minimum_spanning_tree_kruskal.py b/graphs/minimum_spanning_tree_kruskal.py index f21a87a7d..85d937010 100644 --- a/graphs/minimum_spanning_tree_kruskal.py +++ b/graphs/minimum_spanning_tree_kruskal.py @@ -40,7 +40,7 @@ if __name__ == "__main__": # pragma: no cover edges = [] for _ in range(num_edges): - node1, node2, cost = [int(x) for x in input().strip().split()] + node1, node2, cost = (int(x) for x in input().strip().split()) edges.append((node1, node2, cost)) kruskal(num_nodes, edges) diff --git a/graphs/minimum_spanning_tree_prims2.py b/graphs/minimum_spanning_tree_prims2.py index c3444c36f..d924ee3db 100644 --- a/graphs/minimum_spanning_tree_prims2.py +++ b/graphs/minimum_spanning_tree_prims2.py @@ -6,9 +6,10 @@ edges in the tree is minimized. The algorithm operates by building this tree one at a time, from an arbitrary starting vertex, at each step adding the cheapest possible connection from the tree to another vertex. """ +from __future__ import annotations from sys import maxsize -from typing import Generic, Optional, TypeVar +from typing import Generic, TypeVar T = TypeVar("T") @@ -219,7 +220,7 @@ class GraphUndirectedWeighted(Generic[T]): def prims_algo( graph: GraphUndirectedWeighted[T], -) -> tuple[dict[T, int], dict[T, Optional[T]]]: +) -> tuple[dict[T, int], dict[T, T | None]]: """ >>> graph = GraphUndirectedWeighted() @@ -240,7 +241,7 @@ def prims_algo( """ # prim's algorithm for minimum spanning tree dist: dict[T, int] = {node: maxsize for node in graph.connections} - parent: dict[T, Optional[T]] = {node: None for node in graph.connections} + parent: dict[T, T | None] = {node: None for node in graph.connections} priority_queue: MinPriorityQueue[T] = MinPriorityQueue() for node, weight in dist.items(): diff --git a/graphs/page_rank.py b/graphs/page_rank.py index 0f5129146..672405b73 100644 --- a/graphs/page_rank.py +++ b/graphs/page_rank.py @@ -43,7 +43,7 @@ def page_rank(nodes, limit=3, d=0.85): print(f"======= Iteration {i + 1} =======") for j, node in enumerate(nodes): ranks[node.name] = (1 - d) + d * sum( - [ranks[ib] / outbounds[ib] for ib in node.inbound] + ranks[ib] / outbounds[ib] for ib in node.inbound ) print(ranks) diff --git a/graphs/scc_kosaraju.py b/graphs/scc_kosaraju.py index 2b3417014..fa182aa2f 100644 --- a/graphs/scc_kosaraju.py +++ b/graphs/scc_kosaraju.py @@ -1,4 +1,4 @@ -from typing import List +from __future__ import annotations def dfs(u): @@ -39,16 +39,16 @@ if __name__ == "__main__": # n - no of nodes, m - no of edges n, m = list(map(int, input().strip().split())) - graph: List[List[int]] = [[] for i in range(n)] # graph - reversedGraph: List[List[int]] = [[] for i in range(n)] # reversed graph + graph: list[list[int]] = [[] for i in range(n)] # graph + reversedGraph: list[list[int]] = [[] for i in range(n)] # reversed graph # input graph data (edges) for i in range(m): u, v = list(map(int, input().strip().split())) graph[u].append(v) reversedGraph[v].append(u) - stack: List[int] = [] - visit: List[bool] = [False] * n - scc: List[int] = [] - component: List[int] = [] + stack: list[int] = [] + visit: list[bool] = [False] * n + scc: list[int] = [] + component: list[int] = [] print(kosaraju()) diff --git a/hashes/luhn.py b/hashes/luhn.py index 81014120d..bb77fd05c 100644 --- a/hashes/luhn.py +++ b/hashes/luhn.py @@ -1,5 +1,5 @@ """ Luhn Algorithm """ -from typing import List +from __future__ import annotations def is_luhn(string: str) -> bool: @@ -17,9 +17,9 @@ def is_luhn(string: str) -> bool: [False, False, False, True, False, False, False, False, False, False] """ check_digit: int - _vector: List[str] = list(string) + _vector: list[str] = list(string) __vector, check_digit = _vector[:-1], int(_vector[-1]) - vector: List[int] = [int(digit) for digit in __vector] + vector: list[int] = [int(digit) for digit in __vector] vector.reverse() for i, digit in enumerate(vector): diff --git a/knapsack/knapsack.py b/knapsack/knapsack.py index 756443ea6..18a36c3bc 100644 --- a/knapsack/knapsack.py +++ b/knapsack/knapsack.py @@ -1,11 +1,10 @@ -from typing import List - """ A naive recursive implementation of 0-1 Knapsack Problem https://en.wikipedia.org/wiki/Knapsack_problem """ +from __future__ import annotations -def knapsack(capacity: int, weights: List[int], values: List[int], counter: int) -> int: +def knapsack(capacity: int, weights: list[int], values: list[int], counter: int) -> int: """ Returns the maximum value that can be put in a knapsack of a capacity cap, whereby each weight w has a specific value val. diff --git a/linear_algebra/src/lib.py b/linear_algebra/src/lib.py index 5e2f82018..74aeb9137 100644 --- a/linear_algebra/src/lib.py +++ b/linear_algebra/src/lib.py @@ -18,11 +18,11 @@ Overview: - function squareZeroMatrix(N) - function randomMatrix(W,H,a,b) """ - +from __future__ import annotations import math import random -from typing import Collection, Optional, Union, overload +from typing import Collection, overload class Vector: @@ -46,7 +46,7 @@ class Vector: TODO: compare-operator """ - def __init__(self, components: Optional[Collection[float]] = None) -> None: + def __init__(self, components: Collection[float] | None = None) -> None: """ input: components or nothing simple constructor for init the vector @@ -97,7 +97,7 @@ class Vector: summe += c ** 2 return math.sqrt(summe) - def __add__(self, other: "Vector") -> "Vector": + def __add__(self, other: Vector) -> Vector: """ input: other vector assumes: other vector has the same size @@ -110,7 +110,7 @@ class Vector: else: raise Exception("must have the same size") - def __sub__(self, other: "Vector") -> "Vector": + def __sub__(self, other: Vector) -> Vector: """ input: other vector assumes: other vector has the same size @@ -124,14 +124,14 @@ class Vector: raise Exception("must have the same size") @overload - def __mul__(self, other: float) -> "Vector": + def __mul__(self, other: float) -> Vector: ... @overload - def __mul__(self, other: "Vector") -> float: + def __mul__(self, other: Vector) -> float: ... - def __mul__(self, other: Union[float, "Vector"]) -> Union[float, "Vector"]: + def __mul__(self, other: float | Vector) -> float | Vector: """ mul implements the scalar multiplication and the dot-product @@ -148,7 +148,7 @@ class Vector: else: # error case raise Exception("invalid operand!") - def copy(self) -> "Vector": + def copy(self) -> Vector: """ copies this vector and returns it. """ @@ -313,14 +313,14 @@ class Matrix: raise Exception("matrix is not square") @overload - def __mul__(self, other: float) -> "Matrix": + def __mul__(self, other: float) -> Matrix: ... @overload def __mul__(self, other: Vector) -> Vector: ... - def __mul__(self, other: Union[float, Vector]) -> Union[Vector, "Matrix"]: + def __mul__(self, other: float | Vector) -> Vector | Matrix: """ implements the matrix-vector multiplication. implements the matrix-scalar multiplication @@ -347,7 +347,7 @@ class Matrix: ] return Matrix(matrix, self.__width, self.__height) - def __add__(self, other: "Matrix") -> "Matrix": + def __add__(self, other: Matrix) -> Matrix: """ implements the matrix-addition. """ @@ -362,7 +362,7 @@ class Matrix: else: raise Exception("matrix must have the same dimension!") - def __sub__(self, other: "Matrix") -> "Matrix": + def __sub__(self, other: Matrix) -> Matrix: """ implements the matrix-subtraction. """ diff --git a/machine_learning/similarity_search.py b/machine_learning/similarity_search.py index af845c910..ec1b9f9e3 100644 --- a/machine_learning/similarity_search.py +++ b/machine_learning/similarity_search.py @@ -7,8 +7,9 @@ returns a list containing two data for each vector: 1. the nearest vector 2. distance between the vector and the nearest vector (float) """ +from __future__ import annotations + import math -from typing import List, Union import numpy as np @@ -33,7 +34,7 @@ def euclidean(input_a: np.ndarray, input_b: np.ndarray) -> float: def similarity_search( dataset: np.ndarray, value_array: np.ndarray -) -> List[List[Union[List[float], float]]]: +) -> list[list[list[float] | float]]: """ :param dataset: Set containing the vectors. Should be ndarray. :param value_array: vector/vectors we want to know the nearest vector from dataset. diff --git a/maths/area_under_curve.py b/maths/area_under_curve.py index 2d01e414b..ce0932426 100644 --- a/maths/area_under_curve.py +++ b/maths/area_under_curve.py @@ -1,14 +1,15 @@ """ Approximates the area under the curve using the trapezoidal rule """ +from __future__ import annotations -from typing import Callable, Union +from typing import Callable def trapezoidal_area( - fnc: Callable[[Union[int, float]], Union[int, float]], - x_start: Union[int, float], - x_end: Union[int, float], + fnc: Callable[[int | float], int | float], + x_start: int | float, + x_end: int | float, steps: int = 100, ) -> float: """ diff --git a/maths/average_mean.py b/maths/average_mean.py index e02e307f2..274c434ab 100644 --- a/maths/average_mean.py +++ b/maths/average_mean.py @@ -1,7 +1,7 @@ -from typing import List +from __future__ import annotations -def mean(nums: List) -> float: +def mean(nums: list) -> float: """ Find mean of a list of numbers. Wiki: https://en.wikipedia.org/wiki/Mean diff --git a/maths/average_median.py b/maths/average_median.py index 497bf0c3a..cd1ec1574 100644 --- a/maths/average_median.py +++ b/maths/average_median.py @@ -1,7 +1,7 @@ -from typing import Union +from __future__ import annotations -def median(nums: list) -> Union[int, float]: +def median(nums: list) -> int | float: """ Find median of a list of numbers. Wiki: https://en.wikipedia.org/wiki/Median diff --git a/maths/entropy.py b/maths/entropy.py index 43bb3860f..498c28f31 100644 --- a/maths/entropy.py +++ b/maths/entropy.py @@ -68,7 +68,7 @@ def calculate_prob(text: str) -> None: my_fir_sum += prob * math.log2(prob) # entropy formula. # print entropy - print("{:.1f}".format(round(-1 * my_fir_sum))) + print(f"{round(-1 * my_fir_sum):.1f}") # two len string all_sum = sum(two_char_strings.values()) @@ -83,10 +83,10 @@ def calculate_prob(text: str) -> None: my_sec_sum += prob * math.log2(prob) # print second entropy - print("{:.1f}".format(round(-1 * my_sec_sum))) + print(f"{round(-1 * my_sec_sum):.1f}") # print the difference between them - print("{:.1f}".format(round((-1 * my_sec_sum) - (-1 * my_fir_sum)))) + print(f"{round((-1 * my_sec_sum) - (-1 * my_fir_sum)):.1f}") def analyze_text(text: str) -> tuple[dict, dict]: diff --git a/maths/euclidean_distance.py b/maths/euclidean_distance.py index 6e0da6370..a20781613 100644 --- a/maths/euclidean_distance.py +++ b/maths/euclidean_distance.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import Iterable, Union import numpy as np diff --git a/maths/extended_euclidean_algorithm.py b/maths/extended_euclidean_algorithm.py index e7087636c..72afd40aa 100644 --- a/maths/extended_euclidean_algorithm.py +++ b/maths/extended_euclidean_algorithm.py @@ -12,12 +12,12 @@ https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm # @Email: silentcat@protonmail.com # @Last modified by: pikulet # @Last modified time: 2020-10-02 +from __future__ import annotations import sys -from typing import Tuple -def extended_euclidean_algorithm(a: int, b: int) -> Tuple[int, int]: +def extended_euclidean_algorithm(a: int, b: int) -> tuple[int, int]: """ Extended Euclidean Algorithm. diff --git a/maths/hardy_ramanujanalgo.py b/maths/hardy_ramanujanalgo.py index 90e4913c7..e36f763da 100644 --- a/maths/hardy_ramanujanalgo.py +++ b/maths/hardy_ramanujanalgo.py @@ -37,7 +37,7 @@ def exactPrimeFactorCount(n): if __name__ == "__main__": n = 51242183 print(f"The number of distinct prime factors is/are {exactPrimeFactorCount(n)}") - print("The value of log(log(n)) is {:.4f}".format(math.log(math.log(n)))) + print(f"The value of log(log(n)) is {math.log(math.log(n)):.4f}") """ The number of distinct prime factors is/are 3 diff --git a/maths/line_length.py b/maths/line_length.py index 1d386b44b..c4d986279 100644 --- a/maths/line_length.py +++ b/maths/line_length.py @@ -1,11 +1,13 @@ +from __future__ import annotations + import math -from typing import Callable, Union +from typing import Callable def line_length( - fnc: Callable[[Union[int, float]], Union[int, float]], - x_start: Union[int, float], - x_end: Union[int, float], + fnc: Callable[[int | float], int | float], + x_start: int | float, + x_end: int | float, steps: int = 100, ) -> float: diff --git a/maths/max_sum_sliding_window.py b/maths/max_sum_sliding_window.py index 593cb5c8b..c6f9b4ed0 100644 --- a/maths/max_sum_sliding_window.py +++ b/maths/max_sum_sliding_window.py @@ -6,10 +6,10 @@ Instead of using a nested for loop, in a Brute force approach we will use a tech called 'Window sliding technique' where the nested loops can be converted to a single loop to reduce time complexity. """ -from typing import List +from __future__ import annotations -def max_sum_in_array(array: List[int], k: int) -> int: +def max_sum_in_array(array: list[int], k: int) -> int: """ Returns the maximum sum of k consecutive elements >>> arr = [1, 4, 2, 10, 2, 3, 1, 0, 20] diff --git a/maths/median_of_two_arrays.py b/maths/median_of_two_arrays.py index cde12f5d7..55aa587a9 100644 --- a/maths/median_of_two_arrays.py +++ b/maths/median_of_two_arrays.py @@ -1,7 +1,7 @@ -from typing import List +from __future__ import annotations -def median_of_two_arrays(nums1: List[float], nums2: List[float]) -> float: +def median_of_two_arrays(nums1: list[float], nums2: list[float]) -> float: """ >>> median_of_two_arrays([1, 2], [3]) 2 diff --git a/maths/numerical_integration.py b/maths/numerical_integration.py index 87184a76b..577c41a44 100644 --- a/maths/numerical_integration.py +++ b/maths/numerical_integration.py @@ -1,14 +1,15 @@ """ Approximates the area under the curve using the trapezoidal rule """ +from __future__ import annotations -from typing import Callable, Union +from typing import Callable def trapezoidal_area( - fnc: Callable[[Union[int, float]], Union[int, float]], - x_start: Union[int, float], - x_end: Union[int, float], + fnc: Callable[[int | float], int | float], + x_start: int | float, + x_end: int | float, steps: int = 100, ) -> float: diff --git a/maths/sieve_of_eratosthenes.py b/maths/sieve_of_eratosthenes.py index 47a086546..3cd6ce0b4 100644 --- a/maths/sieve_of_eratosthenes.py +++ b/maths/sieve_of_eratosthenes.py @@ -10,13 +10,12 @@ Reference: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes doctest provider: Bruno Simas Hadlich (https://github.com/brunohadlich) Also thanks to Dmitry (https://github.com/LizardWizzard) for finding the problem """ - +from __future__ import annotations import math -from typing import List -def prime_sieve(num: int) -> List[int]: +def prime_sieve(num: int) -> list[int]: """ Returns a list with all prime numbers up to n. diff --git a/maths/volume.py b/maths/volume.py index 41d2331db..51b2b9fc0 100644 --- a/maths/volume.py +++ b/maths/volume.py @@ -3,11 +3,12 @@ Find Volumes of Various Shapes. Wikipedia reference: https://en.wikipedia.org/wiki/Volume """ +from __future__ import annotations + from math import pi, pow -from typing import Union -def vol_cube(side_length: Union[int, float]) -> float: +def vol_cube(side_length: int | float) -> float: """ Calculate the Volume of a Cube. diff --git a/matrix/searching_in_sorted_matrix.py b/matrix/searching_in_sorted_matrix.py index ca6263a32..ae8136149 100644 --- a/matrix/searching_in_sorted_matrix.py +++ b/matrix/searching_in_sorted_matrix.py @@ -1,10 +1,8 @@ from __future__ import annotations -from typing import Union - def search_in_a_sorted_matrix( - mat: list[list], m: int, n: int, key: Union[int, float] + mat: list[list], m: int, n: int, key: int | float ) -> None: """ >>> search_in_a_sorted_matrix( diff --git a/other/date_to_weekday.py b/other/date_to_weekday.py index bb17130c0..9dc68666e 100644 --- a/other/date_to_weekday.py +++ b/other/date_to_weekday.py @@ -14,7 +14,7 @@ def date_to_weekday(inp_date: str) -> str: >>> date_to_weekday("1/1/2021") 'Friday' """ - day, month, year = [int(x) for x in inp_date.split("/")] + day, month, year = (int(x) for x in inp_date.split("/")) if year % 100 == 0: year = "00" new_base_date: str = f"{day}/{month}/{year%100} 0:0:0" diff --git a/other/davis–putnam–logemann–loveland.py b/other/davisb_putnamb_logemannb_loveland.py similarity index 94% rename from other/davis–putnam–logemann–loveland.py rename to other/davisb_putnamb_logemannb_loveland.py index d16de6dd9..00068930b 100644 --- a/other/davis–putnam–logemann–loveland.py +++ b/other/davisb_putnamb_logemannb_loveland.py @@ -8,9 +8,9 @@ conjunctive normal form, i.e, for solving the Conjunctive Normal Form SATisfiabi For more information about the algorithm: https://en.wikipedia.org/wiki/DPLL_algorithm """ +from __future__ import annotations import random -from typing import Dict, List class Clause: @@ -27,7 +27,7 @@ class Clause: True """ - def __init__(self, literals: List[int]) -> None: + def __init__(self, literals: list[int]) -> None: """ Represent the literals and an assignment in a clause." """ @@ -52,7 +52,7 @@ class Clause: """ return len(self.literals) - def assign(self, model: Dict[str, bool]) -> None: + def assign(self, model: dict[str, bool]) -> None: """ Assign values to literals of the clause as given by model. """ @@ -68,7 +68,7 @@ class Clause: value = not value self.literals[literal] = value - def evaluate(self, model: Dict[str, bool]) -> bool: + def evaluate(self, model: dict[str, bool]) -> bool: """ Evaluates the clause with the assignments in model. This has the following steps: @@ -97,7 +97,7 @@ class Formula: {{A1, A2, A3'}, {A5', A2', A1}} is ((A1 v A2 v A3') and (A5' v A2' v A1)) """ - def __init__(self, clauses: List[Clause]) -> None: + def __init__(self, clauses: list[Clause]) -> None: """ Represent the number of clauses and the clauses themselves. """ @@ -146,7 +146,7 @@ def generate_formula() -> Formula: return Formula(set(clauses)) -def generate_parameters(formula: Formula) -> (List[Clause], List[str]): +def generate_parameters(formula: Formula) -> (list[Clause], list[str]): """ Return the clauses and symbols from a formula. A symbol is the uncomplemented form of a literal. @@ -173,8 +173,8 @@ def generate_parameters(formula: Formula) -> (List[Clause], List[str]): def find_pure_symbols( - clauses: List[Clause], symbols: List[str], model: Dict[str, bool] -) -> (List[str], Dict[str, bool]): + clauses: list[Clause], symbols: list[str], model: dict[str, bool] +) -> (list[str], dict[str, bool]): """ Return pure symbols and their values to satisfy clause. Pure symbols are symbols in a formula that exist only @@ -225,8 +225,8 @@ def find_pure_symbols( def find_unit_clauses( - clauses: List[Clause], model: Dict[str, bool] -) -> (List[str], Dict[str, bool]): + clauses: list[Clause], model: dict[str, bool] +) -> (list[str], dict[str, bool]): """ Returns the unit symbols and their values to satisfy clause. Unit symbols are symbols in a formula that are: @@ -273,8 +273,8 @@ def find_unit_clauses( def dpll_algorithm( - clauses: List[Clause], symbols: List[str], model: Dict[str, bool] -) -> (bool, Dict[str, bool]): + clauses: list[Clause], symbols: list[str], model: dict[str, bool] +) -> (bool, dict[str, bool]): """ Returns the model if the formula is satisfiable, else None This has the following steps: diff --git a/other/lfu_cache.py b/other/lfu_cache.py index 40268242f..88167ac1f 100644 --- a/other/lfu_cache.py +++ b/other/lfu_cache.py @@ -1,4 +1,6 @@ -from typing import Callable, Optional +from __future__ import annotations + +from typing import Callable class DoubleLinkedListNode: @@ -119,7 +121,7 @@ class LFUCache: """ return key in self.cache - def get(self, key: int) -> Optional[int]: + def get(self, key: int) -> int | None: """ Returns the value for the input key and updates the Double Linked List. Returns None if key is not present in cache diff --git a/other/lru_cache.py b/other/lru_cache.py index 2a9d7e49b..b74c0a45c 100644 --- a/other/lru_cache.py +++ b/other/lru_cache.py @@ -1,4 +1,6 @@ -from typing import Callable, Optional +from __future__ import annotations + +from typing import Callable class DoubleLinkedListNode: @@ -125,7 +127,7 @@ class LRUCache: return key in self.cache - def get(self, key: int) -> Optional[int]: + def get(self, key: int) -> int | None: """ Returns the value for the input key and updates the Double Linked List. Returns None if key is not present in cache diff --git a/project_euler/problem_001/sol1.py b/project_euler/problem_001/sol1.py index 85ad32294..fcc24c86e 100644 --- a/project_euler/problem_001/sol1.py +++ b/project_euler/problem_001/sol1.py @@ -26,7 +26,7 @@ def solution(n: int = 1000) -> int: 0 """ - return sum([e for e in range(3, n) if e % 3 == 0 or e % 5 == 0]) + return sum(e for e in range(3, n) if e % 3 == 0 or e % 5 == 0) if __name__ == "__main__": diff --git a/project_euler/problem_001/sol5.py b/project_euler/problem_001/sol5.py index 7f0b0bd1b..3edc6f245 100644 --- a/project_euler/problem_001/sol5.py +++ b/project_euler/problem_001/sol5.py @@ -25,7 +25,7 @@ def solution(n: int = 1000) -> int: 83700 """ - return sum([i for i in range(n) if i % 3 == 0 or i % 5 == 0]) + return sum(i for i in range(n) if i % 3 == 0 or i % 5 == 0) if __name__ == "__main__": diff --git a/project_euler/problem_006/sol3.py b/project_euler/problem_006/sol3.py index c87931309..529f233c9 100644 --- a/project_euler/problem_006/sol3.py +++ b/project_euler/problem_006/sol3.py @@ -33,7 +33,7 @@ def solution(n: int = 100) -> int: 1582700 """ - sum_of_squares = sum([i * i for i in range(1, n + 1)]) + sum_of_squares = sum(i * i for i in range(1, n + 1)) square_of_sum = int(math.pow(sum(range(1, n + 1)), 2)) return square_of_sum - sum_of_squares diff --git a/project_euler/problem_008/sol2.py b/project_euler/problem_008/sol2.py index d2c1b4f7c..7f0540263 100644 --- a/project_euler/problem_008/sol2.py +++ b/project_euler/problem_008/sol2.py @@ -70,10 +70,7 @@ def solution(n: str = N) -> int: """ return max( - [ - reduce(lambda x, y: int(x) * int(y), n[i : i + 13]) - for i in range(len(n) - 12) - ] + reduce(lambda x, y: int(x) * int(y), n[i : i + 13]) for i in range(len(n) - 12) ) diff --git a/project_euler/problem_012/sol2.py b/project_euler/problem_012/sol2.py index 5ff0d8349..7578caa98 100644 --- a/project_euler/problem_012/sol2.py +++ b/project_euler/problem_012/sol2.py @@ -29,7 +29,7 @@ def triangle_number_generator(): def count_divisors(n): - return sum([2 for i in range(1, int(n ** 0.5) + 1) if n % i == 0 and i * i != n]) + return sum(2 for i in range(1, int(n ** 0.5) + 1) if n % i == 0 and i * i != n) def solution(): diff --git a/project_euler/problem_013/sol1.py b/project_euler/problem_013/sol1.py index 1ea08b12e..7a414a937 100644 --- a/project_euler/problem_013/sol1.py +++ b/project_euler/problem_013/sol1.py @@ -18,7 +18,7 @@ def solution(): """ file_path = os.path.join(os.path.dirname(__file__), "num.txt") with open(file_path) as file_hand: - return str(sum([int(line) for line in file_hand]))[:10] + return str(sum(int(line) for line in file_hand))[:10] if __name__ == "__main__": diff --git a/project_euler/problem_014/sol2.py b/project_euler/problem_014/sol2.py index 20ad96327..7ed68273b 100644 --- a/project_euler/problem_014/sol2.py +++ b/project_euler/problem_014/sol2.py @@ -25,10 +25,10 @@ that all starting numbers finish at 1. Which starting number, under one million, produces the longest chain? """ -from typing import List +from __future__ import annotations -def collatz_sequence(n: int) -> List[int]: +def collatz_sequence(n: int) -> list[int]: """Returns the Collatz sequence for n.""" sequence = [n] while n != 1: @@ -54,7 +54,7 @@ def solution(n: int = 1000000) -> int: 13255 """ - result = max([(len(collatz_sequence(i)), i) for i in range(1, n)]) + result = max((len(collatz_sequence(i)), i) for i in range(1, n)) return result[1] diff --git a/project_euler/problem_020/sol2.py b/project_euler/problem_020/sol2.py index 92e1e724a..676e96e78 100644 --- a/project_euler/problem_020/sol2.py +++ b/project_euler/problem_020/sol2.py @@ -28,7 +28,7 @@ def solution(num: int = 100) -> int: >>> solution(1) 1 """ - return sum([int(x) for x in str(factorial(num))]) + return sum(int(x) for x in str(factorial(num))) if __name__ == "__main__": diff --git a/project_euler/problem_021/sol1.py b/project_euler/problem_021/sol1.py index 3fac79156..353510ae8 100644 --- a/project_euler/problem_021/sol1.py +++ b/project_euler/problem_021/sol1.py @@ -41,11 +41,9 @@ def solution(n: int = 10000) -> int: 0 """ total = sum( - [ - i - for i in range(1, n) - if sum_of_divisors(sum_of_divisors(i)) == i and sum_of_divisors(i) != i - ] + i + for i in range(1, n) + if sum_of_divisors(sum_of_divisors(i)) == i and sum_of_divisors(i) != i ) return total diff --git a/project_euler/problem_033/sol1.py b/project_euler/problem_033/sol1.py index ba6e553d8..e0c9a058a 100644 --- a/project_euler/problem_033/sol1.py +++ b/project_euler/problem_033/sol1.py @@ -14,8 +14,9 @@ and denominator. If the product of these four fractions is given in its lowest common terms, find the value of the denominator. """ +from __future__ import annotations + from fractions import Fraction -from typing import List def is_digit_cancelling(num: int, den: int) -> bool: @@ -26,7 +27,7 @@ def is_digit_cancelling(num: int, den: int) -> bool: return False -def fraction_list(digit_len: int) -> List[str]: +def fraction_list(digit_len: int) -> list[str]: """ >>> fraction_list(2) ['16/64', '19/95', '26/65', '49/98'] diff --git a/project_euler/problem_036/sol1.py b/project_euler/problem_036/sol1.py index 13a749862..425c41221 100644 --- a/project_euler/problem_036/sol1.py +++ b/project_euler/problem_036/sol1.py @@ -14,11 +14,10 @@ base 10 and base 2. (Please note that the palindromic number, in either base, may not include leading zeros.) """ - -from typing import Union +from __future__ import annotations -def is_palindrome(n: Union[int, str]) -> bool: +def is_palindrome(n: int | str) -> bool: """ Return true if the input n is a palindrome. Otherwise return false. n can be an integer or a string. diff --git a/project_euler/problem_038/sol1.py b/project_euler/problem_038/sol1.py index 6d54f6df7..e4a6d09f8 100644 --- a/project_euler/problem_038/sol1.py +++ b/project_euler/problem_038/sol1.py @@ -37,8 +37,7 @@ a has 3 digits, etc... => 100 <= a < 334, candidate = a * 10^6 + 2a * 10^3 + 3a = 1002003 * a """ - -from typing import Union +from __future__ import annotations def is_9_pandigital(n: int) -> bool: @@ -55,7 +54,7 @@ def is_9_pandigital(n: int) -> bool: return len(s) == 9 and set(s) == set("123456789") -def solution() -> Union[int, None]: +def solution() -> int | None: """ Return the largest 1 to 9 pandigital 9-digital number that can be formed as the concatenated product of an integer with (1,2,...,n) where n > 1. diff --git a/project_euler/problem_049/sol1.py b/project_euler/problem_049/sol1.py index c0d0715be..dd2ef71a3 100644 --- a/project_euler/problem_049/sol1.py +++ b/project_euler/problem_049/sol1.py @@ -132,7 +132,7 @@ def solution(): for seq in passed: answer.add("".join([str(i) for i in seq])) - return max([int(x) for x in answer]) + return max(int(x) for x in answer) if __name__ == "__main__": diff --git a/project_euler/problem_050/sol1.py b/project_euler/problem_050/sol1.py index 7d142e5ff..cfb1911df 100644 --- a/project_euler/problem_050/sol1.py +++ b/project_euler/problem_050/sol1.py @@ -15,10 +15,10 @@ contains 21 terms, and is equal to 953. Which prime, below one-million, can be written as the sum of the most consecutive primes? """ -from typing import List +from __future__ import annotations -def prime_sieve(limit: int) -> List[int]: +def prime_sieve(limit: int) -> list[int]: """ Sieve of Erotosthenes Function to return all the prime numbers up to a number 'limit' diff --git a/project_euler/problem_051/sol1.py b/project_euler/problem_051/sol1.py index b160b5a2d..5f607e3ff 100644 --- a/project_euler/problem_051/sol1.py +++ b/project_euler/problem_051/sol1.py @@ -15,12 +15,12 @@ with this property. Find the smallest prime which, by replacing part of the number (not necessarily adjacent digits) with the same digit, is part of an eight prime value family. """ +from __future__ import annotations from collections import Counter -from typing import List -def prime_sieve(n: int) -> List[int]: +def prime_sieve(n: int) -> list[int]: """ Sieve of Erotosthenes Function to return all the prime numbers up to a certain number @@ -52,7 +52,7 @@ def prime_sieve(n: int) -> List[int]: return primes -def digit_replacements(number: int) -> List[List[int]]: +def digit_replacements(number: int) -> list[list[int]]: """ Returns all the possible families of digit replacements in a number which contains at least one repeating digit diff --git a/project_euler/problem_054/sol1.py b/project_euler/problem_054/sol1.py index d2fd810d1..9af7aef5a 100644 --- a/project_euler/problem_054/sol1.py +++ b/project_euler/problem_054/sol1.py @@ -135,7 +135,7 @@ class PokerHand: """Returns the self hand""" return self._hand - def compare_with(self, other: "PokerHand") -> str: + def compare_with(self, other: PokerHand) -> str: """ Determines the outcome of comparing self hand with other hand. Returns the output as 'Win', 'Loss', 'Tie' according to the rules of @@ -220,7 +220,7 @@ class PokerHand: else: return name + f", {high}" - def _compare_cards(self, other: "PokerHand") -> str: + def _compare_cards(self, other: PokerHand) -> str: # Enumerate gives us the index as well as the element of a list for index, card_value in enumerate(self._card_values): if card_value != other._card_values[index]: diff --git a/project_euler/problem_056/sol1.py b/project_euler/problem_056/sol1.py index 8eaa6e553..f1ec03c49 100644 --- a/project_euler/problem_056/sol1.py +++ b/project_euler/problem_056/sol1.py @@ -30,11 +30,9 @@ def solution(a: int = 100, b: int = 100) -> int: # RETURN the MAXIMUM from the list of SUMs of the list of INT converted from STR of # BASE raised to the POWER return max( - [ - sum([int(x) for x in str(base ** power)]) - for base in range(a) - for power in range(b) - ] + sum(int(x) for x in str(base ** power)) + for base in range(a) + for power in range(b) ) diff --git a/project_euler/problem_059/sol1.py b/project_euler/problem_059/sol1.py index 1f55029b2..b795dd243 100644 --- a/project_euler/problem_059/sol1.py +++ b/project_euler/problem_059/sol1.py @@ -25,23 +25,22 @@ file containing the encrypted ASCII codes, and the knowledge that the plain text must contain common English words, decrypt the message and find the sum of the ASCII values in the original text. """ - +from __future__ import annotations import string from itertools import cycle, product from pathlib import Path -from typing import List, Optional, Set, Tuple VALID_CHARS: str = ( string.ascii_letters + string.digits + string.punctuation + string.whitespace ) -LOWERCASE_INTS: List[int] = [ord(letter) for letter in string.ascii_lowercase] -VALID_INTS: Set[int] = {ord(char) for char in VALID_CHARS} +LOWERCASE_INTS: list[int] = [ord(letter) for letter in string.ascii_lowercase] +VALID_INTS: set[int] = {ord(char) for char in VALID_CHARS} -COMMON_WORDS: List[str] = ["the", "be", "to", "of", "and", "in", "that", "have"] +COMMON_WORDS: list[str] = ["the", "be", "to", "of", "and", "in", "that", "have"] -def try_key(ciphertext: List[int], key: Tuple[int, ...]) -> Optional[str]: +def try_key(ciphertext: list[int], key: tuple[int, ...]) -> str | None: """ Given an encrypted message and a possible 3-character key, decrypt the message. If the decrypted message contains a invalid character, i.e. not an ASCII letter, @@ -66,7 +65,7 @@ def try_key(ciphertext: List[int], key: Tuple[int, ...]) -> Optional[str]: return decoded -def filter_valid_chars(ciphertext: List[int]) -> List[str]: +def filter_valid_chars(ciphertext: list[int]) -> list[str]: """ Given an encrypted message, test all 3-character strings to try and find the key. Return a list of the possible decrypted messages. @@ -77,7 +76,7 @@ def filter_valid_chars(ciphertext: List[int]) -> List[str]: >>> text in filter_valid_chars(encoded) True """ - possibles: List[str] = [] + possibles: list[str] = [] for key in product(LOWERCASE_INTS, repeat=3): encoded = try_key(ciphertext, key) if encoded is not None: @@ -85,7 +84,7 @@ def filter_valid_chars(ciphertext: List[int]) -> List[str]: return possibles -def filter_common_word(possibles: List[str], common_word: str) -> List[str]: +def filter_common_word(possibles: list[str], common_word: str) -> list[str]: """ Given a list of possible decoded messages, narrow down the possibilities for checking for the presence of a specified common word. Only decoded messages @@ -106,8 +105,8 @@ def solution(filename: str = "p059_cipher.txt") -> int: >>> solution("test_cipher.txt") 3000 """ - ciphertext: List[int] - possibles: List[str] + ciphertext: list[int] + possibles: list[str] common_word: str decoded_text: str data: str = Path(__file__).parent.joinpath(filename).read_text(encoding="utf-8") @@ -121,7 +120,7 @@ def solution(filename: str = "p059_cipher.txt") -> int: break decoded_text = possibles[0] - return sum([ord(char) for char in decoded_text]) + return sum(ord(char) for char in decoded_text) if __name__ == "__main__": diff --git a/project_euler/problem_070/sol1.py b/project_euler/problem_070/sol1.py index 9d27119ba..e106800d5 100644 --- a/project_euler/problem_070/sol1.py +++ b/project_euler/problem_070/sol1.py @@ -28,10 +28,10 @@ References: Finding totients https://en.wikipedia.org/wiki/Euler's_totient_function#Euler's_product_formula """ -from typing import List +from __future__ import annotations -def get_totients(max_one: int) -> List[int]: +def get_totients(max_one: int) -> list[int]: """ Calculates a list of totients from 0 to max_one exclusive, using the definition of Euler's product formula. diff --git a/project_euler/problem_074/sol1.py b/project_euler/problem_074/sol1.py index 38d4e1439..a40a62903 100644 --- a/project_euler/problem_074/sol1.py +++ b/project_euler/problem_074/sol1.py @@ -66,7 +66,7 @@ def sum_digit_factorials(n: int) -> int: """ if n in CACHE_SUM_DIGIT_FACTORIALS: return CACHE_SUM_DIGIT_FACTORIALS[n] - ret = sum([DIGIT_FACTORIALS[let] for let in str(n)]) + ret = sum(DIGIT_FACTORIALS[let] for let in str(n)) CACHE_SUM_DIGIT_FACTORIALS[n] = ret return ret diff --git a/project_euler/problem_077/sol1.py b/project_euler/problem_077/sol1.py index e92992a90..214e25879 100644 --- a/project_euler/problem_077/sol1.py +++ b/project_euler/problem_077/sol1.py @@ -12,10 +12,10 @@ It is possible to write ten as the sum of primes in exactly five different ways: What is the first value which can be written as the sum of primes in over five thousand different ways? """ +from __future__ import annotations from functools import lru_cache from math import ceil -from typing import Optional, Set NUM_PRIMES = 100 @@ -30,7 +30,7 @@ for prime in range(3, ceil(NUM_PRIMES ** 0.5), 2): @lru_cache(maxsize=100) -def partition(number_to_partition: int) -> Set[int]: +def partition(number_to_partition: int) -> set[int]: """ Return a set of integers corresponding to unique prime partitions of n. The unique prime partitions can be represented as unique prime decompositions, @@ -47,7 +47,7 @@ def partition(number_to_partition: int) -> Set[int]: elif number_to_partition == 0: return {1} - ret: Set[int] = set() + ret: set[int] = set() prime: int sub: int @@ -60,7 +60,7 @@ def partition(number_to_partition: int) -> Set[int]: return ret -def solution(number_unique_partitions: int = 5000) -> Optional[int]: +def solution(number_unique_partitions: int = 5000) -> int | None: """ Return the smallest integer that can be written as the sum of primes in over m unique ways. diff --git a/project_euler/problem_080/sol1.py b/project_euler/problem_080/sol1.py index db69d7e84..517be3fc0 100644 --- a/project_euler/problem_080/sol1.py +++ b/project_euler/problem_080/sol1.py @@ -27,7 +27,7 @@ def solution() -> int: if len(str(sqrt_number)) > 1: answer += int(str(sqrt_number)[0]) sqrt_number = str(sqrt_number)[2:101] - answer += sum([int(x) for x in sqrt_number]) + answer += sum(int(x) for x in sqrt_number) return answer diff --git a/project_euler/problem_081/sol1.py b/project_euler/problem_081/sol1.py index afa143f23..aef6106b5 100644 --- a/project_euler/problem_081/sol1.py +++ b/project_euler/problem_081/sol1.py @@ -22,7 +22,7 @@ def solution(filename: str = "matrix.txt") -> int: >>> solution() 427337 """ - with open(os.path.join(os.path.dirname(__file__), filename), "r") as in_file: + with open(os.path.join(os.path.dirname(__file__), filename)) as in_file: data = in_file.read() grid = [[int(cell) for cell in row.split(",")] for row in data.strip().splitlines()] diff --git a/project_euler/problem_085/sol1.py b/project_euler/problem_085/sol1.py index 74e36b130..d0f297964 100644 --- a/project_euler/problem_085/sol1.py +++ b/project_euler/problem_085/sol1.py @@ -44,10 +44,9 @@ Solution: Reference: https://en.wikipedia.org/wiki/Triangular_number https://en.wikipedia.org/wiki/Quadratic_formula """ - +from __future__ import annotations from math import ceil, floor, sqrt -from typing import List def solution(target: int = 2000000) -> int: @@ -61,7 +60,7 @@ def solution(target: int = 2000000) -> int: >>> solution(2000000000) 86595 """ - triangle_numbers: List[int] = [0] + triangle_numbers: list[int] = [0] idx: int for idx in range(1, ceil(sqrt(target * 2) * 1.1)): diff --git a/project_euler/problem_089/sol1.py b/project_euler/problem_089/sol1.py index 11582aa4a..1c4e2600f 100644 --- a/project_euler/problem_089/sol1.py +++ b/project_euler/problem_089/sol1.py @@ -125,7 +125,7 @@ def solution(roman_numerals_filename: str = "/p089_roman.txt") -> int: savings = 0 - file1 = open(os.path.dirname(__file__) + roman_numerals_filename, "r") + file1 = open(os.path.dirname(__file__) + roman_numerals_filename) lines = file1.readlines() for line in lines: original = line.strip() diff --git a/project_euler/problem_101/sol1.py b/project_euler/problem_101/sol1.py index e66316090..553f8f442 100644 --- a/project_euler/problem_101/sol1.py +++ b/project_euler/problem_101/sol1.py @@ -41,11 +41,11 @@ Consider the following tenth degree polynomial generating function: Find the sum of FITs for the BOPs. """ +from __future__ import annotations +from typing import Callable, Union -from typing import Callable, List, Union - -Matrix = List[List[Union[float, int]]] +Matrix = list[list[Union[float, int]]] def solve(matrix: Matrix, vector: Matrix) -> Matrix: @@ -78,9 +78,9 @@ def solve(matrix: Matrix, vector: Matrix) -> Matrix: col = 0 while row < size and col < size: # pivoting - pivot_row = max( - [(abs(augmented[row2][col]), row2) for row2 in range(col, size)] - )[1] + pivot_row = max((abs(augmented[row2][col]), row2) for row2 in range(col, size))[ + 1 + ] if augmented[pivot_row][col] == 0: col += 1 continue @@ -109,7 +109,7 @@ def solve(matrix: Matrix, vector: Matrix) -> Matrix: ] -def interpolate(y_list: List[int]) -> Callable[[int], int]: +def interpolate(y_list: list[int]) -> Callable[[int], int]: """ Given a list of data points (1,y0),(2,y1), ..., return a function that interpolates the data points. We find the coefficients of the interpolating @@ -195,9 +195,9 @@ def solution(func: Callable[[int], int] = question_function, order: int = 10) -> >>> solution(lambda n: n ** 3, 3) 74 """ - data_points: List[int] = [func(x_val) for x_val in range(1, order + 1)] + data_points: list[int] = [func(x_val) for x_val in range(1, order + 1)] - polynomials: List[Callable[[int], int]] = [ + polynomials: list[Callable[[int], int]] = [ interpolate(data_points[:max_coeff]) for max_coeff in range(1, order + 1) ] diff --git a/project_euler/problem_102/sol1.py b/project_euler/problem_102/sol1.py index 00af72665..4f6e6361e 100644 --- a/project_euler/problem_102/sol1.py +++ b/project_euler/problem_102/sol1.py @@ -18,12 +18,12 @@ the number of triangles for which the interior contains the origin. NOTE: The first two examples in the file represent the triangles in the example given above. """ +from __future__ import annotations from pathlib import Path -from typing import List, Tuple -def vector_product(point1: Tuple[int, int], point2: Tuple[int, int]) -> int: +def vector_product(point1: tuple[int, int], point2: tuple[int, int]) -> int: """ Return the 2-d vector product of two vectors. >>> vector_product((1, 2), (-5, 0)) @@ -43,9 +43,9 @@ def contains_origin(x1: int, y1: int, x2: int, y2: int, x3: int, y3: int) -> boo >>> contains_origin(-175, 41, -421, -714, 574, -645) False """ - point_a: Tuple[int, int] = (x1, y1) - point_a_to_b: Tuple[int, int] = (x2 - x1, y2 - y1) - point_a_to_c: Tuple[int, int] = (x3 - x1, y3 - y1) + point_a: tuple[int, int] = (x1, y1) + point_a_to_b: tuple[int, int] = (x2 - x1, y2 - y1) + point_a_to_c: tuple[int, int] = (x3 - x1, y3 - y1) a: float = -vector_product(point_a, point_a_to_b) / vector_product( point_a_to_c, point_a_to_b ) @@ -64,12 +64,12 @@ def solution(filename: str = "p102_triangles.txt") -> int: """ data: str = Path(__file__).parent.joinpath(filename).read_text(encoding="utf-8") - triangles: List[List[int]] = [] + triangles: list[list[int]] = [] for line in data.strip().split("\n"): triangles.append([int(number) for number in line.split(",")]) ret: int = 0 - triangle: List[int] + triangle: list[int] for triangle in triangles: ret += contains_origin(*triangle) diff --git a/project_euler/problem_107/sol1.py b/project_euler/problem_107/sol1.py index 80a10e499..6a411a114 100644 --- a/project_euler/problem_107/sol1.py +++ b/project_euler/problem_107/sol1.py @@ -27,11 +27,12 @@ Solution: We use Prim's algorithm to find a Minimum Spanning Tree. Reference: https://en.wikipedia.org/wiki/Prim%27s_algorithm """ +from __future__ import annotations import os -from typing import Dict, List, Mapping, Set, Tuple +from typing import Mapping -EdgeT = Tuple[int, int] +EdgeT = tuple[int, int] class Graph: @@ -39,9 +40,9 @@ class Graph: A class representing an undirected weighted graph. """ - def __init__(self, vertices: Set[int], edges: Mapping[EdgeT, int]) -> None: - self.vertices: Set[int] = vertices - self.edges: Dict[EdgeT, int] = { + def __init__(self, vertices: set[int], edges: Mapping[EdgeT, int]) -> None: + self.vertices: set[int] = vertices + self.edges: dict[EdgeT, int] = { (min(edge), max(edge)): weight for edge, weight in edges.items() } @@ -59,7 +60,7 @@ class Graph: self.vertices.add(edge[1]) self.edges[(min(edge), max(edge))] = weight - def prims_algorithm(self) -> "Graph": + def prims_algorithm(self) -> Graph: """ Run Prim's algorithm to find the minimum spanning tree. Reference: https://en.wikipedia.org/wiki/Prim%27s_algorithm @@ -98,13 +99,13 @@ def solution(filename: str = "p107_network.txt") -> int: """ script_dir: str = os.path.abspath(os.path.dirname(__file__)) network_file: str = os.path.join(script_dir, filename) - adjacency_matrix: List[List[str]] - edges: Dict[EdgeT, int] = dict() - data: List[str] + adjacency_matrix: list[list[str]] + edges: dict[EdgeT, int] = dict() + data: list[str] edge1: int edge2: int - with open(network_file, "r") as f: + with open(network_file) as f: data = f.read().strip().split("\n") adjaceny_matrix = [line.split(",") for line in data] diff --git a/project_euler/problem_119/sol1.py b/project_euler/problem_119/sol1.py index 7f343ac24..60ec16cda 100644 --- a/project_euler/problem_119/sol1.py +++ b/project_euler/problem_119/sol1.py @@ -23,7 +23,7 @@ def digit_sum(n: int) -> int: >>> digit_sum(78910) 25 """ - return sum([int(digit) for digit in str(n)]) + return sum(int(digit) for digit in str(n)) def solution(n: int = 30) -> int: diff --git a/project_euler/problem_123/sol1.py b/project_euler/problem_123/sol1.py index 85350c8ba..919132227 100644 --- a/project_euler/problem_123/sol1.py +++ b/project_euler/problem_123/sol1.py @@ -37,8 +37,9 @@ So it could be simplified as, r = 2pn when n is odd r = 2 when n is even. """ +from __future__ import annotations -from typing import Dict, Generator +from typing import Generator def sieve() -> Generator[int, None, None]: @@ -60,7 +61,7 @@ def sieve() -> Generator[int, None, None]: >>> next(primes) 13 """ - factor_map: Dict[int, int] = {} + factor_map: dict[int, int] = {} prime = 2 while True: factor = factor_map.pop(prime, None) diff --git a/project_euler/problem_180/sol1.py b/project_euler/problem_180/sol1.py index 6112db2ea..f7c097323 100644 --- a/project_euler/problem_180/sol1.py +++ b/project_euler/problem_180/sol1.py @@ -44,11 +44,10 @@ we get the right numerator and denominator. Reference: https://en.wikipedia.org/wiki/Fermat%27s_Last_Theorem """ - +from __future__ import annotations from fractions import Fraction from math import gcd, sqrt -from typing import Tuple def is_sq(number: int) -> bool: @@ -68,7 +67,7 @@ def is_sq(number: int) -> bool: def add_three( x_num: int, x_den: int, y_num: int, y_den: int, z_num: int, z_den: int -) -> Tuple[int, int]: +) -> tuple[int, int]: """ Given the numerators and denominators of three fractions, return the numerator and denominator of their sum in lowest form. @@ -100,7 +99,7 @@ def solution(order: int = 35) -> int: unique_s: set = set() hcf: int total: Fraction = Fraction(0) - fraction_sum: Tuple[int, int] + fraction_sum: tuple[int, int] for x_num in range(1, order + 1): for x_den in range(x_num + 1, order + 1): diff --git a/project_euler/problem_203/sol1.py b/project_euler/problem_203/sol1.py index 227b476da..030cf12f2 100644 --- a/project_euler/problem_203/sol1.py +++ b/project_euler/problem_203/sol1.py @@ -27,12 +27,12 @@ Pascal's triangle. References: - https://en.wikipedia.org/wiki/Pascal%27s_triangle """ +from __future__ import annotations import math -from typing import List, Set -def get_pascal_triangle_unique_coefficients(depth: int) -> Set[int]: +def get_pascal_triangle_unique_coefficients(depth: int) -> set[int]: """ Returns the unique coefficients of a Pascal's triangle of depth "depth". @@ -61,7 +61,7 @@ def get_pascal_triangle_unique_coefficients(depth: int) -> Set[int]: return coefficients -def get_primes_squared(max_number: int) -> List[int]: +def get_primes_squared(max_number: int) -> list[int]: """ Calculates all primes between 2 and round(sqrt(max_number)) and returns them squared up. @@ -92,7 +92,7 @@ def get_primes_squared(max_number: int) -> List[int]: def get_squared_primes_to_use( - num_to_look: int, squared_primes: List[int], previous_index: int + num_to_look: int, squared_primes: list[int], previous_index: int ) -> int: """ Returns an int indicating the last index on which squares of primes @@ -128,8 +128,8 @@ def get_squared_primes_to_use( def get_squarefree( - unique_coefficients: Set[int], squared_primes: List[int] -) -> Set[int]: + unique_coefficients: set[int], squared_primes: list[int] +) -> set[int]: """ Calculates the squarefree numbers inside unique_coefficients given a list of square of primes. diff --git a/scheduling/first_come_first_served.py b/scheduling/first_come_first_served.py index b51fc9fe0..c5f61720f 100644 --- a/scheduling/first_come_first_served.py +++ b/scheduling/first_come_first_served.py @@ -2,10 +2,10 @@ # In this Algorithm we just care about the order that the processes arrived # without carring about their duration time # https://en.wikipedia.org/wiki/Scheduling_(computing)#First_come,_first_served -from typing import List +from __future__ import annotations -def calculate_waiting_times(duration_times: List[int]) -> List[int]: +def calculate_waiting_times(duration_times: list[int]) -> list[int]: """ This function calculates the waiting time of some processes that have a specified duration time. @@ -24,8 +24,8 @@ def calculate_waiting_times(duration_times: List[int]) -> List[int]: def calculate_turnaround_times( - duration_times: List[int], waiting_times: List[int] -) -> List[int]: + duration_times: list[int], waiting_times: list[int] +) -> list[int]: """ This function calculates the turnaround time of some processes. Return: The time difference between the completion time and the @@ -44,7 +44,7 @@ def calculate_turnaround_times( ] -def calculate_average_turnaround_time(turnaround_times: List[int]) -> float: +def calculate_average_turnaround_time(turnaround_times: list[int]) -> float: """ This function calculates the average of the turnaround times Return: The average of the turnaround times. @@ -58,7 +58,7 @@ def calculate_average_turnaround_time(turnaround_times: List[int]) -> float: return sum(turnaround_times) / len(turnaround_times) -def calculate_average_waiting_time(waiting_times: List[int]) -> float: +def calculate_average_waiting_time(waiting_times: list[int]) -> float: """ This function calculates the average of the waiting times Return: The average of the waiting times. diff --git a/scheduling/round_robin.py b/scheduling/round_robin.py index 4a79301c1..e8d54dd9a 100644 --- a/scheduling/round_robin.py +++ b/scheduling/round_robin.py @@ -3,11 +3,12 @@ Round Robin is a scheduling algorithm. In Round Robin each process is assigned a fixed time slot in a cyclic way. https://en.wikipedia.org/wiki/Round-robin_scheduling """ +from __future__ import annotations + from statistics import mean -from typing import List -def calculate_waiting_times(burst_times: List[int]) -> List[int]: +def calculate_waiting_times(burst_times: list[int]) -> list[int]: """ Calculate the waiting times of a list of processes that have a specified duration. @@ -40,8 +41,8 @@ def calculate_waiting_times(burst_times: List[int]) -> List[int]: def calculate_turn_around_times( - burst_times: List[int], waiting_times: List[int] -) -> List[int]: + burst_times: list[int], waiting_times: list[int] +) -> list[int]: """ >>> calculate_turn_around_times([1, 2, 3, 4], [0, 1, 3]) [1, 3, 6] diff --git a/scheduling/shortest_job_first.py b/scheduling/shortest_job_first.py index a49d037d6..17409108a 100644 --- a/scheduling/shortest_job_first.py +++ b/scheduling/shortest_job_first.py @@ -3,14 +3,14 @@ Shortest job remaining first Please note arrival time and burst Please use spaces to separate times entered. """ -from typing import List +from __future__ import annotations import pandas as pd def calculate_waitingtime( - arrival_time: List[int], burst_time: List[int], no_of_processes: int -) -> List[int]: + arrival_time: list[int], burst_time: list[int], no_of_processes: int +) -> list[int]: """ Calculate the waiting time of each processes Return: List of waiting times. @@ -72,8 +72,8 @@ def calculate_waitingtime( def calculate_turnaroundtime( - burst_time: List[int], no_of_processes: int, waiting_time: List[int] -) -> List[int]: + burst_time: list[int], no_of_processes: int, waiting_time: list[int] +) -> list[int]: """ Calculate the turn around time of each Processes Return: list of turn around times. @@ -91,7 +91,7 @@ def calculate_turnaroundtime( def calculate_average_times( - waiting_time: List[int], turn_around_time: List[int], no_of_processes: int + waiting_time: list[int], turn_around_time: list[int], no_of_processes: int ) -> None: """ This function calculates the average of the waiting & turnaround times diff --git a/searches/binary_search.py b/searches/binary_search.py index 35e0dd059..0966cd8de 100644 --- a/searches/binary_search.py +++ b/searches/binary_search.py @@ -9,12 +9,13 @@ python3 -m doctest -v binary_search.py For manual testing run: python3 binary_search.py """ +from __future__ import annotations + import bisect -from typing import List, Optional def bisect_left( - sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1 + sorted_collection: list[int], item: int, lo: int = 0, hi: int = -1 ) -> int: """ Locates the first element in a sorted array that is larger or equal to a given @@ -60,7 +61,7 @@ def bisect_left( def bisect_right( - sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1 + sorted_collection: list[int], item: int, lo: int = 0, hi: int = -1 ) -> int: """ Locates the first element in a sorted array that is larger than a given value. @@ -105,7 +106,7 @@ def bisect_right( def insort_left( - sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1 + sorted_collection: list[int], item: int, lo: int = 0, hi: int = -1 ) -> None: """ Inserts a given value into a sorted array before other values with the same value. @@ -148,7 +149,7 @@ def insort_left( def insort_right( - sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1 + sorted_collection: list[int], item: int, lo: int = 0, hi: int = -1 ) -> None: """ Inserts a given value into a sorted array after other values with the same value. @@ -190,7 +191,7 @@ def insort_right( sorted_collection.insert(bisect_right(sorted_collection, item, lo, hi), item) -def binary_search(sorted_collection: List[int], item: int) -> Optional[int]: +def binary_search(sorted_collection: list[int], item: int) -> int | None: """Pure implementation of binary search algorithm in Python Be careful collection must be ascending sorted, otherwise result will be @@ -228,7 +229,7 @@ def binary_search(sorted_collection: List[int], item: int) -> Optional[int]: return None -def binary_search_std_lib(sorted_collection: List[int], item: int) -> Optional[int]: +def binary_search_std_lib(sorted_collection: list[int], item: int) -> int | None: """Pure implementation of binary search algorithm in Python using stdlib Be careful collection must be ascending sorted, otherwise result will be @@ -258,8 +259,8 @@ def binary_search_std_lib(sorted_collection: List[int], item: int) -> Optional[i def binary_search_by_recursion( - sorted_collection: List[int], item: int, left: int, right: int -) -> Optional[int]: + sorted_collection: list[int], item: int, left: int, right: int +) -> int | None: """Pure implementation of binary search algorithm in Python by recursion diff --git a/searches/fibonacci_search.py b/searches/fibonacci_search.py index ac8ecc99a..55fc05d39 100644 --- a/searches/fibonacci_search.py +++ b/searches/fibonacci_search.py @@ -13,7 +13,7 @@ python3 fibonacci_search.py from functools import lru_cache -@lru_cache() +@lru_cache def fibonacci(k: int) -> int: """Finds fibonacci number in index k. diff --git a/searches/ternary_search.py b/searches/ternary_search.py index 9422a4ccb..01e437723 100644 --- a/searches/ternary_search.py +++ b/searches/ternary_search.py @@ -6,7 +6,7 @@ This is a type of divide and conquer algorithm which divides the search space in Time Complexity : O(log3 N) Space Complexity : O(1) """ -from typing import List +from __future__ import annotations # This is the precision for this function which can be altered. # It is recommended for users to keep this number greater than or equal to 10. @@ -16,7 +16,7 @@ precision = 10 # This is the linear search that will occur after the search space has become smaller. -def lin_search(left: int, right: int, array: List[int], target: int) -> int: +def lin_search(left: int, right: int, array: list[int], target: int) -> int: """Perform linear search in list. Returns -1 if element is not found. Parameters @@ -58,7 +58,7 @@ def lin_search(left: int, right: int, array: List[int], target: int) -> int: return -1 -def ite_ternary_search(array: List[int], target: int) -> int: +def ite_ternary_search(array: list[int], target: int) -> int: """Iterative method of the ternary search algorithm. >>> test_list = [0, 1, 2, 8, 13, 17, 19, 32, 42] >>> ite_ternary_search(test_list, 3) @@ -110,7 +110,7 @@ def ite_ternary_search(array: List[int], target: int) -> int: return -1 -def rec_ternary_search(left: int, right: int, array: List[int], target: int) -> int: +def rec_ternary_search(left: int, right: int, array: list[int], target: int) -> int: """Recursive method of the ternary search algorithm. >>> test_list = [0, 1, 2, 8, 13, 17, 19, 32, 42] diff --git a/sorts/bitonic_sort.py b/sorts/bitonic_sort.py index c718973e5..201fecd2c 100644 --- a/sorts/bitonic_sort.py +++ b/sorts/bitonic_sort.py @@ -3,10 +3,10 @@ Python program for Bitonic Sort. Note that this program works only when size of input is a power of 2. """ -from typing import List +from __future__ import annotations -def comp_and_swap(array: List[int], index1: int, index2: int, direction: int) -> None: +def comp_and_swap(array: list[int], index1: int, index2: int, direction: int) -> None: """Compare the value at given index1 and index2 of the array and swap them as per the given direction. @@ -37,7 +37,7 @@ def comp_and_swap(array: List[int], index1: int, index2: int, direction: int) -> array[index1], array[index2] = array[index2], array[index1] -def bitonic_merge(array: List[int], low: int, length: int, direction: int) -> None: +def bitonic_merge(array: list[int], low: int, length: int, direction: int) -> None: """ It recursively sorts a bitonic sequence in ascending order, if direction = 1, and in descending if direction = 0. @@ -61,7 +61,7 @@ def bitonic_merge(array: List[int], low: int, length: int, direction: int) -> No bitonic_merge(array, low + middle, middle, direction) -def bitonic_sort(array: List[int], low: int, length: int, direction: int) -> None: +def bitonic_sort(array: list[int], low: int, length: int, direction: int) -> None: """ This function first produces a bitonic sequence by recursively sorting its two halves in opposite sorting orders, and then calls bitonic_merge to make them in the diff --git a/sorts/bucket_sort.py b/sorts/bucket_sort.py index 1ac76774f..58242a1cb 100644 --- a/sorts/bucket_sort.py +++ b/sorts/bucket_sort.py @@ -27,7 +27,7 @@ If k = O(n), time complexity is O(n) Source: https://en.wikipedia.org/wiki/Bucket_sort """ -from typing import List +from __future__ import annotations def bucket_sort(my_list: list) -> list: @@ -52,7 +52,7 @@ def bucket_sort(my_list: list) -> list: return [] min_value, max_value = min(my_list), max(my_list) bucket_count = int(max_value - min_value) + 1 - buckets: List[list] = [[] for _ in range(bucket_count)] + buckets: list[list] = [[] for _ in range(bucket_count)] for i in range(len(my_list)): buckets[(int(my_list[i] - min_value) // bucket_count)].append(my_list[i]) diff --git a/sorts/msd_radix_sort.py b/sorts/msd_radix_sort.py index 4c3cea30e..3cdec4bd0 100644 --- a/sorts/msd_radix_sort.py +++ b/sorts/msd_radix_sort.py @@ -4,10 +4,10 @@ It used the binary representation of the integers to sort them. https://en.wikipedia.org/wiki/Radix_sort """ -from typing import List +from __future__ import annotations -def msd_radix_sort(list_of_ints: List[int]) -> List[int]: +def msd_radix_sort(list_of_ints: list[int]) -> list[int]: """ Implementation of the MSD radix sort algorithm. Only works with positive integers @@ -36,7 +36,7 @@ def msd_radix_sort(list_of_ints: List[int]) -> List[int]: return _msd_radix_sort(list_of_ints, most_bits) -def _msd_radix_sort(list_of_ints: List[int], bit_position: int) -> List[int]: +def _msd_radix_sort(list_of_ints: list[int], bit_position: int) -> list[int]: """ Sort the given list based on the bit at bit_position. Numbers with a 0 at that position will be at the start of the list, numbers with a @@ -74,7 +74,7 @@ def _msd_radix_sort(list_of_ints: List[int], bit_position: int) -> List[int]: return res -def msd_radix_sort_inplace(list_of_ints: List[int]): +def msd_radix_sort_inplace(list_of_ints: list[int]): """ Inplace implementation of the MSD radix sort algorithm. Sorts based on the binary representation of the integers. @@ -109,7 +109,7 @@ def msd_radix_sort_inplace(list_of_ints: List[int]): def _msd_radix_sort_inplace( - list_of_ints: List[int], bit_position: int, begin_index: int, end_index: int + list_of_ints: list[int], bit_position: int, begin_index: int, end_index: int ): """ Sort the given list based on the bit at bit_position. Numbers with a diff --git a/sorts/patience_sort.py b/sorts/patience_sort.py index 87f5a4078..845db5174 100644 --- a/sorts/patience_sort.py +++ b/sorts/patience_sort.py @@ -1,7 +1,8 @@ +from __future__ import annotations + from bisect import bisect_left from functools import total_ordering from heapq import merge -from typing import List """ A pure Python implementation of the patience sort algorithm @@ -44,7 +45,7 @@ def patience_sort(collection: list) -> list: >>> patience_sort([-3, -17, -48]) [-48, -17, -3] """ - stacks: List[Stack] = [] + stacks: list[Stack] = [] # sort into stacks for element in collection: new_stacks = Stack([element]) @@ -55,7 +56,7 @@ def patience_sort(collection: list) -> list: stacks.append(new_stacks) # use a heap-based merge to merge stack efficiently - collection[:] = merge(*[reversed(stack) for stack in stacks]) + collection[:] = merge(*(reversed(stack) for stack in stacks)) return collection diff --git a/sorts/pigeon_sort.py b/sorts/pigeon_sort.py index 3d81f0643..3e6d4c09c 100644 --- a/sorts/pigeon_sort.py +++ b/sorts/pigeon_sort.py @@ -9,10 +9,10 @@ For manual testing run: python pigeon_sort.py """ -from typing import List +from __future__ import annotations -def pigeon_sort(array: List[int]) -> List[int]: +def pigeon_sort(array: list[int]) -> list[int]: """ Implementation of pigeon hole sort algorithm :param array: Collection of comparable items diff --git a/sorts/quick_sort.py b/sorts/quick_sort.py index 6f51f6eca..b099c7886 100644 --- a/sorts/quick_sort.py +++ b/sorts/quick_sort.py @@ -7,7 +7,7 @@ python3 -m doctest -v quick_sort.py For manual testing run: python3 quick_sort.py """ -from typing import List +from __future__ import annotations def quick_sort(collection: list) -> list: @@ -27,8 +27,8 @@ def quick_sort(collection: list) -> list: if len(collection) < 2: return collection pivot = collection.pop() # Use the last element as the first pivot - greater: List[int] = [] # All elements greater than pivot - lesser: List[int] = [] # All elements less than or equal to pivot + greater: list[int] = [] # All elements greater than pivot + lesser: list[int] = [] # All elements less than or equal to pivot for element in collection: (greater if element > pivot else lesser).append(element) return quick_sort(lesser) + [pivot] + quick_sort(greater) diff --git a/sorts/radix_sort.py b/sorts/radix_sort.py index b802b5278..e433bc507 100644 --- a/sorts/radix_sort.py +++ b/sorts/radix_sort.py @@ -9,10 +9,8 @@ python radix_sort.py """ from __future__ import annotations -from typing import List - -def radix_sort(list_of_ints: List[int]) -> List[int]: +def radix_sort(list_of_ints: list[int]) -> list[int]: """ Examples: >>> radix_sort([0, 5, 3, 2, 2]) @@ -30,7 +28,7 @@ def radix_sort(list_of_ints: List[int]) -> List[int]: max_digit = max(list_of_ints) while placement <= max_digit: # declare and initialize empty buckets - buckets: List[list] = [list() for _ in range(RADIX)] + buckets: list[list] = [list() for _ in range(RADIX)] # split list_of_ints between the buckets for i in list_of_ints: tmp = int((i / placement) % RADIX) diff --git a/sorts/recursive_insertion_sort.py b/sorts/recursive_insertion_sort.py index 89f88b4a9..ab2716f8e 100644 --- a/sorts/recursive_insertion_sort.py +++ b/sorts/recursive_insertion_sort.py @@ -1,11 +1,8 @@ """ A recursive implementation of the insertion sort algorithm """ - from __future__ import annotations -from typing import List - def rec_insertion_sort(collection: list, n: int): """ @@ -72,6 +69,6 @@ def insert_next(collection: list, index: int): if __name__ == "__main__": numbers = input("Enter integers separated by spaces: ") - number_list: List[int] = [int(num) for num in numbers.split()] + number_list: list[int] = [int(num) for num in numbers.split()] rec_insertion_sort(number_list, len(number_list)) print(number_list) diff --git a/sorts/slowsort.py b/sorts/slowsort.py index 53bb14554..a5f4e873e 100644 --- a/sorts/slowsort.py +++ b/sorts/slowsort.py @@ -8,13 +8,10 @@ in their paper Pessimal Algorithms and Simplexity Analysis Source: https://en.wikipedia.org/wiki/Slowsort """ - -from typing import Optional +from __future__ import annotations -def slowsort( - sequence: list, start: Optional[int] = None, end: Optional[int] = None -) -> None: +def slowsort(sequence: list, start: int | None = None, end: int | None = None) -> None: """ Sorts sequence[start..end] (both inclusive) in-place. start defaults to 0 if not given. diff --git a/strings/aho_corasick.py b/strings/aho_corasick.py index 712cb338a..b9a6a8072 100644 --- a/strings/aho_corasick.py +++ b/strings/aho_corasick.py @@ -1,5 +1,6 @@ +from __future__ import annotations + from collections import deque -from typing import Dict, List, Union class Automaton: @@ -13,7 +14,7 @@ class Automaton: self.add_keyword(keyword) self.set_fail_transitions() - def find_next_state(self, current_state: int, char: str) -> Union[int, None]: + def find_next_state(self, current_state: int, char: str) -> int | None: for state in self.adlist[current_state]["next_states"]: if char == self.adlist[state]["value"]: return state @@ -63,7 +64,7 @@ class Automaton: + self.adlist[self.adlist[child]["fail_state"]]["output"] ) - def search_in(self, string: str) -> Dict[str, List[int]]: + def search_in(self, string: str) -> dict[str, list[int]]: """ >>> A = Automaton(["what", "hat", "ver", "er"]) >>> A.search_in("whatever, err ... , wherever") diff --git a/strings/boyer_moore_search.py b/strings/boyer_moore_search.py index a3e6cf614..8d8ff22f6 100644 --- a/strings/boyer_moore_search.py +++ b/strings/boyer_moore_search.py @@ -17,7 +17,7 @@ Time Complexity : O(n/m) n=length of main string m=length of pattern string """ -from typing import List +from __future__ import annotations class BoyerMooreSearch: @@ -59,7 +59,7 @@ class BoyerMooreSearch: return currentPos + i return -1 - def bad_character_heuristic(self) -> List[int]: + def bad_character_heuristic(self) -> list[int]: # searches pattern in text and returns index positions positions = [] for i in range(self.textLen - self.patLen + 1): diff --git a/strings/knuth_morris_pratt.py b/strings/knuth_morris_pratt.py index a205ce37e..a488c171a 100644 --- a/strings/knuth_morris_pratt.py +++ b/strings/knuth_morris_pratt.py @@ -1,4 +1,4 @@ -from typing import List +from __future__ import annotations def kmp(pattern: str, text: str) -> bool: @@ -36,7 +36,7 @@ def kmp(pattern: str, text: str) -> bool: return False -def get_failure_array(pattern: str) -> List[int]: +def get_failure_array(pattern: str) -> list[int]: """ Calculates the new index we should go to if we fail a comparison :param pattern: diff --git a/web_programming/emails_from_url.py b/web_programming/emails_from_url.py index 0571ac331..afaee5bbe 100644 --- a/web_programming/emails_from_url.py +++ b/web_programming/emails_from_url.py @@ -1,4 +1,6 @@ """Get the site emails from URL.""" +from __future__ import annotations + __author__ = "Muhammad Umer Farooq" __license__ = "MIT" __version__ = "1.0.0" @@ -8,7 +10,6 @@ __status__ = "Alpha" import re from html.parser import HTMLParser -from typing import Optional from urllib import parse import requests @@ -20,7 +21,7 @@ class Parser(HTMLParser): self.urls: list[str] = [] self.domain = domain - def handle_starttag(self, tag: str, attrs: list[tuple[str, Optional[str]]]) -> None: + def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None: """ This function parse html to take takes url from tags """ diff --git a/web_programming/fetch_github_info.py b/web_programming/fetch_github_info.py index c9198460f..aa4e1d7b1 100644 --- a/web_programming/fetch_github_info.py +++ b/web_programming/fetch_github_info.py @@ -17,8 +17,10 @@ with your token:: #!/usr/bin/env bash export USER_TOKEN="" """ +from __future__ import annotations + import os -from typing import Any, Dict +from typing import Any import requests @@ -31,7 +33,7 @@ AUTHENTICATED_USER_ENDPOINT = BASE_URL + "/user" USER_TOKEN = os.environ.get("USER_TOKEN", "") -def fetch_github_info(auth_token: str) -> Dict[Any, Any]: +def fetch_github_info(auth_token: str) -> dict[Any, Any]: """ Fetch GitHub info of a user using the requests module """ From 01d58562ccbfbea9d16aca6a876676b603026238 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sat, 18 Sep 2021 22:33:03 +0300 Subject: [PATCH 028/726] Fix typos in Project Euler problem 034 solution 1 (#4748) * Fix comment * Fix output --- project_euler/problem_034/sol1.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project_euler/problem_034/sol1.py b/project_euler/problem_034/sol1.py index 78b318b76..11c84ab96 100644 --- a/project_euler/problem_034/sol1.py +++ b/project_euler/problem_034/sol1.py @@ -11,7 +11,7 @@ from math import factorial def sum_of_digit_factorial(n: int) -> int: """ - Returns the sum of the digits in n + Returns the sum of the factorial of digits in n >>> sum_of_digit_factorial(15) 121 >>> sum_of_digit_factorial(0) @@ -33,4 +33,4 @@ def solution() -> int: if __name__ == "__main__": - print(f"{solution()} = ") + print(f"{solution() = }") From 4761fef1a5a3904167285af8819091018c8e04b1 Mon Sep 17 00:00:00 2001 From: jonabtc <39396756+jonabtc@users.noreply.github.com> Date: Sat, 18 Sep 2021 20:22:47 -0500 Subject: [PATCH 029/726] Double factorial iterative (#4760) * Adding the double factorial algorithm * Adding the double factorial algorithm Co-authored-by: Jonathan Ocles --- maths/double_factorial_iterative.py | 33 +++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 maths/double_factorial_iterative.py diff --git a/maths/double_factorial_iterative.py b/maths/double_factorial_iterative.py new file mode 100644 index 000000000..b2b58aa04 --- /dev/null +++ b/maths/double_factorial_iterative.py @@ -0,0 +1,33 @@ +def double_factorial(num: int) -> int: + """ + Compute double factorial using iterative method. + + To learn about the theory behind this algorithm: + https://en.wikipedia.org/wiki/Double_factorial + + >>> import math + >>> all(double_factorial(i) == math.prod(range(i, 0, -2)) for i in range(20)) + True + >>> double_factorial(0.1) + Traceback (most recent call last): + ... + ValueError: double_factorial() only accepts integral values + >>> double_factorial(-1) + Traceback (most recent call last): + ... + ValueError: double_factorial() not defined for negative values + """ + if not isinstance(num, int): + raise ValueError("double_factorial() only accepts integral values") + if num < 0: + raise ValueError("double_factorial() not defined for negative values") + value = 1 + for i in range(num, 0, -2): + value *= i + return value + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From a7b9e28bc34478850ea22e31f1d5a022502e2350 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Tue, 21 Sep 2021 14:28:27 +0300 Subject: [PATCH 030/726] Improve Project Euler problem 009 solution 1 (#4749) * Improve solution * Uncomment code that has been commented due to slow execution affecting Travis --- project_euler/problem_009/sol1.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/project_euler/problem_009/sol1.py b/project_euler/problem_009/sol1.py index a58ea943e..c50dfeecf 100644 --- a/project_euler/problem_009/sol1.py +++ b/project_euler/problem_009/sol1.py @@ -25,18 +25,16 @@ def solution() -> int: 2. a**2 + b**2 = c**2 3. a + b + c = 1000 - # The code below has been commented due to slow execution affecting Travis. - # >>> solution() - # 31875000 + >>> solution() + 31875000 """ for a in range(300): - for b in range(400): - for c in range(500): - if a < b < c: + for b in range(a + 1, 400): + for c in range(b + 1, 500): + if (a + b + c) == 1000: if (a ** 2) + (b ** 2) == (c ** 2): - if (a + b + c) == 1000: - return a * b * c + return a * b * c def solution_fast() -> int: @@ -47,9 +45,8 @@ def solution_fast() -> int: 2. a**2 + b**2 = c**2 3. a + b + c = 1000 - # The code below has been commented due to slow execution affecting Travis. - # >>> solution_fast() - # 31875000 + >>> solution_fast() + 31875000 """ for a in range(300): From abc725f12de0ef186db67e2d6bc48161ed894644 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 22 Sep 2021 19:37:18 +0200 Subject: [PATCH 031/726] mypy --install-types --non-interactive . (#4530) * mypy --install-types --non-interactive . @dhruvmanila Is this useful/needed given that we do not pin our dependencies? https://mypy-lang.blogspot.com/2021/06/mypy-0910-released.html * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2ffc2aa29..7c2255275 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,7 +21,7 @@ jobs: run: | python -m pip install --upgrade pip setuptools six wheel python -m pip install mypy pytest-cov -r requirements.txt - - run: mypy . + - run: mypy --install-types --non-interactive . - name: Run tests run: pytest --doctest-modules --ignore=project_euler/ --ignore=scripts/ --cov-report=term-missing:skip-covered --cov=. . - if: ${{ success() }} From dc07a850763d8154e012c9d1be7f8fe78326e8fb Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 22 Sep 2021 20:03:11 +0200 Subject: [PATCH 032/726] Update and rename check_valid_ip_address.py to is_ip_v4_address_valid.py (#4665) * Update and rename check_valid_ip_address.py to is_ip_v4_address_valid.py New test cases that the algorithm must detect: * [ ] an octet much bigger than 255 * [ ] an octet is negative * [ ] number of octets is less than 4 * [ ] number of octets is greater than 4 * [ ] an octet is a letter * updating DIRECTORY.md * Add two more tests to is_ip_v4_address_valid.py Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: John Law --- DIRECTORY.md | 2 +- maths/check_valid_ip_address.py | 46 --------------------------- maths/is_ip_v4_address_valid.py | 56 +++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 47 deletions(-) delete mode 100644 maths/check_valid_ip_address.py create mode 100644 maths/is_ip_v4_address_valid.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 0c00d5ca7..0d44e10ad 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -424,7 +424,6 @@ * [Binomial Distribution](https://github.com/TheAlgorithms/Python/blob/master/maths/binomial_distribution.py) * [Bisection](https://github.com/TheAlgorithms/Python/blob/master/maths/bisection.py) * [Ceil](https://github.com/TheAlgorithms/Python/blob/master/maths/ceil.py) - * [Check Valid Ip Address](https://github.com/TheAlgorithms/Python/blob/master/maths/check_valid_ip_address.py) * [Chudnovsky Algorithm](https://github.com/TheAlgorithms/Python/blob/master/maths/chudnovsky_algorithm.py) * [Collatz Sequence](https://github.com/TheAlgorithms/Python/blob/master/maths/collatz_sequence.py) * [Combinations](https://github.com/TheAlgorithms/Python/blob/master/maths/combinations.py) @@ -454,6 +453,7 @@ * [Greedy Coin Change](https://github.com/TheAlgorithms/Python/blob/master/maths/greedy_coin_change.py) * [Hardy Ramanujanalgo](https://github.com/TheAlgorithms/Python/blob/master/maths/hardy_ramanujanalgo.py) * [Integration By Simpson Approx](https://github.com/TheAlgorithms/Python/blob/master/maths/integration_by_simpson_approx.py) + * [Is Ip V4 Address Valid](https://github.com/TheAlgorithms/Python/blob/master/maths/is_ip_v4_address_valid.py) * [Is Square Free](https://github.com/TheAlgorithms/Python/blob/master/maths/is_square_free.py) * [Jaccard Similarity](https://github.com/TheAlgorithms/Python/blob/master/maths/jaccard_similarity.py) * [Kadanes](https://github.com/TheAlgorithms/Python/blob/master/maths/kadanes.py) diff --git a/maths/check_valid_ip_address.py b/maths/check_valid_ip_address.py deleted file mode 100644 index 6e8d35ebc..000000000 --- a/maths/check_valid_ip_address.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -Checking valid Ip Address. -A valid IP address must be in the form of A.B.C.D, -where A,B,C and D are numbers from 0-254 -for example: 192.168.23.1, 172.254.254.254 are valid IP address - 192.168.255.0, 255.192.3.121 are Invalid IP address -""" - - -def check_valid_ip(ip: str) -> bool: - """ - print "Valid IP address" If IP is valid. - or - print "Invalid IP address" If IP is Invalid. - - >>> check_valid_ip("192.168.0.23") - True - - >>> check_valid_ip("192.255.15.8") - False - - >>> check_valid_ip("172.100.0.8") - True - - >>> check_valid_ip("254.255.0.255") - False - """ - ip1 = ip.replace(".", " ") - list1 = [int(i) for i in ip1.split() if i.isdigit()] - count = 0 - for i in list1: - if i > 254: - count += 1 - break - if count: - return False - return True - - -if __name__ == "__main__": - ip = input() - output = check_valid_ip(ip) - if output is True: - print(f"{ip} is a Valid IP address") - else: - print(f"{ip} is an Invalid IP address") diff --git a/maths/is_ip_v4_address_valid.py b/maths/is_ip_v4_address_valid.py new file mode 100644 index 000000000..0ae8e021e --- /dev/null +++ b/maths/is_ip_v4_address_valid.py @@ -0,0 +1,56 @@ +""" +Is IP v4 address valid? +A valid IP address must be four octets in the form of A.B.C.D, +where A,B,C and D are numbers from 0-254 +for example: 192.168.23.1, 172.254.254.254 are valid IP address + 192.168.255.0, 255.192.3.121 are invalid IP address +""" + + +def is_ip_v4_address_valid(ip_v4_address: str) -> bool: + """ + print "Valid IP address" If IP is valid. + or + print "Invalid IP address" If IP is invalid. + + >>> is_ip_v4_address_valid("192.168.0.23") + True + + >>> is_ip_v4_address_valid("192.255.15.8") + False + + >>> is_ip_v4_address_valid("172.100.0.8") + True + + >>> is_ip_v4_address_valid("254.255.0.255") + False + + >>> is_ip_v4_address_valid("1.2.33333333.4") + False + + >>> is_ip_v4_address_valid("1.2.-3.4") + False + + >>> is_ip_v4_address_valid("1.2.3") + False + + >>> is_ip_v4_address_valid("1.2.3.4.5") + False + + >>> is_ip_v4_address_valid("1.2.A.4") + False + + >>> is_ip_v4_address_valid("0.0.0.0") + True + + >>> is_ip_v4_address_valid("1.2.3.") + False + """ + octets = [int(i) for i in ip_v4_address.split(".") if i.isdigit()] + return len(octets) == 4 and all(0 <= int(octet) <= 254 for octet in octets) + + +if __name__ == "__main__": + ip = input().strip() + valid_or_invalid = "valid" if is_ip_v4_address_valid(ip) else "invalid" + print(f"{ip} is a {valid_or_invalid} IP v4 address.") From 15d1cfabb15903c5e9d4d103e2390876efb3f85f Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 22 Sep 2021 23:11:51 +0200 Subject: [PATCH 033/726] from __future__ import annotations (#4763) * from __future__ import annotations * updating DIRECTORY.md * from __future__ import annotations * from __future__ import annotations * Update xor_cipher.py Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 1 + ciphers/a1z26.py | 1 + ciphers/enigma_machine2.py | 1 + ciphers/trafid_cipher.py | 1 + ciphers/xor_cipher.py | 27 +++++++-------------------- 5 files changed, 11 insertions(+), 20 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 0d44e10ad..2e9942b5b 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -448,6 +448,7 @@ * [Find Min Recursion](https://github.com/TheAlgorithms/Python/blob/master/maths/find_min_recursion.py) * [Floor](https://github.com/TheAlgorithms/Python/blob/master/maths/floor.py) * [Gamma](https://github.com/TheAlgorithms/Python/blob/master/maths/gamma.py) + * [Gamma Recursive](https://github.com/TheAlgorithms/Python/blob/master/maths/gamma_recursive.py) * [Gaussian](https://github.com/TheAlgorithms/Python/blob/master/maths/gaussian.py) * [Greatest Common Divisor](https://github.com/TheAlgorithms/Python/blob/master/maths/greatest_common_divisor.py) * [Greedy Coin Change](https://github.com/TheAlgorithms/Python/blob/master/maths/greedy_coin_change.py) diff --git a/ciphers/a1z26.py b/ciphers/a1z26.py index e6684fb1e..0f0eb7c5c 100644 --- a/ciphers/a1z26.py +++ b/ciphers/a1z26.py @@ -5,6 +5,7 @@ corresponding to the character's position in the alphabet. https://www.dcode.fr/letter-number-cipher http://bestcodes.weebly.com/a1z26.html """ +from __future__ import annotations def encode(plain: str) -> list[int]: diff --git a/ciphers/enigma_machine2.py b/ciphers/enigma_machine2.py index f4ce5a075..9252dd0ed 100644 --- a/ciphers/enigma_machine2.py +++ b/ciphers/enigma_machine2.py @@ -14,6 +14,7 @@ Module includes: Created by TrapinchO """ +from __future__ import annotations RotorPositionT = tuple[int, int, int] RotorSelectionT = tuple[str, str, str] diff --git a/ciphers/trafid_cipher.py b/ciphers/trafid_cipher.py index 1c8ea3024..b12ceff72 100644 --- a/ciphers/trafid_cipher.py +++ b/ciphers/trafid_cipher.py @@ -1,4 +1,5 @@ # https://en.wikipedia.org/wiki/Trifid_cipher +from __future__ import annotations def __encryptPart(messagePart: str, character2Number: dict[str, str]) -> str: diff --git a/ciphers/xor_cipher.py b/ciphers/xor_cipher.py index 12d580e72..ca9dfe20f 100644 --- a/ciphers/xor_cipher.py +++ b/ciphers/xor_cipher.py @@ -16,6 +16,7 @@ - encrypt_file : boolean - decrypt_file : boolean """ +from __future__ import annotations class XORCipher: @@ -41,17 +42,10 @@ class XORCipher: key = key or self.__key or 1 - # make sure key can be any size - while key > 255: - key -= 255 + # make sure key is an appropriate size + key %= 255 - # This will be returned - ans = [] - - for ch in content: - ans.append(chr(ord(ch) ^ key)) - - return ans + return [chr(ord(ch) ^ key) for ch in content] def decrypt(self, content: str, key: int) -> list[str]: """ @@ -66,17 +60,10 @@ class XORCipher: key = key or self.__key or 1 - # make sure key can be any size - while key > 255: - key -= 255 + # make sure key is an appropriate size + key %= 255 - # This will be returned - ans = [] - - for ch in content: - ans.append(chr(ord(ch) ^ key)) - - return ans + return [chr(ord(ch) ^ key) for ch in content] def encrypt_string(self, content: str, key: int = 0) -> str: """ From 66a528b171b433a9cb298fba395180445fe1f3e1 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Thu, 23 Sep 2021 21:55:18 +0300 Subject: [PATCH 034/726] Improve Project Euler problem 014 solution 2 (#4752) --- project_euler/problem_014/sol2.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/project_euler/problem_014/sol2.py b/project_euler/problem_014/sol2.py index 7ed68273b..0a58f8d9a 100644 --- a/project_euler/problem_014/sol2.py +++ b/project_euler/problem_014/sol2.py @@ -28,16 +28,16 @@ Which starting number, under one million, produces the longest chain? from __future__ import annotations -def collatz_sequence(n: int) -> list[int]: - """Returns the Collatz sequence for n.""" - sequence = [n] +def collatz_sequence_length(n: int) -> int: + """Returns the Collatz sequence length for n.""" + sequence_length = 1 while n != 1: if n % 2 == 0: n //= 2 else: n = 3 * n + 1 - sequence.append(n) - return sequence + sequence_length += 1 + return sequence_length def solution(n: int = 1000000) -> int: @@ -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((collatz_sequence_length(i), i) for i in range(1, n)) return result[1] From 5d02103b273dffb2637264c0fc2136ca4fd41b57 Mon Sep 17 00:00:00 2001 From: Jogendra Singh <58473917+Joe-Sin7h@users.noreply.github.com> Date: Fri, 24 Sep 2021 16:24:38 +0530 Subject: [PATCH 035/726] Fixed #4764 (#4779) * Fixed #4764 * Fixes #4764 --- data_structures/disjoint_set/disjoint_set.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/data_structures/disjoint_set/disjoint_set.py b/data_structures/disjoint_set/disjoint_set.py index a93b89621..bf5ab415d 100644 --- a/data_structures/disjoint_set/disjoint_set.py +++ b/data_structures/disjoint_set/disjoint_set.py @@ -26,7 +26,10 @@ def union_set(x, y): disjoint set tree will be more flat. """ x, y = find_set(x), find_set(y) - if x.rank > y.rank: + if x == y: + return + + elif x.rank > y.rank: y.parent = x else: x.parent = y From 02bc4bf4171497277354c01387c96e044f2dedfe Mon Sep 17 00:00:00 2001 From: Alexandre De Zotti Date: Wed, 29 Sep 2021 06:42:11 +0100 Subject: [PATCH 036/726] Add Julia sets to fractals (#4382) * Added Julia sets drawing * Forgot the .py extension * Update julia_sets.py Added online sources for comparison. Added more examples of fractal Julia sets. Added all type hints. Only show one picture Silented RuntuleWarning's (there's no way of avoiding them and they're not an issue per se) * Added doctest example for "show_results" * Filtering Nan's and infinites * added 1 missing type hint * in iterate_function, convert to dtype=complex64 * RuntimeWarning (fine) filtering * Type hint, test for ignore_warnings function, typo in header * Update julia_sets.py Type of expected output value for iterate function int array -> complex array (throws an error on test) * Update julia_sets.py - More accurate type for tests cases in eval_quadratic_polynomial and iterate_function - added more characters for variables c & z in eval_quadratic_polynomial and eval_exponential to silent bot warnings * Function def formatting Blocked by black * Update julia_sets.py * Update fractals/julia_sets.py Co-authored-by: John Law * Update fractals/julia_sets.py Co-authored-by: John Law * Update fractals/julia_sets.py Co-authored-by: John Law * Update fractals/julia_sets.py Co-authored-by: John Law * Update fractals/julia_sets.py Co-authored-by: John Law * Update fractals/julia_sets.py Co-authored-by: John Law * Update fractals/julia_sets.py Co-authored-by: John Law * added more doctests for eval_exponential * Update fractals/julia_sets.py Co-authored-by: John Law Co-authored-by: John Law --- fractals/julia_sets.py | 219 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 fractals/julia_sets.py diff --git a/fractals/julia_sets.py b/fractals/julia_sets.py new file mode 100644 index 000000000..0168a0153 --- /dev/null +++ b/fractals/julia_sets.py @@ -0,0 +1,219 @@ +"""Author Alexandre De Zotti + +Draws Julia sets of quadratic polynomials and exponential maps. + More specifically, this iterates the function a fixed number of times + then plots whether the absolute value of the last iterate is greater than + a fixed threshold (named "escape radius"). For the exponential map this is not + really an escape radius but rather a convenient way to approximate the Julia + set with bounded orbits. + +The examples presented here are: +- The Cauliflower Julia set, see e.g. +https://en.wikipedia.org/wiki/File:Julia_z2%2B0,25.png +- Other examples from https://en.wikipedia.org/wiki/Julia_set +- An exponential map Julia set, ambiantly homeomorphic to the examples in +http://www.math.univ-toulouse.fr/~cheritat/GalII/galery.html + and +https://ddd.uab.cat/pub/pubmat/02141493v43n1/02141493v43n1p27.pdf + +Remark: Some overflow runtime warnings are suppressed. This is because of the + way the iteration loop is implemented, using numpy's efficient computations. + Overflows and infinites are replaced after each step by a large number. +""" + +import warnings +from typing import Any, Callable + +import numpy +from matplotlib import pyplot + +c_cauliflower = 0.25 + 0.0j +c_polynomial_1 = -0.4 + 0.6j +c_polynomial_2 = -0.1 + 0.651j +c_exponential = -2.0 +nb_iterations = 56 +window_size = 2.0 +nb_pixels = 666 + + +def eval_exponential(c_parameter: complex, z_values: numpy.ndarray) -> numpy.ndarray: + """ + Evaluate $e^z + c$. + >>> eval_exponential(0, 0) + 1.0 + >>> abs(eval_exponential(1, numpy.pi*1.j)) < 1e-15 + True + >>> abs(eval_exponential(1.j, 0)-1-1.j) < 1e-15 + True + """ + return numpy.exp(z_values) + c_parameter + + +def eval_quadratic_polynomial( + c_parameter: complex, z_values: numpy.ndarray +) -> numpy.ndarray: + """ + >>> eval_quadratic_polynomial(0, 2) + 4 + >>> eval_quadratic_polynomial(-1, 1) + 0 + >>> round(eval_quadratic_polynomial(1.j, 0).imag) + 1 + >>> round(eval_quadratic_polynomial(1.j, 0).real) + 0 + """ + return z_values * z_values + c_parameter + + +def prepare_grid(window_size: float, nb_pixels: int) -> numpy.ndarray: + """ + Create a grid of complex values of size nb_pixels*nb_pixels with real and + imaginary parts ranging from -window_size to window_size (inclusive). + Returns a numpy array. + + >>> prepare_grid(1,3) + array([[-1.-1.j, -1.+0.j, -1.+1.j], + [ 0.-1.j, 0.+0.j, 0.+1.j], + [ 1.-1.j, 1.+0.j, 1.+1.j]]) + """ + x = numpy.linspace(-window_size, window_size, nb_pixels) + x = x.reshape((nb_pixels, 1)) + y = numpy.linspace(-window_size, window_size, nb_pixels) + y = y.reshape((1, nb_pixels)) + return x + 1.0j * y + + +def iterate_function( + eval_function: Callable[[Any, numpy.ndarray], numpy.ndarray], + function_params: Any, + nb_iterations: int, + z_0: numpy.ndarray, + infinity: float = None, +) -> numpy.ndarray: + """ + Iterate the function "eval_function" exactly nb_iterations times. + The first argument of the function is a parameter which is contained in + function_params. The variable z_0 is an array that contains the initial + values to iterate from. + This function returns the final iterates. + + >>> iterate_function(eval_quadratic_polynomial, 0, 3, numpy.array([0,1,2])).shape + (3,) + >>> numpy.round(iterate_function(eval_quadratic_polynomial, + ... 0, + ... 3, + ... numpy.array([0,1,2]))[0]) + 0j + >>> numpy.round(iterate_function(eval_quadratic_polynomial, + ... 0, + ... 3, + ... numpy.array([0,1,2]))[1]) + (1+0j) + >>> numpy.round(iterate_function(eval_quadratic_polynomial, + ... 0, + ... 3, + ... numpy.array([0,1,2]))[2]) + (256+0j) + """ + + z_n = z_0.astype("complex64") + for i in range(nb_iterations): + z_n = eval_function(function_params, z_n) + if infinity is not None: + numpy.nan_to_num(z_n, copy=False, nan=infinity) + z_n[abs(z_n) == numpy.inf] = infinity + return z_n + + +def show_results( + function_label: str, + function_params: Any, + escape_radius: float, + z_final: numpy.ndarray, +) -> None: + """ + Plots of whether the absolute value of z_final is greater than + the value of escape_radius. Adds the function_label and function_params to + the title. + + >>> show_results('80', 0, 1, numpy.array([[0,1,.5],[.4,2,1.1],[.2,1,1.3]])) + """ + + abs_z_final = (abs(z_final)).transpose() + abs_z_final[:, :] = abs_z_final[::-1, :] + pyplot.matshow(abs_z_final < escape_radius) + pyplot.title(f"Julia set of ${function_label}$, $c={function_params}$") + pyplot.show() + + +def ignore_overflow_warnings() -> None: + """ + Ignore some overflow and invalid value warnings. + + >>> ignore_overflow_warnings() + """ + warnings.filterwarnings( + "ignore", category=RuntimeWarning, message="overflow encountered in multiply" + ) + warnings.filterwarnings( + "ignore", + category=RuntimeWarning, + message="invalid value encountered in multiply", + ) + warnings.filterwarnings( + "ignore", category=RuntimeWarning, message="overflow encountered in absolute" + ) + warnings.filterwarnings( + "ignore", category=RuntimeWarning, message="overflow encountered in exp" + ) + + +if __name__ == "__main__": + + z_0 = prepare_grid(window_size, nb_pixels) + + ignore_overflow_warnings() # See file header for explanations + + nb_iterations = 24 + escape_radius = 2 * abs(c_cauliflower) + 1 + z_final = iterate_function( + eval_quadratic_polynomial, + c_cauliflower, + nb_iterations, + z_0, + infinity=1.1 * escape_radius, + ) + show_results("z^2+c", c_cauliflower, escape_radius, z_final) + + nb_iterations = 64 + escape_radius = 2 * abs(c_polynomial_1) + 1 + z_final = iterate_function( + eval_quadratic_polynomial, + c_polynomial_1, + nb_iterations, + z_0, + infinity=1.1 * escape_radius, + ) + show_results("z^2+c", c_polynomial_1, escape_radius, z_final) + + nb_iterations = 161 + escape_radius = 2 * abs(c_polynomial_2) + 1 + z_final = iterate_function( + eval_quadratic_polynomial, + c_polynomial_2, + nb_iterations, + z_0, + infinity=1.1 * escape_radius, + ) + show_results("z^2+c", c_polynomial_2, escape_radius, z_final) + + nb_iterations = 12 + escape_radius = 10000.0 + z_final = iterate_function( + eval_exponential, + c_exponential, + nb_iterations, + z_0 + 2, + infinity=1.0e10, + ) + show_results("e^z+c", c_exponential, escape_radius, z_final) From b9f18152b74e7a1b0b60c6c1781580e6228f4ba4 Mon Sep 17 00:00:00 2001 From: "Arghya Sarkar (ASRA)" <67339217+sarkarghya@users.noreply.github.com> Date: Wed, 29 Sep 2021 22:19:42 +0530 Subject: [PATCH 037/726] Create check_polygon.py (#4605) * Create check_polygon.py * Update check_polygon.py * Update maths/check_polygon.py * Update check_polygon.py * Update check_polygon.py Co-authored-by: John Law --- maths/check_polygon.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 maths/check_polygon.py diff --git a/maths/check_polygon.py b/maths/check_polygon.py new file mode 100644 index 000000000..0e7711973 --- /dev/null +++ b/maths/check_polygon.py @@ -0,0 +1,31 @@ +from typing import List + + +def check_polygon(nums: List) -> bool: + """ + Takes list of possible side lengths and determines whether a + two-dimensional polygon with such side lengths can exist. + + Returns a boolean value for the < comparison + of the largest side length with sum of the rest. + Wiki: https://en.wikipedia.org/wiki/Triangle_inequality + + >>> check_polygon([6, 10, 5]) + True + >>> check_polygon([3, 7, 13, 2]) + False + >>> check_polygon([]) + Traceback (most recent call last): + ... + ValueError: List is invalid + """ + if not nums: + raise ValueError("List is invalid") + nums.sort() + return nums.pop() < sum(nums) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From d1e70cfa3a56914f03a1be7d92447197b9a6a5dc Mon Sep 17 00:00:00 2001 From: ss1208 <87578327+ss1208@users.noreply.github.com> Date: Wed, 29 Sep 2021 23:34:35 +0530 Subject: [PATCH 038/726] docs: renovate README (#4620) Conjunctive adverbs should be followed by a comma. For more details, kindly refer: https://www.aje.com/arc/editing-tip-commas-conjunctive-adverbs/ Separate out the labels into two rows Co-authored-by: John Law Co-authored-by: Dhruv Manilawala --- README.md | 67 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 1e85ed0da..0298d4602 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,55 @@ -# The Algorithms - Python -[![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod&style=flat-square)](https://gitpod.io/#https://github.com/TheAlgorithms/Python)  -[![Discord chat](https://img.shields.io/discord/808045925556682782.svg?logo=discord&colorB=7289DA&style=flat-square)](https://discord.gg/c7MnfGFGa6)  -[![Gitter chat](https://img.shields.io/badge/Chat-Gitter-ff69b4.svg?label=Chat&logo=gitter&style=flat-square)](https://gitter.im/TheAlgorithms)  -[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/TheAlgorithms/Python/build?label=CI&logo=github&style=flat-square)](https://github.com/TheAlgorithms/Python/actions)  -[![LGTM](https://img.shields.io/lgtm/alerts/github/TheAlgorithms/Python.svg?label=LGTM&logo=LGTM&style=flat-square)](https://lgtm.com/projects/g/TheAlgorithms/Python/alerts)  -[![contributions welcome](https://img.shields.io/static/v1.svg?label=Contributions&message=Welcome&color=0059b3&style=flat-square)](https://github.com/TheAlgorithms/Python/blob/master/CONTRIBUTING.md)  -[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg?logo=paypal&style=flat-square)](https://www.paypal.me/TheAlgorithms/100)  -![](https://img.shields.io/github/repo-size/TheAlgorithms/Python.svg?label=Repo%20size&style=flat-square)  -[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=flat-square)](https://github.com/pre-commit/pre-commit)  -[![code style: black](https://img.shields.io/static/v1?label=code%20style&message=black&color=black&style=flat-square)](https://github.com/psf/black)  - +
+ + + + +

The Algorithms - Python

+ + + + Gitpod Ready-to-Code + + + Contributions Welcome + + + Donate + + + + Discord chat + + + Gitter chat + + +
+ + GitHub Workflow Status + + + LGTM + + + pre-commit + + + code style: black + + +

All algorithms implemented in Python - for education

+
-### All algorithms implemented in Python (for education) +Implementations are for learning purposes only. As they may be less efficient than the implementations in the Python standard library, use them at your discretion. -These implementations are for learning purposes only. Therefore they may be less efficient than the implementations in the Python standard library. +## Getting Started -## Contribution Guidelines +Read through our [Contribution Guidelines](CONTRIBUTING.md) before you contribute. -Read our [Contribution Guidelines](CONTRIBUTING.md) before you contribute. +## Community Channels -## Community Channel - -We're on [Gitter](https://gitter.im/TheAlgorithms)! Please join us. +We're on [Discord](https://discord.gg/c7MnfGFGa6) and [Gitter](https://gitter.im/TheAlgorithms)! Community channels are great for you to ask questions and get help. Please join us! ## List of Algorithms -See our [directory](DIRECTORY.md). +See our [directory](DIRECTORY.md) for easier navigation and better overview of the project. From 6341f351aab0ff510fcf1d9ce135be680763a971 Mon Sep 17 00:00:00 2001 From: DukicDev Date: Fri, 1 Oct 2021 23:48:47 +0200 Subject: [PATCH 039/726] Fix comments in backtracking/coloring.py (#4857) --- backtracking/coloring.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/backtracking/coloring.py b/backtracking/coloring.py index 8bda4b587..9d539de8a 100644 --- a/backtracking/coloring.py +++ b/backtracking/coloring.py @@ -1,7 +1,7 @@ """ Graph Coloring also called "m coloring problem" - consists of coloring given graph with at most m colors - such that no adjacent vertices are assigned same color + consists of coloring a given graph with at most m colors + such that no adjacent vertices are assigned the same color Wikipedia: https://en.wikipedia.org/wiki/Graph_coloring """ @@ -11,9 +11,9 @@ def valid_coloring( neighbours: list[int], colored_vertices: list[int], color: int ) -> bool: """ - For each neighbour check if coloring constraint is satisfied + For each neighbour check if the coloring constraint is satisfied If any of the neighbours fail the constraint return False - If all neighbours validate constraint return True + If all neighbours validate the constraint return True >>> neighbours = [0,1,0,1,0] >>> colored_vertices = [0, 2, 1, 2, 0] @@ -41,14 +41,14 @@ def util_color( Base Case: 1. Check if coloring is complete - 1.1 If complete return True (meaning that we successfully colored graph) + 1.1 If complete return True (meaning that we successfully colored the graph) Recursive Step: - 2. Itterates over each color: - Check if current coloring is valid: + 2. Iterates over each color: + Check if the current coloring is valid: 2.1. Color given vertex - 2.2. Do recursive call check if this coloring leads to solving problem - 2.4. if current coloring leads to solution return + 2.2. Do recursive call, check if this coloring leads to a solution + 2.4. if current coloring leads to a solution return 2.5. Uncolor given vertex >>> graph = [[0, 1, 0, 0, 0], From 31b34af9fa7e09b4832af36071be86df37959e0d Mon Sep 17 00:00:00 2001 From: DukicDev Date: Sat, 2 Oct 2021 15:37:28 +0200 Subject: [PATCH 040/726] Correct grammar in backtracking/n_queens_math.py (#4869) --- backtracking/n_queens_math.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index c12aa6c33..2de784ded 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -1,7 +1,7 @@ r""" Problem: -The n queens problem is of placing N queens on a N * N chess board such that no queen +The n queens problem is: placing N queens on a N * N chess board such that no queen can attack any other queens placed on that chess board. This means that one queen cannot have any other queen on its horizontal, vertical and diagonal lines. @@ -31,7 +31,7 @@ So if we use an array and we verify that each value in the array is different to other we know that at least the queens can't attack each other in horizontal and vertical. -At this point we have that halfway completed and we will treat the chessboard as a +At this point we have it halfway completed and we will treat the chessboard as a Cartesian plane. Hereinafter we are going to remember basic math, so in the school we learned this formula: @@ -47,7 +47,7 @@ This formula allow us to get the slope. For the angles 45º (right diagonal) and See:: https://www.enotes.com/homework-help/write-equation-line-that-hits-origin-45-degree-1474860 -Then we have this another formula: +Then we have this other formula: Slope intercept: @@ -59,7 +59,7 @@ we would have: y - mx = b -And like we already have the m values for the angles 45º and 135º, this formula would +And since we already have the m values for the angles 45º and 135º, this formula would look like this: 45º: y - (1)x = b @@ -71,7 +71,7 @@ look like this: y = row x = column -Applying this two formulas we can check if a queen in some position is being attacked +Applying these two formulas we can check if a queen in some position is being attacked for another one or vice versa. """ From c873fa0b1bab5dcfeffb386dddd6a755ef2aa0f9 Mon Sep 17 00:00:00 2001 From: DukicDev Date: Sat, 2 Oct 2021 15:51:53 +0200 Subject: [PATCH 041/726] Correct grammar of comment in backtracking/hamiltonian_cycle.py (#4868) --- backtracking/hamiltonian_cycle.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backtracking/hamiltonian_cycle.py b/backtracking/hamiltonian_cycle.py index 19751b347..500e993e5 100644 --- a/backtracking/hamiltonian_cycle.py +++ b/backtracking/hamiltonian_cycle.py @@ -15,8 +15,8 @@ def valid_connection( Checks whether it is possible to add next into path by validating 2 statements 1. There should be path between current and next vertex 2. Next vertex should not be in path - If both validations succeeds we return True saying that it is possible to connect - this vertices either we return False + If both validations succeed we return True, saying that it is possible to connect + this vertices, otherwise we return False Case 1:Use exact graph as in main function, with initialized values >>> graph = [[0, 1, 0, 1, 0], From d530d2bcf42391a8172c720e8d7c7d354a748abf Mon Sep 17 00:00:00 2001 From: Nolan Emirot Date: Sun, 3 Oct 2021 20:33:42 -0700 Subject: [PATCH 042/726] fix: comment in patience sort (#4972) --- sorts/patience_sort.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sorts/patience_sort.py b/sorts/patience_sort.py index 845db5174..63c2c8ffe 100644 --- a/sorts/patience_sort.py +++ b/sorts/patience_sort.py @@ -29,7 +29,7 @@ class Stack(list): def patience_sort(collection: list) -> list: - """A pure implementation of quick sort algorithm in Python + """A pure implementation of patience sort algorithm in Python :param collection: some mutable ordered collection with heterogeneous comparable items inside From 90db98304e06a60a3c578e9f55fe139524a4c3f8 Mon Sep 17 00:00:00 2001 From: Sarvesh Kumar Dwivedi Date: Mon, 4 Oct 2021 09:37:58 +0530 Subject: [PATCH 043/726] Fix word typos in comments (#4928) * fixed: spelling nonegative -> non-negative * fixed: spelling transpostiion -> transposition * fixed: spelling topolical -> topological * fixed: spelling sufix -> suffix --- sorts/bead_sort.py | 2 +- sorts/odd_even_transposition_single_threaded.py | 2 +- sorts/topological_sort.py | 2 +- strings/prefix_function.py | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sorts/bead_sort.py b/sorts/bead_sort.py index 3767e842d..26a3fabc4 100644 --- a/sorts/bead_sort.py +++ b/sorts/bead_sort.py @@ -1,5 +1,5 @@ """ -Bead sort only works for sequences of nonegative integers. +Bead sort only works for sequences of non-negative integers. https://en.wikipedia.org/wiki/Bead_sort """ diff --git a/sorts/odd_even_transposition_single_threaded.py b/sorts/odd_even_transposition_single_threaded.py index fe06459e8..f6cf7fba2 100644 --- a/sorts/odd_even_transposition_single_threaded.py +++ b/sorts/odd_even_transposition_single_threaded.py @@ -1,7 +1,7 @@ """ Source: https://en.wikipedia.org/wiki/Odd%E2%80%93even_sort -This is a non-parallelized implementation of odd-even transpostiion sort. +This is a non-parallelized implementation of odd-even transposition sort. Normally the swaps in each set happen simultaneously, without that the algorithm is no better than bubble sort. diff --git a/sorts/topological_sort.py b/sorts/topological_sort.py index e7a52f7c7..59a0c8571 100644 --- a/sorts/topological_sort.py +++ b/sorts/topological_sort.py @@ -10,7 +10,7 @@ vertices = ["a", "b", "c", "d", "e"] def topological_sort(start, visited, sort): - """Perform topolical sort on a directed acyclic graph.""" + """Perform topological sort on a directed acyclic graph.""" current = start # add current to visited visited.append(current) diff --git a/strings/prefix_function.py b/strings/prefix_function.py index 9e6dbbf54..6eca01635 100644 --- a/strings/prefix_function.py +++ b/strings/prefix_function.py @@ -14,7 +14,7 @@ Time Complexity: O(n) - where n is the length of the string def prefix_function(input_string: str) -> list: """ For the given string this function computes value for each index(i), - which represents the longest coincidence of prefix and sufix + which represents the longest coincidence of prefix and suffix for given substring (input_str[0...i]) For the value of the first element the algorithm always returns 0 @@ -45,7 +45,7 @@ def prefix_function(input_string: str) -> list: def longest_prefix(input_str: str) -> int: """ Prefix-function use case - Finding longest prefix which is sufix as well + Finding longest prefix which is suffix as well >>> longest_prefix("aabcdaabc") 4 From a4d68d69f17f08f71ec81e5c5b681e1213ec8f7d Mon Sep 17 00:00:00 2001 From: Lewis Tian Date: Wed, 6 Oct 2021 22:06:49 +0800 Subject: [PATCH 044/726] bugfix: Add abs_max.py & abs_min.py empty list detection (#4844) * bugfix: Add abs_max.py & abs_min.py empty list detection * fix shebangs check --- maths/abs_max.py | 17 ++++++++++++++++- maths/abs_min.py | 19 +++++++++++++++---- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/maths/abs_max.py b/maths/abs_max.py index e5a821965..4a4b4d9eb 100644 --- a/maths/abs_max.py +++ b/maths/abs_max.py @@ -7,7 +7,13 @@ def abs_max(x: list[int]) -> int: 11 >>> abs_max([3,-10,-2]) -10 + >>> abs_max([]) + Traceback (most recent call last): + ... + ValueError: abs_max() arg is an empty sequence """ + if len(x) == 0: + raise ValueError("abs_max() arg is an empty sequence") j = x[0] for i in x: if abs(i) > abs(j): @@ -15,13 +21,19 @@ def abs_max(x: list[int]) -> int: return j -def abs_max_sort(x): +def abs_max_sort(x: list[int]) -> int: """ >>> abs_max_sort([0,5,1,11]) 11 >>> abs_max_sort([3,-10,-2]) -10 + >>> abs_max_sort([]) + Traceback (most recent call last): + ... + ValueError: abs_max_sort() arg is an empty sequence """ + if len(x) == 0: + raise ValueError("abs_max_sort() arg is an empty sequence") return sorted(x, key=abs)[-1] @@ -32,4 +44,7 @@ def main(): if __name__ == "__main__": + import doctest + + doctest.testmod(verbose=True) main() diff --git a/maths/abs_min.py b/maths/abs_min.py index eb84de37c..00dbcb025 100644 --- a/maths/abs_min.py +++ b/maths/abs_min.py @@ -1,13 +1,21 @@ +from __future__ import annotations + from .abs import abs_val -def absMin(x): +def abs_min(x: list[int]) -> int: """ - >>> absMin([0,5,1,11]) + >>> abs_min([0,5,1,11]) 0 - >>> absMin([3,-10,-2]) + >>> abs_min([3,-10,-2]) -2 + >>> abs_min([]) + Traceback (most recent call last): + ... + ValueError: abs_min() arg is an empty sequence """ + if len(x) == 0: + raise ValueError("abs_min() arg is an empty sequence") j = x[0] for i in x: if abs_val(i) < abs_val(j): @@ -17,8 +25,11 @@ def absMin(x): def main(): a = [-3, -1, 2, -11] - print(absMin(a)) # = -1 + print(abs_min(a)) # = -1 if __name__ == "__main__": + import doctest + + doctest.testmod(verbose=True) main() From 629369a34fdcaee70392d1fcd8cbcae5418c350b Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Wed, 6 Oct 2021 17:11:15 +0300 Subject: [PATCH 045/726] Improve Project Euler problem 203 solution 1 (#4807) --- project_euler/problem_203/sol1.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/project_euler/problem_203/sol1.py b/project_euler/problem_203/sol1.py index 030cf12f2..fe4d14b20 100644 --- a/project_euler/problem_203/sol1.py +++ b/project_euler/problem_203/sol1.py @@ -75,17 +75,15 @@ def get_primes_squared(max_number: int) -> list[int]: >>> get_primes_squared(100) [4, 9, 25, 49] """ - max_prime = round(math.sqrt(max_number)) - non_primes = set() + max_prime = math.isqrt(max_number) + non_primes = [False] * (max_prime + 1) primes = [] for num in range(2, max_prime + 1): - if num in non_primes: + if non_primes[num]: continue - counter = 2 - while num * counter <= max_prime: - non_primes.add(num * counter) - counter += 1 + for num_counter in range(num ** 2, max_prime + 1, num): + non_primes[num_counter] = True primes.append(num ** 2) return primes From d654806eae5dc6027911424ea828e566a64641fd Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Wed, 6 Oct 2021 17:11:50 +0300 Subject: [PATCH 046/726] Improve Project Euler problem 112 solution 1 (#4808) --- project_euler/problem_112/sol1.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/project_euler/problem_112/sol1.py b/project_euler/problem_112/sol1.py index d8cb334c9..b3ea6b356 100644 --- a/project_euler/problem_112/sol1.py +++ b/project_euler/problem_112/sol1.py @@ -47,7 +47,9 @@ def check_bouncy(n: int) -> bool: """ if not isinstance(n, int): raise ValueError("check_bouncy() accepts only integer arguments") - return "".join(sorted(str(n))) != str(n) and "".join(sorted(str(n)))[::-1] != str(n) + str_n = str(n) + sorted_str_n = "".join(sorted(str_n)) + return sorted_str_n != str_n and sorted_str_n[::-1] != str_n def solution(percent: float = 99) -> int: From d324f91fe75cc859335ee1f7c9c6307d958d0558 Mon Sep 17 00:00:00 2001 From: Parth Satodiya Date: Thu, 7 Oct 2021 20:48:23 +0530 Subject: [PATCH 047/726] Fix mypy errors for data_structures->linked_list directory files (#4927) --- data_structures/linked_list/__init__.py | 11 +++++++---- .../linked_list/circular_linked_list.py | 14 +++++++------- data_structures/linked_list/has_loop.py | 6 +++--- .../linked_list/middle_element_of_linked_list.py | 8 ++++++-- data_structures/linked_list/skip_list.py | 6 +++--- 5 files changed, 26 insertions(+), 19 deletions(-) diff --git a/data_structures/linked_list/__init__.py b/data_structures/linked_list/__init__.py index a5f5537b1..8ae171d71 100644 --- a/data_structures/linked_list/__init__.py +++ b/data_structures/linked_list/__init__.py @@ -6,7 +6,7 @@ Nodes contain data and also may link to other nodes: - Last node: points to null """ -from typing import Any +from typing import Any, Optional class Node: @@ -17,7 +17,7 @@ class Node: class LinkedList: def __init__(self) -> None: - self.head = None + self.head: Optional[Node] = None self.size = 0 def add(self, item: Any) -> None: @@ -25,7 +25,10 @@ class LinkedList: self.size += 1 def remove(self) -> Any: - if self.is_empty(): + # Switched 'self.is_empty()' to 'self.head is None' + # because mypy was considering the possibility that 'self.head' + # can be None in below else part and giving error + if self.head is None: return None else: item = self.head.item @@ -50,7 +53,7 @@ class LinkedList: else: iterate = self.head item_str = "" - item_list = [] + item_list: list[str] = [] while iterate: item_list.append(str(iterate.item)) iterate = iterate.next diff --git a/data_structures/linked_list/circular_linked_list.py b/data_structures/linked_list/circular_linked_list.py index f67c1e8f2..42794ba79 100644 --- a/data_structures/linked_list/circular_linked_list.py +++ b/data_structures/linked_list/circular_linked_list.py @@ -1,10 +1,10 @@ -from typing import Any +from typing import Any, Iterator, Optional class Node: def __init__(self, data: Any): - self.data = data - self.next = None + self.data: Any = data + self.next: Optional[Node] = None class CircularLinkedList: @@ -12,7 +12,7 @@ class CircularLinkedList: self.head = None self.tail = None - def __iter__(self): + def __iter__(self) -> Iterator[Any]: node = self.head while self.head: yield node.data @@ -54,10 +54,10 @@ class CircularLinkedList: def delete_front(self): return self.delete_nth(0) - def delete_tail(self) -> None: + def delete_tail(self) -> Any: return self.delete_nth(len(self) - 1) - def delete_nth(self, index: int = 0): + def delete_nth(self, index: int = 0) -> Any: if not 0 <= index < len(self): raise IndexError("list index out of range.") delete_node = self.head @@ -76,7 +76,7 @@ class CircularLinkedList: self.tail = temp return delete_node.data - def is_empty(self): + def is_empty(self) -> bool: return len(self) == 0 diff --git a/data_structures/linked_list/has_loop.py b/data_structures/linked_list/has_loop.py index 405ece7e2..a155ab4c7 100644 --- a/data_structures/linked_list/has_loop.py +++ b/data_structures/linked_list/has_loop.py @@ -1,4 +1,4 @@ -from typing import Any +from typing import Any, Optional class ContainsLoopError(Exception): @@ -7,8 +7,8 @@ class ContainsLoopError(Exception): class Node: def __init__(self, data: Any) -> None: - self.data = data - self.next_node = None + self.data: Any = data + self.next_node: Optional[Node] = None def __iter__(self): node = self diff --git a/data_structures/linked_list/middle_element_of_linked_list.py b/data_structures/linked_list/middle_element_of_linked_list.py index 185c4ccbb..296696897 100644 --- a/data_structures/linked_list/middle_element_of_linked_list.py +++ b/data_structures/linked_list/middle_element_of_linked_list.py @@ -1,5 +1,8 @@ +from typing import Optional + + class Node: - def __init__(self, data: int) -> int: + def __init__(self, data: int) -> None: self.data = data self.next = None @@ -14,7 +17,7 @@ class LinkedList: self.head = new_node return self.head.data - def middle_element(self) -> int: + def middle_element(self) -> Optional[int]: """ >>> link = LinkedList() >>> link.middle_element() @@ -54,6 +57,7 @@ class LinkedList: return slow_pointer.data else: print("No element found.") + return None if __name__ == "__main__": diff --git a/data_structures/linked_list/skip_list.py b/data_structures/linked_list/skip_list.py index ee0b44607..be30592ec 100644 --- a/data_structures/linked_list/skip_list.py +++ b/data_structures/linked_list/skip_list.py @@ -5,14 +5,14 @@ https://epaperpress.com/sortsearch/download/skiplist.pdf from __future__ import annotations from random import random -from typing import Generic, TypeVar +from typing import Generic, Optional, TypeVar, Union KT = TypeVar("KT") VT = TypeVar("VT") class Node(Generic[KT, VT]): - def __init__(self, key: KT, value: VT): + def __init__(self, key: Union[KT, str] = "root", value: Optional[VT] = None): self.key = key self.value = value self.forward: list[Node[KT, VT]] = [] @@ -49,7 +49,7 @@ class Node(Generic[KT, VT]): class SkipList(Generic[KT, VT]): def __init__(self, p: float = 0.5, max_level: int = 16): - self.head = Node("root", None) + self.head: Node[KT, VT] = Node[KT, VT]() self.level = 0 self.p = p self.max_level = max_level From 77b243e62b09cdf6201916af6762b03c54d8f77a Mon Sep 17 00:00:00 2001 From: Lewis Tian Date: Thu, 7 Oct 2021 23:20:32 +0800 Subject: [PATCH 048/726] bugfix: Add empty list detection for find_max/min (#4881) * bugfix: Add empty list detection for find_max/min * fix shebangs check --- maths/find_max.py | 20 ++++++++++++------- maths/find_max_recursion.py | 39 ++++++++++++++++++++++++++++++++++--- maths/find_min.py | 21 ++++++++++++++------ maths/find_min_recursion.py | 39 ++++++++++++++++++++++++++++++++++--- 4 files changed, 100 insertions(+), 19 deletions(-) diff --git a/maths/find_max.py b/maths/find_max.py index 4d92e37eb..684fbe816 100644 --- a/maths/find_max.py +++ b/maths/find_max.py @@ -1,7 +1,7 @@ -# NguyenU +from __future__ import annotations -def find_max(nums): +def find_max(nums: list[int | float]) -> int | float: """ >>> for nums in ([3, 2, 1], [-3, -2, -1], [3, -3, 0], [3.0, 3.1, 2.9]): ... find_max(nums) == max(nums) @@ -9,7 +9,15 @@ def find_max(nums): True True True + >>> find_max([2, 4, 9, 7, 19, 94, 5]) + 94 + >>> find_max([]) + Traceback (most recent call last): + ... + ValueError: find_max() arg is an empty sequence """ + if len(nums) == 0: + raise ValueError("find_max() arg is an empty sequence") max_num = nums[0] for x in nums: if x > max_num: @@ -17,9 +25,7 @@ def find_max(nums): return max_num -def main(): - print(find_max([2, 4, 9, 7, 19, 94, 5])) # 94 - - if __name__ == "__main__": - main() + import doctest + + doctest.testmod(verbose=True) diff --git a/maths/find_max_recursion.py b/maths/find_max_recursion.py index 03fb81950..629932e08 100644 --- a/maths/find_max_recursion.py +++ b/maths/find_max_recursion.py @@ -1,5 +1,8 @@ +from __future__ import annotations + + # Divide and Conquer algorithm -def find_max(nums, left, right): +def find_max(nums: list[int | float], left: int, right: int) -> int | float: """ find max value in list :param nums: contains elements @@ -7,10 +10,39 @@ def find_max(nums, left, right): :param right: index of last element :return: max in nums + >>> for nums in ([3, 2, 1], [-3, -2, -1], [3, -3, 0], [3.0, 3.1, 2.9]): + ... find_max(nums, 0, len(nums) - 1) == max(nums) + True + True + True + True >>> nums = [1, 3, 5, 7, 9, 2, 4, 6, 8, 10] >>> find_max(nums, 0, len(nums) - 1) == max(nums) True + >>> find_max([], 0, 0) + Traceback (most recent call last): + ... + ValueError: find_max() arg is an empty sequence + >>> find_max(nums, 0, len(nums)) == max(nums) + Traceback (most recent call last): + ... + IndexError: list index out of range + >>> find_max(nums, -len(nums), -1) == max(nums) + True + >>> find_max(nums, -len(nums) - 1, -1) == max(nums) + Traceback (most recent call last): + ... + IndexError: list index out of range """ + if len(nums) == 0: + raise ValueError("find_max() arg is an empty sequence") + if ( + left >= len(nums) + or left < -len(nums) + or right >= len(nums) + or right < -len(nums) + ): + raise IndexError("list index out of range") if left == right: return nums[left] mid = (left + right) >> 1 # the middle @@ -21,5 +53,6 @@ def find_max(nums, left, right): if __name__ == "__main__": - nums = [1, 3, 5, 7, 9, 2, 4, 6, 8, 10] - assert find_max(nums, 0, len(nums) - 1) == 10 + import doctest + + doctest.testmod(verbose=True) diff --git a/maths/find_min.py b/maths/find_min.py index 2af2e44ba..228205ed7 100644 --- a/maths/find_min.py +++ b/maths/find_min.py @@ -1,4 +1,7 @@ -def find_min(nums): +from __future__ import annotations + + +def find_min(nums: list[int | float]) -> int | float: """ Find Minimum Number in a List :param nums: contains elements @@ -10,7 +13,15 @@ def find_min(nums): True True True + >>> find_min([0, 1, 2, 3, 4, 5, -3, 24, -56]) + -56 + >>> find_min([]) + Traceback (most recent call last): + ... + ValueError: find_min() arg is an empty sequence """ + if len(nums) == 0: + raise ValueError("find_min() arg is an empty sequence") min_num = nums[0] for num in nums: if min_num > num: @@ -18,9 +29,7 @@ def find_min(nums): return min_num -def main(): - assert find_min([0, 1, 2, 3, 4, 5, -3, 24, -56]) == -56 - - if __name__ == "__main__": - main() + import doctest + + doctest.testmod(verbose=True) diff --git a/maths/find_min_recursion.py b/maths/find_min_recursion.py index 4488967cc..4d11015ef 100644 --- a/maths/find_min_recursion.py +++ b/maths/find_min_recursion.py @@ -1,5 +1,8 @@ +from __future__ import annotations + + # Divide and Conquer algorithm -def find_min(nums, left, right): +def find_min(nums: list[int | float], left: int, right: int) -> int | float: """ find min value in list :param nums: contains elements @@ -7,10 +10,39 @@ def find_min(nums, left, right): :param right: index of last element :return: min in nums + >>> for nums in ([3, 2, 1], [-3, -2, -1], [3, -3, 0], [3.0, 3.1, 2.9]): + ... find_min(nums, 0, len(nums) - 1) == min(nums) + True + True + True + True >>> nums = [1, 3, 5, 7, 9, 2, 4, 6, 8, 10] >>> find_min(nums, 0, len(nums) - 1) == min(nums) True + >>> find_min([], 0, 0) + Traceback (most recent call last): + ... + ValueError: find_min() arg is an empty sequence + >>> find_min(nums, 0, len(nums)) == min(nums) + Traceback (most recent call last): + ... + IndexError: list index out of range + >>> find_min(nums, -len(nums), -1) == min(nums) + True + >>> find_min(nums, -len(nums) - 1, -1) == min(nums) + Traceback (most recent call last): + ... + IndexError: list index out of range """ + if len(nums) == 0: + raise ValueError("find_min() arg is an empty sequence") + if ( + left >= len(nums) + or left < -len(nums) + or right >= len(nums) + or right < -len(nums) + ): + raise IndexError("list index out of range") if left == right: return nums[left] mid = (left + right) >> 1 # the middle @@ -21,5 +53,6 @@ def find_min(nums, left, right): if __name__ == "__main__": - nums = [1, 3, 5, 7, 9, 2, 4, 6, 8, 10] - assert find_min(nums, 0, len(nums) - 1) == 1 + import doctest + + doctest.testmod(verbose=True) From 7578e0b920831c0ee3274cbfdaa6dc2b6a82cc97 Mon Sep 17 00:00:00 2001 From: Rohanrbharadwaj <89947037+Rohanrbharadwaj@users.noreply.github.com> Date: Sun, 10 Oct 2021 23:22:38 +0530 Subject: [PATCH 049/726] Used in-built method (#5183) * Used in-built method * Delete swap_case.py Co-authored-by: Christian Clauss --- strings/swap_case.py | 37 ------------------------------------- 1 file changed, 37 deletions(-) delete mode 100644 strings/swap_case.py diff --git a/strings/swap_case.py b/strings/swap_case.py deleted file mode 100644 index 107fda4b5..000000000 --- a/strings/swap_case.py +++ /dev/null @@ -1,37 +0,0 @@ -""" -This algorithm helps you to swap cases. - -User will give input and then program will perform swap cases. - -In other words, convert all lowercase letters to uppercase letters and vice versa. -For example: -1. Please input sentence: Algorithm.Python@89 - aLGORITHM.pYTHON@89 -2. Please input sentence: github.com/mayur200 - GITHUB.COM/MAYUR200 - -""" - - -def swap_case(sentence: str) -> str: - """ - This function will convert all lowercase letters to uppercase letters - and vice versa. - - >>> swap_case('Algorithm.Python@89') - 'aLGORITHM.pYTHON@89' - """ - new_string = "" - for char in sentence: - if char.isupper(): - new_string += char.lower() - elif char.islower(): - new_string += char.upper() - else: - new_string += char - - return new_string - - -if __name__ == "__main__": - print(swap_case(input("Please input sentence: "))) From 97562c19f8f1f079714b393b1b2afa895e930916 Mon Sep 17 00:00:00 2001 From: Rohanrbharadwaj <89947037+Rohanrbharadwaj@users.noreply.github.com> Date: Sun, 10 Oct 2021 23:30:04 +0530 Subject: [PATCH 050/726] Added doctest (#5182) --- strings/indian_phone_validator.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/strings/indian_phone_validator.py b/strings/indian_phone_validator.py index d544e9266..7f3fda5db 100644 --- a/strings/indian_phone_validator.py +++ b/strings/indian_phone_validator.py @@ -16,6 +16,8 @@ def indian_phone_validator(phone: str) -> bool: True >>> indian_phone_validator("+91-1234567899") False + >>> indian_phone_validator("+91-9876543218") + True """ pat = re.compile(r"^(\+91[\-\s]?)?[0]?(91)?[789]\d{9}$") match = re.search(pat, phone) From 729b4d875a07bd15bc6e5e8a3c79f16fa1e003e6 Mon Sep 17 00:00:00 2001 From: Jordan Rinder Date: Sun, 10 Oct 2021 14:02:44 -0400 Subject: [PATCH 051/726] Add Sylvester's sequence to maths (#5171) * Add Sylvester's sequence to maths * Update sylvester_sequence.py Co-authored-by: Christian Clauss --- maths/sylvester_sequence.py | 43 +++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 maths/sylvester_sequence.py diff --git a/maths/sylvester_sequence.py b/maths/sylvester_sequence.py new file mode 100644 index 000000000..0cd99affe --- /dev/null +++ b/maths/sylvester_sequence.py @@ -0,0 +1,43 @@ +""" + +Calculates the nth number in Sylvester's sequence + +Source: + https://en.wikipedia.org/wiki/Sylvester%27s_sequence + +""" + + +def sylvester(number: int) -> int: + """ + :param number: nth number to calculate in the sequence + :return: the nth number in Sylvester's sequence + + >>> sylvester(8) + 113423713055421844361000443 + + >>> sylvester(-1) + Traceback (most recent call last): + ... + ValueError: The input value of [n=-1] has to be > 0 + + >>> sylvester(8.0) + Traceback (most recent call last): + ... + AssertionError: The input value of [n=8.0] is not an integer + """ + assert isinstance(number, int), f"The input value of [n={number}] is not an integer" + + if number == 1: + return 2 + elif number < 1: + raise ValueError(f"The input value of [n={number}] has to be > 0") + else: + num = sylvester(number - 1) + lower = num - 1 + upper = num + return lower * upper + 1 + + +if __name__ == "__main__": + print(f"The 8th number in Sylvester's sequence: {sylvester(8)}") From fadb97609f7b84f83a47fcf8a253145562469b23 Mon Sep 17 00:00:00 2001 From: Sidhaant Thakker <59668364+SidhaantThakker@users.noreply.github.com> Date: Mon, 11 Oct 2021 21:59:52 +0530 Subject: [PATCH 052/726] Add carrier concentrations calculation algorithm (#4791) * added carrier concentrations algorithm * Add more references Added more references to the carrier concentrations file * Update electronics/carrier_concentration.py Co-authored-by: John Law * Update electronics/carrier_concentration.py Co-authored-by: John Law Co-authored-by: John Law --- electronics/carrier_concentration.py | 75 ++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 electronics/carrier_concentration.py diff --git a/electronics/carrier_concentration.py b/electronics/carrier_concentration.py new file mode 100644 index 000000000..87bcad8df --- /dev/null +++ b/electronics/carrier_concentration.py @@ -0,0 +1,75 @@ +# https://en.wikipedia.org/wiki/Charge_carrier_density +# https://www.pveducation.org/pvcdrom/pn-junctions/equilibrium-carrier-concentration +# http://www.ece.utep.edu/courses/ee3329/ee3329/Studyguide/ToC/Fundamentals/Carriers/concentrations.html + +from __future__ import annotations + + +def carrier_concentration( + electron_conc: float, + hole_conc: float, + intrinsic_conc: float, +) -> tuple: + """ + This function can calculate any one of the three - + 1. Electron Concentration + 2, Hole Concentration + 3. Intrinsic Concentration + given the other two. + Examples - + >>> carrier_concentration(electron_conc=25, hole_conc=100, intrinsic_conc=0) + ('intrinsic_conc', 50.0) + >>> carrier_concentration(electron_conc=0, hole_conc=1600, intrinsic_conc=200) + ('electron_conc', 25.0) + >>> carrier_concentration(electron_conc=1000, hole_conc=0, intrinsic_conc=1200) + ('hole_conc', 1440.0) + >>> carrier_concentration(electron_conc=1000, hole_conc=400, intrinsic_conc=1200) + Traceback (most recent call last): + File "", line 37, in + ValueError: You cannot supply more or less than 2 values + >>> carrier_concentration(electron_conc=-1000, hole_conc=0, intrinsic_conc=1200) + Traceback (most recent call last): + File "", line 40, in + ValueError: Electron concentration cannot be negative in a semiconductor + >>> carrier_concentration(electron_conc=0, hole_conc=-400, intrinsic_conc=1200) + Traceback (most recent call last): + File "", line 44, in + ValueError: Hole concentration cannot be negative in a semiconductor + >>> carrier_concentration(electron_conc=0, hole_conc=400, intrinsic_conc=-1200) + Traceback (most recent call last): + File "", line 48, in + ValueError: Intrinsic concentration cannot be negative in a semiconductor + """ + if (electron_conc, hole_conc, intrinsic_conc).count(0) != 1: + raise ValueError("You cannot supply more or less than 2 values") + elif electron_conc < 0: + raise ValueError("Electron concentration cannot be negative in a semiconductor") + elif hole_conc < 0: + raise ValueError("Hole concentration cannot be negative in a semiconductor") + elif intrinsic_conc < 0: + raise ValueError( + "Intrinsic concentration cannot be negative in a semiconductor" + ) + elif electron_conc == 0: + return ( + "electron_conc", + intrinsic_conc ** 2 / hole_conc, + ) + elif hole_conc == 0: + return ( + "hole_conc", + intrinsic_conc ** 2 / electron_conc, + ) + elif intrinsic_conc == 0: + return ( + "intrinsic_conc", + (electron_conc * hole_conc) ** 0.5, + ) + else: + return (-1, -1) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From e311b02e704891b2f31a1e2c8fe2df77a032b09b Mon Sep 17 00:00:00 2001 From: Muhammad Hammad Sani <58339378+mhammadsaani@users.noreply.github.com> Date: Mon, 11 Oct 2021 21:33:06 +0500 Subject: [PATCH 053/726] Remove unnecessary branch (#4824) * Algorithm Optimized * Update divide_and_conquer/inversions.py Co-authored-by: John Law * Update divide_and_conquer/inversions.py Co-authored-by: John Law * Update divide_and_conquer/inversions.py Co-authored-by: John Law Co-authored-by: John Law --- divide_and_conquer/inversions.py | 36 +++++++++----------------------- 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/divide_and_conquer/inversions.py b/divide_and_conquer/inversions.py index 9bb656229..b47145602 100644 --- a/divide_and_conquer/inversions.py +++ b/divide_and_conquer/inversions.py @@ -2,31 +2,25 @@ Given an array-like data structure A[1..n], how many pairs (i, j) for all 1 <= i < j <= n such that A[i] > A[j]? These pairs are called inversions. Counting the number of such inversions in an array-like -object is the important. Among other things, counting inversions can help -us determine how close a given array is to being sorted - +object is the important. Among other things, counting inversions can help +us determine how close a given array is to being sorted. In this implementation, I provide two algorithms, a divide-and-conquer algorithm which runs in nlogn and the brute-force n^2 algorithm. - """ def count_inversions_bf(arr): """ Counts the number of inversions using a a naive brute-force algorithm - Parameters ---------- arr: arr: array-like, the list containing the items for which the number of inversions is desired. The elements of `arr` must be comparable. - Returns ------- num_inversions: The total number of inversions in `arr` - Examples --------- - >>> count_inversions_bf([1, 4, 2, 4, 1]) 4 >>> count_inversions_bf([1, 1, 2, 4, 4]) @@ -49,20 +43,16 @@ def count_inversions_bf(arr): def count_inversions_recursive(arr): """ Counts the number of inversions using a divide-and-conquer algorithm - Parameters ----------- arr: array-like, the list containing the items for which the number of inversions is desired. The elements of `arr` must be comparable. - Returns ------- C: a sorted copy of `arr`. num_inversions: int, the total number of inversions in 'arr' - Examples -------- - >>> count_inversions_recursive([1, 4, 2, 4, 1]) ([1, 1, 2, 4, 4], 4) >>> count_inversions_recursive([1, 1, 2, 4, 4]) @@ -72,40 +62,34 @@ def count_inversions_recursive(arr): """ if len(arr) <= 1: return arr, 0 - else: - mid = len(arr) // 2 - P = arr[0:mid] - Q = arr[mid:] + mid = len(arr) // 2 + P = arr[0:mid] + Q = arr[mid:] - A, inversion_p = count_inversions_recursive(P) - B, inversions_q = count_inversions_recursive(Q) - C, cross_inversions = _count_cross_inversions(A, B) + A, inversion_p = count_inversions_recursive(P) + B, inversions_q = count_inversions_recursive(Q) + C, cross_inversions = _count_cross_inversions(A, B) - num_inversions = inversion_p + inversions_q + cross_inversions - return C, num_inversions + num_inversions = inversion_p + inversions_q + cross_inversions + return C, num_inversions def _count_cross_inversions(P, Q): """ Counts the inversions across two sorted arrays. And combine the two arrays into one sorted array - For all 1<= i<=len(P) and for all 1 <= j <= len(Q), if P[i] > Q[j], then (i, j) is a cross inversion - Parameters ---------- P: array-like, sorted in non-decreasing order Q: array-like, sorted in non-decreasing order - Returns ------ R: array-like, a sorted array of the elements of `P` and `Q` num_inversion: int, the number of inversions across `P` and `Q` - Examples -------- - >>> _count_cross_inversions([1, 2, 3], [0, 2, 5]) ([0, 1, 2, 2, 3, 5], 4) >>> _count_cross_inversions([1, 2, 3], [3, 4, 5]) From bcfca67faa120cc4cb42775af302d6d52d3a3f1e Mon Sep 17 00:00:00 2001 From: Joyce Date: Tue, 12 Oct 2021 00:33:44 +0800 Subject: [PATCH 054/726] [mypy] fix type annotations for all Project Euler problems (#4747) * [mypy] fix type annotations for problem003/sol1 and problem003/sol3 * [mypy] fix type annotations for project euler problem007/sol2 * [mypy] fix type annotations for project euler problem008/sol2 * [mypy] fix type annotations for project euler problem009/sol1 * [mypy] fix type annotations for project euler problem014/sol1 * [mypy] fix type annotations for project euler problem 025/sol2 * [mypy] fix type annotations for project euler problem026/sol1.py * [mypy] fix type annotations for project euler problem037/sol1 * [mypy] fix type annotations for project euler problem044/sol1 * [mypy] fix type annotations for project euler problem046/sol1 * [mypy] fix type annotations for project euler problem051/sol1 * [mypy] fix type annotations for project euler problem074/sol2 * [mypy] fix type annotations for project euler problem080/sol1 * [mypy] fix type annotations for project euler problem099/sol1 * [mypy] fix type annotations for project euler problem101/sol1 * [mypy] fix type annotations for project euler problem188/sol1 * [mypy] fix type annotations for project euler problem191/sol1 * [mypy] fix type annotations for project euler problem207/sol1 * [mypy] fix type annotations for project euler problem551/sol1 --- project_euler/problem_003/sol1.py | 4 ++-- project_euler/problem_003/sol3.py | 2 +- project_euler/problem_007/sol2.py | 2 +- project_euler/problem_008/sol2.py | 4 +++- project_euler/problem_009/sol1.py | 4 ++++ project_euler/problem_014/sol1.py | 2 +- project_euler/problem_025/sol2.py | 3 ++- project_euler/problem_026/sol1.py | 2 +- project_euler/problem_037/sol1.py | 2 +- project_euler/problem_044/sol1.py | 2 ++ project_euler/problem_046/sol1.py | 2 ++ project_euler/problem_051/sol1.py | 8 +++++--- project_euler/problem_074/sol2.py | 4 ++-- project_euler/problem_080/sol1.py | 5 +++-- project_euler/problem_099/sol1.py | 10 ++++++---- project_euler/problem_101/sol1.py | 2 +- project_euler/problem_188/sol1.py | 4 ++-- project_euler/problem_191/sol1.py | 2 +- project_euler/problem_207/sol1.py | 2 +- project_euler/problem_551/sol1.py | 3 ++- 20 files changed, 43 insertions(+), 26 deletions(-) diff --git a/project_euler/problem_003/sol1.py b/project_euler/problem_003/sol1.py index 3441dbf9e..1f3299842 100644 --- a/project_euler/problem_003/sol1.py +++ b/project_euler/problem_003/sol1.py @@ -92,8 +92,8 @@ def solution(n: int = 600851475143) -> int: return n for i in range(3, int(math.sqrt(n)) + 1, 2): if n % i == 0: - if isprime(n / i): - max_number = n / i + if isprime(n // i): + max_number = n // i break elif isprime(i): max_number = i diff --git a/project_euler/problem_003/sol3.py b/project_euler/problem_003/sol3.py index bc6f1d2f6..e13a0eb74 100644 --- a/project_euler/problem_003/sol3.py +++ b/project_euler/problem_003/sol3.py @@ -57,7 +57,7 @@ def solution(n: int = 600851475143) -> int: i += 1 ans = i while n % i == 0: - n = n / i + n = n // i i += 1 return int(ans) diff --git a/project_euler/problem_007/sol2.py b/project_euler/problem_007/sol2.py index b395c631b..20c2ddf21 100644 --- a/project_euler/problem_007/sol2.py +++ b/project_euler/problem_007/sol2.py @@ -73,7 +73,7 @@ def solution(nth: int = 10001) -> int: raise TypeError("Parameter nth must be int or castable to int.") from None if nth <= 0: raise ValueError("Parameter nth must be greater than or equal to one.") - primes = [] + primes: list[int] = [] num = 2 while len(primes) < nth: if isprime(num): diff --git a/project_euler/problem_008/sol2.py b/project_euler/problem_008/sol2.py index 7f0540263..889c3a314 100644 --- a/project_euler/problem_008/sol2.py +++ b/project_euler/problem_008/sol2.py @@ -70,7 +70,9 @@ 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) + # mypy cannot properly interpret reduce + int(reduce(lambda x, y: str(int(x) * int(y)), n[i : i + 13])) + for i in range(len(n) - 12) ) diff --git a/project_euler/problem_009/sol1.py b/project_euler/problem_009/sol1.py index c50dfeecf..83c88acf1 100644 --- a/project_euler/problem_009/sol1.py +++ b/project_euler/problem_009/sol1.py @@ -36,6 +36,8 @@ def solution() -> int: if (a ** 2) + (b ** 2) == (c ** 2): return a * b * c + return -1 + def solution_fast() -> int: """ @@ -55,6 +57,8 @@ def solution_fast() -> int: if a < b < c and (a ** 2) + (b ** 2) == (c ** 2): return a * b * c + return -1 + def benchmark() -> None: """ diff --git a/project_euler/problem_014/sol1.py b/project_euler/problem_014/sol1.py index 1745ec931..43aa4e726 100644 --- a/project_euler/problem_014/sol1.py +++ b/project_euler/problem_014/sol1.py @@ -44,7 +44,7 @@ def solution(n: int = 1000000) -> int: while number > 1: if number % 2 == 0: - number /= 2 + number //= 2 counter += 1 else: number = (3 * number) + 1 diff --git a/project_euler/problem_025/sol2.py b/project_euler/problem_025/sol2.py index ed3b54bb3..b041afd98 100644 --- a/project_euler/problem_025/sol2.py +++ b/project_euler/problem_025/sol2.py @@ -23,9 +23,10 @@ The 12th term, F12, is the first term to contain three digits. What is the index of the first term in the Fibonacci sequence to contain 1000 digits? """ +from typing import Generator -def fibonacci_generator() -> int: +def fibonacci_generator() -> Generator[int, None, None]: """ A generator that produces numbers in the Fibonacci sequence diff --git a/project_euler/problem_026/sol1.py b/project_euler/problem_026/sol1.py index 64e0bbfef..75d48df79 100644 --- a/project_euler/problem_026/sol1.py +++ b/project_euler/problem_026/sol1.py @@ -39,7 +39,7 @@ def solution(numerator: int = 1, digit: int = 1000) -> int: longest_list_length = 0 for divide_by_number in range(numerator, digit + 1): - has_been_divided = [] + has_been_divided: list[int] = [] now_divide = numerator for division_cycle in range(1, digit + 1): if now_divide in has_been_divided: diff --git a/project_euler/problem_037/sol1.py b/project_euler/problem_037/sol1.py index 5423aac37..0411ad41b 100644 --- a/project_euler/problem_037/sol1.py +++ b/project_euler/problem_037/sol1.py @@ -76,7 +76,7 @@ def compute_truncated_primes(count: int = 11) -> list[int]: >>> compute_truncated_primes(11) [23, 37, 53, 73, 313, 317, 373, 797, 3137, 3797, 739397] """ - list_truncated_primes = [] + list_truncated_primes: list[int] = [] num = 13 while len(list_truncated_primes) != count: if validate(num): diff --git a/project_euler/problem_044/sol1.py b/project_euler/problem_044/sol1.py index d3ae6476d..3b75b6a56 100644 --- a/project_euler/problem_044/sol1.py +++ b/project_euler/problem_044/sol1.py @@ -42,6 +42,8 @@ def solution(limit: int = 5000) -> int: if is_pentagonal(a) and is_pentagonal(b): return b + return -1 + if __name__ == "__main__": print(f"{solution() = }") diff --git a/project_euler/problem_046/sol1.py b/project_euler/problem_046/sol1.py index 3fdf56755..550c4c7c4 100644 --- a/project_euler/problem_046/sol1.py +++ b/project_euler/problem_046/sol1.py @@ -85,6 +85,8 @@ def compute_nums(n: int) -> list[int]: if len(list_nums) == n: return list_nums + return [] + def solution() -> int: """Return the solution to the problem""" diff --git a/project_euler/problem_051/sol1.py b/project_euler/problem_051/sol1.py index 5f607e3ff..eedb02379 100644 --- a/project_euler/problem_051/sol1.py +++ b/project_euler/problem_051/sol1.py @@ -63,12 +63,12 @@ def digit_replacements(number: int) -> list[list[int]]: >>> digit_replacements(3112) [[3002, 3112, 3222, 3332, 3442, 3552, 3662, 3772, 3882, 3992]] """ - number = str(number) + number_str = str(number) replacements = [] digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] - for duplicate in Counter(number) - Counter(set(number)): - family = [int(number.replace(duplicate, digit)) for digit in digits] + for duplicate in Counter(number_str) - Counter(set(number_str)): + family = [int(number_str.replace(duplicate, digit)) for digit in digits] replacements.append(family) return replacements @@ -106,6 +106,8 @@ def solution(family_length: int = 8) -> int: return min(primes_in_family) + return -1 + if __name__ == "__main__": print(solution()) diff --git a/project_euler/problem_074/sol2.py b/project_euler/problem_074/sol2.py index 689593277..55e67c6b9 100644 --- a/project_euler/problem_074/sol2.py +++ b/project_euler/problem_074/sol2.py @@ -20,8 +20,8 @@ counter increases. """ -factorial_cache = {} -factorial_sum_cache = {} +factorial_cache: dict[int, int] = {} +factorial_sum_cache: dict[int, int] = {} def factorial(a: int) -> int: diff --git a/project_euler/problem_080/sol1.py b/project_euler/problem_080/sol1.py index 517be3fc0..916998bdd 100644 --- a/project_euler/problem_080/sol1.py +++ b/project_euler/problem_080/sol1.py @@ -26,8 +26,8 @@ def solution() -> int: sqrt_number = number.sqrt(decimal_context) 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) + sqrt_number_str = str(sqrt_number)[2:101] + answer += sum(int(x) for x in sqrt_number_str) return answer @@ -35,3 +35,4 @@ if __name__ == "__main__": import doctest doctest.testmod() + print(f"{solution() = }") diff --git a/project_euler/problem_099/sol1.py b/project_euler/problem_099/sol1.py index 88912e1f0..bf5621c65 100644 --- a/project_euler/problem_099/sol1.py +++ b/project_euler/problem_099/sol1.py @@ -22,12 +22,14 @@ def solution(data_file: str = "base_exp.txt") -> int: >>> solution() 709 """ - largest = [0, 0] + largest: float = 0 + result = 0 for i, line in enumerate(open(os.path.join(os.path.dirname(__file__), data_file))): a, x = list(map(int, line.split(","))) - if x * log10(a) > largest[0]: - largest = [x * log10(a), i + 1] - return largest[1] + if x * log10(a) > largest: + largest = x * log10(a) + result = i + 1 + return result if __name__ == "__main__": diff --git a/project_euler/problem_101/sol1.py b/project_euler/problem_101/sol1.py index 553f8f442..14013c435 100644 --- a/project_euler/problem_101/sol1.py +++ b/project_euler/problem_101/sol1.py @@ -202,7 +202,7 @@ def solution(func: Callable[[int], int] = question_function, order: int = 10) -> ] ret: int = 0 - poly: int + poly: Callable[[int], int] x_val: int for poly in polynomials: diff --git a/project_euler/problem_188/sol1.py b/project_euler/problem_188/sol1.py index 6473c6362..c8cd9eb10 100644 --- a/project_euler/problem_188/sol1.py +++ b/project_euler/problem_188/sol1.py @@ -19,7 +19,7 @@ References: """ -# small helper function for modular exponentiation +# small helper function for modular exponentiation (fast exponentiation algorithm) def _modexpt(base: int, exponent: int, modulo_value: int) -> int: """ Returns the modular exponentiation, that is the value @@ -36,7 +36,7 @@ def _modexpt(base: int, exponent: int, modulo_value: int) -> int: if exponent == 1: return base if exponent % 2 == 0: - x = _modexpt(base, exponent / 2, modulo_value) % modulo_value + x = _modexpt(base, exponent // 2, modulo_value) % modulo_value return (x * x) % modulo_value else: return (base * _modexpt(base, exponent - 1, modulo_value)) % modulo_value diff --git a/project_euler/problem_191/sol1.py b/project_euler/problem_191/sol1.py index 38325b363..6bff9d54e 100644 --- a/project_euler/problem_191/sol1.py +++ b/project_euler/problem_191/sol1.py @@ -26,7 +26,7 @@ References: """ -cache = {} +cache: dict[tuple[int, int, int], int] = {} def _calculate(days: int, absent: int, late: int) -> int: diff --git a/project_euler/problem_207/sol1.py b/project_euler/problem_207/sol1.py index fb901fde1..99d1a9174 100644 --- a/project_euler/problem_207/sol1.py +++ b/project_euler/problem_207/sol1.py @@ -90,7 +90,7 @@ def solution(max_proportion: float = 1 / 12345) -> int: perfect_partitions += 1 if perfect_partitions > 0: if perfect_partitions / total_partitions < max_proportion: - return partition_candidate + return int(partition_candidate) integer += 1 diff --git a/project_euler/problem_551/sol1.py b/project_euler/problem_551/sol1.py index 71956691a..005d2e985 100644 --- a/project_euler/problem_551/sol1.py +++ b/project_euler/problem_551/sol1.py @@ -12,9 +12,10 @@ You are given a(10^6) = 31054319. Find a(10^15) """ + ks = [k for k in range(2, 20 + 1)] base = [10 ** k for k in range(ks[-1] + 1)] -memo = {} +memo: dict[int, dict[int, list[list[int]]]] = {} def next_term(a_i, k, i, n): From abaa0d754b8dc24abacac2a4d7ecade2d3ddacb6 Mon Sep 17 00:00:00 2001 From: scfenton6 <91698851+scfenton6@users.noreply.github.com> Date: Mon, 11 Oct 2021 18:34:30 +0200 Subject: [PATCH 055/726] Add type annotations (#4814) --- data_structures/disjoint_set/disjoint_set.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/data_structures/disjoint_set/disjoint_set.py b/data_structures/disjoint_set/disjoint_set.py index bf5ab415d..f8500bf2c 100644 --- a/data_structures/disjoint_set/disjoint_set.py +++ b/data_structures/disjoint_set/disjoint_set.py @@ -1,17 +1,19 @@ """ - disjoint set + Disjoint set. Reference: https://en.wikipedia.org/wiki/Disjoint-set_data_structure """ class Node: - def __init__(self, data): + def __init__(self, data: int) -> None: self.data = data + self.rank: int + self.parent: Node -def make_set(x): +def make_set(x: Node) -> None: """ - make x as a set. + Make x as a set. """ # rank is the distance from x to its' parent # root's rank is 0 @@ -19,9 +21,9 @@ def make_set(x): x.parent = x -def union_set(x, y): +def union_set(x: Node, y: Node) -> None: """ - union two sets. + Union of two sets. set with bigger rank should be parent, so that the disjoint set tree will be more flat. """ @@ -37,9 +39,9 @@ def union_set(x, y): y.rank += 1 -def find_set(x): +def find_set(x: Node) -> Node: """ - return the parent of x + Return the parent of x """ if x != x.parent: x.parent = find_set(x.parent) @@ -57,7 +59,7 @@ def find_python_set(node: Node) -> set: raise ValueError(f"{node.data} is not in {sets}") -def test_disjoint_set(): +def test_disjoint_set() -> None: """ >>> test_disjoint_set() """ From 9586a6a98ef4bad7894bfe31da4fab42f6b3d6cd Mon Sep 17 00:00:00 2001 From: poloso Date: Mon, 11 Oct 2021 11:44:38 -0500 Subject: [PATCH 056/726] Change comments for improved consistency (#5223) * Change comments for improved consistency https://github.com/TheAlgorithms/Python/blob/master/CONTRIBUTING.md#L56 https://github.com/TheAlgorithms/Python/blob/master/CONTRIBUTING.md#L80 https://github.com/TheAlgorithms/Python/blob/master/CONTRIBUTING.md#L87 * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- CONTRIBUTING.md | 2 +- DIRECTORY.md | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 13d330a90..e9cf0e6a1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -53,7 +53,7 @@ Algorithms in this repo should not be how-to examples for existing Python packag Use [pre-commit](https://pre-commit.com/#installation) to automatically format your code to match our coding style: ```bash -python3 -m pip install pre-commit # required only once +python3 -m pip install pre-commit # only required the first time pre-commit install ``` That's it! The plugin will run every time you commit any changes. If there are any errors found during the run, fix them and commit those changes. You can even run the plugin manually on all files: diff --git a/DIRECTORY.md b/DIRECTORY.md index 2e9942b5b..6c227fd2b 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -274,6 +274,7 @@ * [Test Send File](https://github.com/TheAlgorithms/Python/blob/master/file_transfer/tests/test_send_file.py) ## Fractals + * [Julia Sets](https://github.com/TheAlgorithms/Python/blob/master/fractals/julia_sets.py) * [Koch Snowflake](https://github.com/TheAlgorithms/Python/blob/master/fractals/koch_snowflake.py) * [Mandelbrot](https://github.com/TheAlgorithms/Python/blob/master/fractals/mandelbrot.py) * [Sierpinski Triangle](https://github.com/TheAlgorithms/Python/blob/master/fractals/sierpinski_triangle.py) @@ -424,10 +425,12 @@ * [Binomial Distribution](https://github.com/TheAlgorithms/Python/blob/master/maths/binomial_distribution.py) * [Bisection](https://github.com/TheAlgorithms/Python/blob/master/maths/bisection.py) * [Ceil](https://github.com/TheAlgorithms/Python/blob/master/maths/ceil.py) + * [Check Polygon](https://github.com/TheAlgorithms/Python/blob/master/maths/check_polygon.py) * [Chudnovsky Algorithm](https://github.com/TheAlgorithms/Python/blob/master/maths/chudnovsky_algorithm.py) * [Collatz Sequence](https://github.com/TheAlgorithms/Python/blob/master/maths/collatz_sequence.py) * [Combinations](https://github.com/TheAlgorithms/Python/blob/master/maths/combinations.py) * [Decimal Isolate](https://github.com/TheAlgorithms/Python/blob/master/maths/decimal_isolate.py) + * [Double Factorial Iterative](https://github.com/TheAlgorithms/Python/blob/master/maths/double_factorial_iterative.py) * [Double Factorial Recursive](https://github.com/TheAlgorithms/Python/blob/master/maths/double_factorial_recursive.py) * [Entropy](https://github.com/TheAlgorithms/Python/blob/master/maths/entropy.py) * [Euclidean Distance](https://github.com/TheAlgorithms/Python/blob/master/maths/euclidean_distance.py) @@ -511,6 +514,7 @@ * [Sum Of Arithmetic Series](https://github.com/TheAlgorithms/Python/blob/master/maths/sum_of_arithmetic_series.py) * [Sum Of Digits](https://github.com/TheAlgorithms/Python/blob/master/maths/sum_of_digits.py) * [Sum Of Geometric Progression](https://github.com/TheAlgorithms/Python/blob/master/maths/sum_of_geometric_progression.py) + * [Sylvester Sequence](https://github.com/TheAlgorithms/Python/blob/master/maths/sylvester_sequence.py) * [Test Prime Check](https://github.com/TheAlgorithms/Python/blob/master/maths/test_prime_check.py) * [Trapezoidal Rule](https://github.com/TheAlgorithms/Python/blob/master/maths/trapezoidal_rule.py) * [Triplet Sum](https://github.com/TheAlgorithms/Python/blob/master/maths/triplet_sum.py) @@ -928,7 +932,6 @@ * [Reverse Letters](https://github.com/TheAlgorithms/Python/blob/master/strings/reverse_letters.py) * [Reverse Words](https://github.com/TheAlgorithms/Python/blob/master/strings/reverse_words.py) * [Split](https://github.com/TheAlgorithms/Python/blob/master/strings/split.py) - * [Swap Case](https://github.com/TheAlgorithms/Python/blob/master/strings/swap_case.py) * [Upper](https://github.com/TheAlgorithms/Python/blob/master/strings/upper.py) * [Word Occurrence](https://github.com/TheAlgorithms/Python/blob/master/strings/word_occurrence.py) * [Word Patterns](https://github.com/TheAlgorithms/Python/blob/master/strings/word_patterns.py) From 1b0ac73da25915d4cb4d2754f7c12d1b81fc9f90 Mon Sep 17 00:00:00 2001 From: Aman kanojiya <50018596+AMANKANOJIYA@users.noreply.github.com> Date: Tue, 12 Oct 2021 15:21:27 +0530 Subject: [PATCH 057/726] Magnitude and Angle of Vector (#5225) * Magnitude and Angle Core function to find Magnitude and Angle of two Given Vector * Magnitude and Angle with Doctest added Doctest to the functions * Update linear_algebra/src/lib.py Co-authored-by: Christian Clauss * Update linear_algebra/src/lib.py Co-authored-by: Christian Clauss * Changes done and Magnitude and Angle Issues * black Co-authored-by: Christian Clauss --- linear_algebra/src/lib.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/linear_algebra/src/lib.py b/linear_algebra/src/lib.py index 74aeb9137..6a18df5e1 100644 --- a/linear_algebra/src/lib.py +++ b/linear_algebra/src/lib.py @@ -148,6 +148,36 @@ class Vector: else: # error case raise Exception("invalid operand!") + def magnitude(self) -> float: + """ + Magnitude of a Vector + + >>> Vector([2, 3, 4]).magnitude() + 5.385164807134504 + + """ + return sum([i ** 2 for i in self.__components]) ** (1 / 2) + + def angle(self, other: Vector, deg: bool = False) -> float: + """ + find angle between two Vector (self, Vector) + + >>> Vector([3, 4, -1]).angle(Vector([2, -1, 1])) + 1.4906464636572374 + >>> Vector([3, 4, -1]).angle(Vector([2, -1, 1]), deg = True) + 85.40775111366095 + >>> Vector([3, 4, -1]).angle(Vector([2, -1])) + Traceback (most recent call last): + ... + Exception: invalid operand! + """ + num = self * other + den = self.magnitude() * other.magnitude() + if deg: + return math.degrees(math.acos(num / den)) + else: + return math.acos(num / den) + def copy(self) -> Vector: """ copies this vector and returns it. From 943e03fc545f91482dae08d7a2f1335d9d1faf17 Mon Sep 17 00:00:00 2001 From: Raj-Pansuriya <72313592+Raj-Pansuriya@users.noreply.github.com> Date: Thu, 14 Oct 2021 16:21:13 +0530 Subject: [PATCH 058/726] Added Optimal Merge Pattern Algorithm (#5274) * Minor changes due to precommit * Update optimal_merge_pattern.py Co-authored-by: Christian Clauss --- greedy_methods/optimal_merge_pattern.py | 56 +++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 greedy_methods/optimal_merge_pattern.py diff --git a/greedy_methods/optimal_merge_pattern.py b/greedy_methods/optimal_merge_pattern.py new file mode 100644 index 000000000..911e1966f --- /dev/null +++ b/greedy_methods/optimal_merge_pattern.py @@ -0,0 +1,56 @@ +""" +This is a pure Python implementation of the greedy-merge-sort algorithm +reference: https://www.geeksforgeeks.org/optimal-file-merge-patterns/ + +For doctests run following command: +python3 -m doctest -v greedy_merge_sort.py + +Objective +Merge a set of sorted files of different length into a single sorted file. +We need to find an optimal solution, where the resultant file +will be generated in minimum time. + +Approach +If the number of sorted files are given, there are many ways +to merge them into a single sorted file. +This merge can be performed pair wise. +To merge a m-record file and a n-record file requires possibly m+n record moves +the optimal choice being, +merge the two smallest files together at each step (greedy approach). +""" + + +def optimal_merge_pattern(files: list) -> float: + """Function to merge all the files with optimum cost + + Args: + files [list]: A list of sizes of different files to be merged + + Returns: + optimal_merge_cost [int]: Optimal cost to merge all those files + + Examples: + >>> optimal_merge_pattern([2, 3, 4]) + 14 + >>> optimal_merge_pattern([5, 10, 20, 30, 30]) + 205 + >>> optimal_merge_pattern([8, 8, 8, 8, 8]) + 96 + """ + optimal_merge_cost = 0 + while len(files) > 1: + temp = 0 + # Consider two files with minimum cost to be merged + for i in range(2): + min_index = files.index(min(files)) + temp += files[min_index] + files.pop(min_index) + files.append(temp) + optimal_merge_cost += temp + return optimal_merge_cost + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 9b4cb05ee5a89609590785b683f81f42a77dadf1 Mon Sep 17 00:00:00 2001 From: Aman kanojiya <50018596+AMANKANOJIYA@users.noreply.github.com> Date: Thu, 14 Oct 2021 16:23:03 +0530 Subject: [PATCH 059/726] Modified Euler's Method (#5258) * Magnitude and Angle Core function to find Magnitude and Angle of two Given Vector * Magnitude and Angle with Doctest added Doctest to the functions * Update linear_algebra/src/lib.py Co-authored-by: Christian Clauss * Update linear_algebra/src/lib.py Co-authored-by: Christian Clauss * Changes done and Magnitude and Angle Issues * black * Modified Euler's Method Adding Modified Euler's method, which was the further change to a Euler method and known for better accuracy to the given value * Modified Euler's Method (changed the typing of function) Modified function is used for better accuracy * Link added Added link to an explanation as per Contributions Guidelines * Resolving Pre-Commit error * Pre-Commit Error Resolved * Pre-Commit Error import statement Change * Removed Import Math * import math built issue * adding space pre-commit error * statement sorter for doc Co-authored-by: Christian Clauss --- maths/euler_modified.py | 54 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 maths/euler_modified.py diff --git a/maths/euler_modified.py b/maths/euler_modified.py new file mode 100644 index 000000000..bf0c07c17 --- /dev/null +++ b/maths/euler_modified.py @@ -0,0 +1,54 @@ +from typing import Callable + +import numpy as np + + +def euler_modified( + ode_func: Callable, y0: float, x0: float, step_size: float, x_end: float +) -> np.array: + """ + Calculate solution at each step to an ODE using Euler's Modified Method + The Euler is straightforward to implement, but can't give accurate solutions. + So, they Proposed some changes to improve the accuracy + + https://en.wikipedia.org/wiki/Euler_method + + Arguments: + ode_func -- The ode as a function of x and y + y0 -- the initial value for y + x0 -- the initial value for x + stepsize -- the increment value for x + x_end -- the end value for x + + >>> # the exact solution is math.exp(x) + >>> def f1(x, y): + ... return -2*x*(y**2) + >>> y = euler_modified(f1, 1.0, 0.0, 0.2, 1.0) + >>> y[-1] + 0.503338255442106 + >>> import math + >>> def f2(x, y): + ... return -2*y + (x**3)*math.exp(-2*x) + >>> y = euler_modified(f2, 1.0, 0.0, 0.1, 0.3) + >>> y[-1] + 0.5525976431951775 + """ + N = int(np.ceil((x_end - x0) / step_size)) + y = np.zeros((N + 1,)) + y[0] = y0 + x = x0 + + for k in range(N): + y_get = y[k] + step_size * ode_func(x, y[k]) + y[k + 1] = y[k] + ( + (step_size / 2) * (ode_func(x, y[k]) + ode_func(x + step_size, y_get)) + ) + x += step_size + + return y + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From d561de0bd93a4aef31765ae84b97dafdb606a7e6 Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj <89947037+Rohanrbharadwaj@users.noreply.github.com> Date: Thu, 14 Oct 2021 16:53:18 +0530 Subject: [PATCH 060/726] Add surface area of cone and cylinder and hemisphere (#5220) * Update area.py * Update area.py * Update area.py * Update area.py * Update area.py * Update area.py * Update area.py * Update area.py --- maths/area.py | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/maths/area.py b/maths/area.py index 8689f323c..13c05af5f 100644 --- a/maths/area.py +++ b/maths/area.py @@ -42,6 +42,85 @@ def surface_area_sphere(radius: float) -> float: return 4 * pi * radius ** 2 +def surface_area_hemisphere(radius: float) -> float: + """ + Calculate the Surface Area of a Hemisphere. + Formula: 3 * pi * r^2 + + >>> surface_area_hemisphere(5) + 235.61944901923448 + >>> surface_area_hemisphere(1) + 9.42477796076938 + >>> surface_area_hemisphere(0) + 0.0 + >>> surface_area_hemisphere(1.1) + 11.40398133253095 + >>> surface_area_hemisphere(-1) + Traceback (most recent call last): + ... + ValueError: surface_area_hemisphere() only accepts non-negative values + """ + if radius < 0: + raise ValueError("surface_area_hemisphere() only accepts non-negative values") + return 3 * pi * radius ** 2 + + +def surface_area_cone(radius: float, height: float) -> float: + """ + Calculate the Surface Area of a Cone. + Wikipedia reference: https://en.wikipedia.org/wiki/Cone + Formula: pi * r * (r + (h ** 2 + r ** 2) ** 0.5) + + >>> surface_area_cone(10, 24) + 1130.9733552923256 + >>> surface_area_cone(6, 8) + 301.59289474462014 + >>> surface_area_cone(-1, -2) + Traceback (most recent call last): + ... + ValueError: surface_area_cone() only accepts non-negative values + >>> surface_area_cone(1, -2) + Traceback (most recent call last): + ... + ValueError: surface_area_cone() only accepts non-negative values + >>> surface_area_cone(-1, 2) + Traceback (most recent call last): + ... + ValueError: surface_area_cone() only accepts non-negative values + """ + if radius < 0 or height < 0: + raise ValueError("surface_area_cone() only accepts non-negative values") + return pi * radius * (radius + (height ** 2 + radius ** 2) ** 0.5) + + +def surface_area_cylinder(radius: float, height: float) -> float: + """ + Calculate the Surface Area of a Cylinder. + Wikipedia reference: https://en.wikipedia.org/wiki/Cylinder + Formula: 2 * pi * r * (h + r) + + >>> surface_area_cylinder(7, 10) + 747.6990515543707 + >>> surface_area_cylinder(6, 8) + 527.7875658030853 + >>> surface_area_cylinder(-1, -2) + Traceback (most recent call last): + ... + ValueError: surface_area_cylinder() only accepts non-negative values + >>> surface_area_cylinder(1, -2) + Traceback (most recent call last): + ... + ValueError: surface_area_cylinder() only accepts non-negative values + >>> surface_area_cylinder(-1, 2) + Traceback (most recent call last): + ... + ValueError: surface_area_cylinder() only accepts non-negative values + """ + if radius < 0 or height < 0: + raise ValueError("surface_area_cylinder() only accepts non-negative values") + return 2 * pi * radius * (height + radius) + + def area_rectangle(length: float, width: float) -> float: """ Calculate the area of a rectangle. @@ -280,9 +359,12 @@ if __name__ == "__main__": print(f"Triangle: {area_triangle(10, 10) = }") print(f"Triangle: {area_triangle_three_sides(5, 12, 13) = }") print(f"Parallelogram: {area_parallelogram(10, 20) = }") + print(f"Rhombus: {area_rhombus(10, 20) = }") print(f"Trapezium: {area_trapezium(10, 20, 30) = }") print(f"Circle: {area_circle(20) = }") print("\nSurface Areas of various geometric shapes: \n") print(f"Cube: {surface_area_cube(20) = }") print(f"Sphere: {surface_area_sphere(20) = }") - print(f"Rhombus: {area_rhombus(10, 20) = }") + print(f"Hemisphere: {surface_area_hemisphere(20) = }") + print(f"Cone: {surface_area_cone(10, 20) = }") + print(f"Cylinder: {surface_area_cylinder(10, 20) = }") From bb37ebbe50b7c7140b6efc52b95f3c32f230ea0a Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj <89947037+Rohanrbharadwaj@users.noreply.github.com> Date: Thu, 14 Oct 2021 19:31:38 +0530 Subject: [PATCH 061/726] Create baconian_cipher.py (#5251) * Create baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py * Update baconian_cipher.py --- ciphers/baconian_cipher.py | 89 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 ciphers/baconian_cipher.py diff --git a/ciphers/baconian_cipher.py b/ciphers/baconian_cipher.py new file mode 100644 index 000000000..027fbc50e --- /dev/null +++ b/ciphers/baconian_cipher.py @@ -0,0 +1,89 @@ +""" +Program to encode and decode Baconian or Bacon's Cipher +Wikipedia reference : https://en.wikipedia.org/wiki/Bacon%27s_cipher +""" + +encode_dict = { + "a": "AAAAA", + "b": "AAAAB", + "c": "AAABA", + "d": "AAABB", + "e": "AABAA", + "f": "AABAB", + "g": "AABBA", + "h": "AABBB", + "i": "ABAAA", + "j": "BBBAA", + "k": "ABAAB", + "l": "ABABA", + "m": "ABABB", + "n": "ABBAA", + "o": "ABBAB", + "p": "ABBBA", + "q": "ABBBB", + "r": "BAAAA", + "s": "BAAAB", + "t": "BAABA", + "u": "BAABB", + "v": "BBBAB", + "w": "BABAA", + "x": "BABAB", + "y": "BABBA", + "z": "BABBB", + " ": " ", +} + + +decode_dict = {value: key for key, value in encode_dict.items()} + + +def encode(word: str) -> str: + """ + Encodes to Baconian cipher + + >>> encode("hello") + 'AABBBAABAAABABAABABAABBAB' + >>> encode("hello world") + 'AABBBAABAAABABAABABAABBAB BABAAABBABBAAAAABABAAAABB' + >>> encode("hello world!") + Traceback (most recent call last): + ... + Exception: encode() accepts only letters of the alphabet and spaces + """ + encoded = "" + for letter in word.lower(): + if letter.isalpha() or letter == " ": + encoded += encode_dict[letter] + else: + raise Exception("encode() accepts only letters of the alphabet and spaces") + return encoded + + +def decode(coded: str) -> str: + """ + Decodes from Baconian cipher + + >>> decode("AABBBAABAAABABAABABAABBAB BABAAABBABBAAAAABABAAAABB") + 'hello world' + >>> decode("AABBBAABAAABABAABABAABBAB") + 'hello' + >>> decode("AABBBAABAAABABAABABAABBAB BABAAABBABBAAAAABABAAAABB!") + Traceback (most recent call last): + ... + Exception: decode() accepts only 'A', 'B' and spaces + """ + if set(coded) - {"A", "B", " "} != set(): + raise Exception("decode() accepts only 'A', 'B' and spaces") + decoded = "" + for word in coded.split(): + while len(word) != 0: + decoded += decode_dict[word[:5]] + word = word[5:] + decoded += " " + return decoded.strip() + + +if "__name__" == "__main__": + from doctest import testmod + + testmod() From 618f9ca885a6f4e0c2f7dfcf1768ef7b0f717ba6 Mon Sep 17 00:00:00 2001 From: Jordan Rinder Date: Thu, 14 Oct 2021 10:30:52 -0400 Subject: [PATCH 062/726] Add Proth number to maths (#5246) * Add Proth number to maths * Add test for 0 and more informative output * Fixing test failure issue - unused variable * Update proth_number.py Co-authored-by: Christian Clauss --- maths/proth_number.py | 77 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 maths/proth_number.py diff --git a/maths/proth_number.py b/maths/proth_number.py new file mode 100644 index 000000000..065244ed7 --- /dev/null +++ b/maths/proth_number.py @@ -0,0 +1,77 @@ +""" +Calculate the nth Proth number + +Source: + https://handwiki.org/wiki/Proth_number +""" + +import math + + +def proth(number: int) -> int: + """ + :param number: nth number to calculate in the sequence + :return: the nth number in Proth number + + Note: indexing starts at 1 i.e. proth(1) gives the first Proth number of 3 + + >>> proth(6) + 25 + + >>> proth(0) + Traceback (most recent call last): + ... + ValueError: Input value of [number=0] must be > 0 + + >>> proth(-1) + Traceback (most recent call last): + ... + ValueError: Input value of [number=-1] must be > 0 + + >>> proth(6.0) + Traceback (most recent call last): + ... + TypeError: Input value of [number=6.0] must be an integer + """ + + if not isinstance(number, int): + raise TypeError(f"Input value of [number={number}] must be an integer") + + if number < 1: + raise ValueError(f"Input value of [number={number}] must be > 0") + elif number == 1: + return 3 + elif number == 2: + return 5 + else: + block_index = number // 3 + """ + +1 for binary starting at 0 i.e. 2^0, 2^1, etc. + +1 to start the sequence at the 3rd Proth number + Hence, we have a +2 in the below statement + """ + block_index = math.log(block_index, 2) + 2 + block_index = int(block_index) + + proth_list = [3, 5] + proth_index = 2 + increment = 3 + for block in range(1, block_index): + for move in range(increment): + proth_list.append(2 ** (block + 1) + proth_list[proth_index - 1]) + proth_index += 1 + increment *= 2 + + return proth_list[number - 1] + + +if __name__ == "__main__": + for number in range(11): + value = 0 + try: + value = proth(number) + except ValueError: + print(f"ValueError: there is no {number}th Proth number") + continue + + print(f"The {number}th Proth number: {value}") From ca842b4add2a81c6d50e4fba2bf33ad07f54dbca Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 14 Oct 2021 18:19:47 +0200 Subject: [PATCH 063/726] It is OK to test ./scripts (#5290) * It is OK to test ./scripts * updating DIRECTORY.md * Update build.yml Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- DIRECTORY.md | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7c2255275..f710e1e0e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,6 +23,6 @@ jobs: python -m pip install mypy pytest-cov -r requirements.txt - run: mypy --install-types --non-interactive . - name: Run tests - run: pytest --doctest-modules --ignore=project_euler/ --ignore=scripts/ --cov-report=term-missing:skip-covered --cov=. . + run: pytest --doctest-modules --ignore=project_euler/ --ignore=scripts/validate_solutions.py --cov-report=term-missing:skip-covered --cov=. . - if: ${{ success() }} run: scripts/build_directory_md.py 2>&1 | tee DIRECTORY.md diff --git a/DIRECTORY.md b/DIRECTORY.md index 6c227fd2b..d92dccca5 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -264,6 +264,7 @@ * [Sum Of Subset](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/sum_of_subset.py) ## Electronics + * [Carrier Concentration](https://github.com/TheAlgorithms/Python/blob/master/electronics/carrier_concentration.py) * [Electric Power](https://github.com/TheAlgorithms/Python/blob/master/electronics/electric_power.py) * [Ohms Law](https://github.com/TheAlgorithms/Python/blob/master/electronics/ohms_law.py) @@ -346,6 +347,9 @@ * [Test Min Spanning Tree Kruskal](https://github.com/TheAlgorithms/Python/blob/master/graphs/tests/test_min_spanning_tree_kruskal.py) * [Test Min Spanning Tree Prim](https://github.com/TheAlgorithms/Python/blob/master/graphs/tests/test_min_spanning_tree_prim.py) +## Greedy Methods + * [Optimal Merge Pattern](https://github.com/TheAlgorithms/Python/blob/master/greedy_methods/optimal_merge_pattern.py) + ## Hashes * [Adler32](https://github.com/TheAlgorithms/Python/blob/master/hashes/adler32.py) * [Chaos Machine](https://github.com/TheAlgorithms/Python/blob/master/hashes/chaos_machine.py) @@ -436,6 +440,7 @@ * [Euclidean Distance](https://github.com/TheAlgorithms/Python/blob/master/maths/euclidean_distance.py) * [Euclidean Gcd](https://github.com/TheAlgorithms/Python/blob/master/maths/euclidean_gcd.py) * [Euler Method](https://github.com/TheAlgorithms/Python/blob/master/maths/euler_method.py) + * [Euler Modified](https://github.com/TheAlgorithms/Python/blob/master/maths/euler_modified.py) * [Eulers Totient](https://github.com/TheAlgorithms/Python/blob/master/maths/eulers_totient.py) * [Extended Euclidean Algorithm](https://github.com/TheAlgorithms/Python/blob/master/maths/extended_euclidean_algorithm.py) * [Factorial Iterative](https://github.com/TheAlgorithms/Python/blob/master/maths/factorial_iterative.py) From 545fec7a1446348d117f8c840cb4e334a67e25da Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj <89947037+Rohanrbharadwaj@users.noreply.github.com> Date: Fri, 15 Oct 2021 16:03:39 +0530 Subject: [PATCH 064/726] Fix documentation (#5311) --- maths/euler_modified.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maths/euler_modified.py b/maths/euler_modified.py index bf0c07c17..7c76a0ee0 100644 --- a/maths/euler_modified.py +++ b/maths/euler_modified.py @@ -8,8 +8,8 @@ def euler_modified( ) -> np.array: """ Calculate solution at each step to an ODE using Euler's Modified Method - The Euler is straightforward to implement, but can't give accurate solutions. - So, they Proposed some changes to improve the accuracy + The Euler Method is straightforward to implement, but can't give accurate solutions. + So, some changes were proposed to improve accuracy. https://en.wikipedia.org/wiki/Euler_method From 908cb4f1e72e16726ef5ca8365b36d473fcf2e00 Mon Sep 17 00:00:00 2001 From: Manuel Di Lullo <39048927+manueldilullo@users.noreply.github.com> Date: Fri, 15 Oct 2021 15:04:38 +0200 Subject: [PATCH 065/726] Greedy min vertex cover hacktoberfest (#5241) * added complete graph generator function * added doctest, type hints, wikipedia explanation * added return type hint for function complete_graph * added descriptive name for the parameter: n * random graph generator with doctest and type hints * added Greedy min vertex algorithm * pre-commit hook(s) made changes * Delete complete_graph_generator.py * Delete random_graph_generator.py * fixed doctest * updated commit following highligths * fixed following pre-commit highlights * modified variables names --- graphs/greedy_min_vertex_cover.py | 65 +++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 graphs/greedy_min_vertex_cover.py diff --git a/graphs/greedy_min_vertex_cover.py b/graphs/greedy_min_vertex_cover.py new file mode 100644 index 000000000..056c5b89b --- /dev/null +++ b/graphs/greedy_min_vertex_cover.py @@ -0,0 +1,65 @@ +""" +* Author: Manuel Di Lullo (https://github.com/manueldilullo) +* Description: Approximization algorithm for minimum vertex cover problem. + Greedy Approach. Uses graphs represented with an adjacency list + +URL: https://mathworld.wolfram.com/MinimumVertexCover.html +URL: https://cs.stackexchange.com/questions/129017/greedy-algorithm-for-vertex-cover +""" + +import heapq + + +def greedy_min_vertex_cover(graph: dict) -> set: + """ + Greedy APX Algorithm for min Vertex Cover + @input: graph (graph stored in an adjacency list where each vertex + is represented with an integer) + @example: + >>> graph = {0: [1, 3], 1: [0, 3], 2: [0, 3, 4], 3: [0, 1, 2], 4: [2, 3]} + >>> greedy_min_vertex_cover(graph) + {0, 1, 2, 4} + """ + # queue used to store nodes and their rank + queue = [] + + # for each node and his adjacency list add them and the rank of the node to queue + # using heapq module the queue will be filled like a Priority Queue + # heapq works with a min priority queue, so I used -1*len(v) to build it + for key, value in graph.items(): + # O(log(n)) + heapq.heappush(queue, [-1 * len(value), (key, value)]) + + # chosen_vertices = set of chosen vertices + chosen_vertices = set() + + # while queue isn't empty and there are still edges + # (queue[0][0] is the rank of the node with max rank) + while queue and queue[0][0] != 0: + # extract vertex with max rank from queue and add it to chosen_vertices + argmax = heapq.heappop(queue)[1][0] + chosen_vertices.add(argmax) + + # Remove all arcs adjacent to argmax + for elem in queue: + # if v haven't adjacent node, skip + if elem[0] == 0: + continue + # if argmax is reachable from elem + # remove argmax from elem's adjacent list and update his rank + if argmax in elem[1][1]: + index = elem[1][1].index(argmax) + del elem[1][1][index] + elem[0] += 1 + # re-order the queue + heapq.heapify(queue) + return chosen_vertices + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + + # graph = {0: [1, 3], 1: [0, 3], 2: [0, 3, 4], 3: [0, 1, 2], 4: [2, 3]} + # print(f"Minimum vertex cover:\n{greedy_min_vertex_cover(graph)}") From 1d457be29d0ac55ebafe049a9a13f9b9c09f1380 Mon Sep 17 00:00:00 2001 From: Manuel Di Lullo <39048927+manueldilullo@users.noreply.github.com> Date: Fri, 15 Oct 2021 17:03:57 +0200 Subject: [PATCH 066/726] Matching min vertex cover (#5326) * matching algorithm for min vertex cover problem * fixed hint on row 37 * changed variable names * provided doctest for get_edges function * Removed dict.keys() iteration * Update matching_min_vertex_cover.py Co-authored-by: Christian Clauss --- graphs/matching_min_vertex_cover.py | 62 +++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 graphs/matching_min_vertex_cover.py diff --git a/graphs/matching_min_vertex_cover.py b/graphs/matching_min_vertex_cover.py new file mode 100644 index 000000000..5ac944ec1 --- /dev/null +++ b/graphs/matching_min_vertex_cover.py @@ -0,0 +1,62 @@ +""" +* Author: Manuel Di Lullo (https://github.com/manueldilullo) +* Description: Approximization algorithm for minimum vertex cover problem. + Matching Approach. Uses graphs represented with an adjacency list + +URL: https://mathworld.wolfram.com/MinimumVertexCover.html +URL: https://www.princeton.edu/~aaa/Public/Teaching/ORF523/ORF523_Lec6.pdf +""" + + +def matching_min_vertex_cover(graph: dict) -> set: + """ + APX Algorithm for min Vertex Cover using Matching Approach + @input: graph (graph stored in an adjacency list where each vertex + is represented as an integer) + @example: + >>> graph = {0: [1, 3], 1: [0, 3], 2: [0, 3, 4], 3: [0, 1, 2], 4: [2, 3]} + >>> matching_min_vertex_cover(graph) + {0, 1, 2, 4} + """ + # chosen_vertices = set of chosen vertices + chosen_vertices = set() + # edges = list of graph's edges + edges = get_edges(graph) + + # While there are still elements in edges list, take an arbitrary edge + # (from_node, to_node) and add his extremity to chosen_vertices and then + # remove all arcs adjacent to the from_node and to_node + while edges: + from_node, to_node = edges.pop() + chosen_vertices.add(from_node) + chosen_vertices.add(to_node) + for edge in edges.copy(): + if from_node in edge or to_node in edge: + edges.discard(edge) + return chosen_vertices + + +def get_edges(graph: dict) -> set: + """ + Return a set of couples that represents all of the edges. + @input: graph (graph stored in an adjacency list where each vertex is + represented as an integer) + @example: + >>> graph = {0: [1, 3], 1: [0, 3], 2: [0, 3], 3: [0, 1, 2]} + >>> get_edges(graph) + {(0, 1), (3, 1), (0, 3), (2, 0), (3, 0), (2, 3), (1, 0), (3, 2), (1, 3)} + """ + edges = set() + for from_node, to_nodes in graph.items(): + for to_node in to_nodes: + edges.add((from_node, to_node)) + return edges + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + + # graph = {0: [1, 3], 1: [0, 3], 2: [0, 3, 4], 3: [0, 1, 2], 4: [2, 3]} + # print(f"Matching vertex cover:\n{matching_min_vertex_cover(graph)}") From 4cf1aaeb967790b88c85d5c773538754ffd89a44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Murilo=20Gon=C3=A7alves?= <38800183+murilo-goncalves@users.noreply.github.com> Date: Fri, 15 Oct 2021 18:57:41 -0300 Subject: [PATCH 067/726] Updated mypy.ini, removed ok folders that were excluded (#5331) --- mypy.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy.ini b/mypy.ini index 9eec22e22..ba552f878 100644 --- a/mypy.ini +++ b/mypy.ini @@ -2,4 +2,4 @@ ignore_missing_imports = True ; FIXME: #4052 fix mypy errors in the exclude directories and remove them below -exclude = (data_structures|dynamic_programming|graphs|maths|matrix|other|project_euler|searches|strings*)/$ +exclude = (data_structures|graphs|maths|matrix|other|searches)/$ From 152261765a93c2a12eb4af0abdd297652766d47d Mon Sep 17 00:00:00 2001 From: Appledora Date: Sat, 16 Oct 2021 06:02:44 +0600 Subject: [PATCH 068/726] Show images from google query (#4853) * Added new script to open the google image tab with a search query. * Added new script to open the google image tab with a search query. * Added new script to open the google image tab with a search query with doctests. * Fixed doctest error, removed print() from method, changed return type * Update web_programming/show_image_tab_from_google_query.py using iterators instead of lists Co-authored-by: Christian Clauss * Update web_programming/show_image_tab_from_google_query.py Improve readability by removing one-time used variable Co-authored-by: Christian Clauss * Update web_programming/show_image_tab_from_google_query.py Decreasing complication through standard practices. Co-authored-by: Christian Clauss * Update web_programming/show_image_tab_from_google_query.py Exception Handling Co-authored-by: Christian Clauss * changed complete method to download images from google search query * Update download_images_from_google_query.py * Delete show_image_tab_from_google_query.py Co-authored-by: Christian Clauss --- .../download_images_from_google_query.py | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 web_programming/download_images_from_google_query.py diff --git a/web_programming/download_images_from_google_query.py b/web_programming/download_images_from_google_query.py new file mode 100644 index 000000000..c26262788 --- /dev/null +++ b/web_programming/download_images_from_google_query.py @@ -0,0 +1,99 @@ +import json +import os +import re +import sys +import urllib.request + +import requests +from bs4 import BeautifulSoup + +headers = { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" + " (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582" +} + + +def download_images_from_google_query(query: str = "dhaka", max_images: int = 5) -> int: + """Searches google using the provided query term and downloads the images in a folder. + + Args: + query : The image search term to be provided by the user. Defaults to + "dhaka". + image_numbers : [description]. Defaults to 5. + + Returns: + The number of images successfully downloaded. + + >>> download_images_from_google_query() + 5 + >>> download_images_from_google_query("potato") + 5 + """ + max_images = min(max_images, 50) # Prevent abuse! + params = { + "q": query, + "tbm": "isch", + "hl": "en", + "ijn": "0", + } + + html = requests.get("https://www.google.com/search", params=params, headers=headers) + soup = BeautifulSoup(html.text, "html.parser") + matched_images_data = "".join( + re.findall(r"AF_initDataCallback\(([^<]+)\);", str(soup.select("script"))) + ) + + matched_images_data_fix = json.dumps(matched_images_data) + matched_images_data_json = json.loads(matched_images_data_fix) + + matched_google_image_data = re.findall( + r"\[\"GRID_STATE0\",null,\[\[1,\[0,\".*?\",(.*),\"All\",", + matched_images_data_json, + ) + if not matched_google_image_data: + return 0 + + removed_matched_google_images_thumbnails = re.sub( + r"\[\"(https\:\/\/encrypted-tbn0\.gstatic\.com\/images\?.*?)\",\d+,\d+\]", + "", + str(matched_google_image_data), + ) + + matched_google_full_resolution_images = re.findall( + r"(?:'|,),\[\"(https:|http.*?)\",\d+,\d+\]", + removed_matched_google_images_thumbnails, + ) + for index, fixed_full_res_image in enumerate(matched_google_full_resolution_images): + if index >= max_images: + return index + original_size_img_not_fixed = bytes(fixed_full_res_image, "ascii").decode( + "unicode-escape" + ) + original_size_img = bytes(original_size_img_not_fixed, "ascii").decode( + "unicode-escape" + ) + opener = urllib.request.build_opener() + opener.addheaders = [ + ( + "User-Agent", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" + " (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582", + ) + ] + urllib.request.install_opener(opener) + path_name = f"query_{query.replace(' ', '_')}" + if not os.path.exists(path_name): + os.makedirs(path_name) + urllib.request.urlretrieve( + original_size_img, f"{path_name}/original_size_img_{index}.jpg" + ) + return index + + +if __name__ == "__main__": + try: + image_count = download_images_from_google_query(sys.argv[1]) + print(f"{image_count} images were downloaded to disk.") + except IndexError: + print("Please provide a search term.") + raise From 37385883aaa140a505488d23fa37be4049768f2b Mon Sep 17 00:00:00 2001 From: Appledora Date: Sat, 16 Oct 2021 07:32:33 +0600 Subject: [PATCH 069/726] Improved readability of web_programming/get_imdbtop.py and added documentations with doctests (#4855) * improved readability of the existing method by reformatting, adding documentations with doctests. * improved readability of the existing method by reformatting, adding documentations with doctests. * fixed typo in test * added doctest to parse dictionary method * added doctest to parse dictionary method * Changed return type, removed print() from method and implemented doctests as suggested * Fixed doctest error, removed print() from method, created new script as suggested * Update get_imdbtop.py * Fix typo discovered by codespell * return () Co-authored-by: Christian Clauss --- web_programming/get_imdbtop.py | 57 +++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/web_programming/get_imdbtop.py b/web_programming/get_imdbtop.py index 669e7f898..5f7105f83 100644 --- a/web_programming/get_imdbtop.py +++ b/web_programming/get_imdbtop.py @@ -1,20 +1,53 @@ +import bs4 import requests -from bs4 import BeautifulSoup -def imdb_top(imdb_top_n): +def get_movie_data_from_soup(soup: bs4.element.ResultSet) -> dict[str, str]: + return { + "name": soup.h3.a.text, + "genre": soup.find("span", class_="genre").text.strip(), + "rating": soup.strong.text, + "page_link": f"https://www.imdb.com{soup.a.get('href')}", + } + + +def get_imdb_top_movies(num_movies: int = 5) -> tuple: + """Get the top num_movies most highly rated movies from IMDB and + return a tuple of dicts describing each movie's name, genre, rating, and URL. + + Args: + num_movies: The number of movies to get. Defaults to 5. + + Returns: + A list of tuples containing information about the top n movies. + + >>> len(get_imdb_top_movies(5)) + 5 + >>> len(get_imdb_top_movies(-3)) + 0 + >>> len(get_imdb_top_movies(4.99999)) + 4 + """ + num_movies = int(float(num_movies)) + if num_movies < 1: + return () base_url = ( - f"https://www.imdb.com/search/title?title_type=" - f"feature&sort=num_votes,desc&count={imdb_top_n}" + "https://www.imdb.com/search/title?title_type=" + f"feature&sort=num_votes,desc&count={num_movies}" + ) + source = bs4.BeautifulSoup(requests.get(base_url).content, "html.parser") + return tuple( + get_movie_data_from_soup(movie) + for movie in source.find_all("div", class_="lister-item mode-advanced") ) - source = BeautifulSoup(requests.get(base_url).content, "html.parser") - for m in source.findAll("div", class_="lister-item mode-advanced"): - print("\n" + m.h3.a.text) # movie's name - print(m.find("span", attrs={"class": "genre"}).text) # genre - print(m.strong.text) # movie's rating - print(f"https://www.imdb.com{m.a.get('href')}") # movie's page link - print("*" * 40) if __name__ == "__main__": - imdb_top(input("How many movies would you like to see? ")) + import json + + num_movies = int(input("How many movies would you like to see? ")) + print( + ", ".join( + json.dumps(movie, indent=4) for movie in get_imdb_top_movies(num_movies) + ) + ) From 433b804f7d1a19403cb0856232f0d23f09d4b4a0 Mon Sep 17 00:00:00 2001 From: Saurabh Suresh Powar <66636289+Spnetic-5@users.noreply.github.com> Date: Sat, 16 Oct 2021 20:02:40 +0530 Subject: [PATCH 070/726] Added morphological operations, fixes: #5197 (#5199) * Added morphological operations, fixes: #5197 * Added dilation tests and type hints * Added erosion tests and type hints * fixes: TheAlgorithms#5197 * fixes: TheAlgorithms#5197 * Update erosion_operation.py * made suggested changes in dilation * made suggested changes in erosion * made suggested changes in dilation * removed extra spaces in the tests * removed extra spaces in the tests --- .../dilation_operation.py | 74 +++++++++++++++++++ .../erosion_operation.py | 74 +++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 digital_image_processing/morphological_operations/dilation_operation.py create mode 100644 digital_image_processing/morphological_operations/erosion_operation.py diff --git a/digital_image_processing/morphological_operations/dilation_operation.py b/digital_image_processing/morphological_operations/dilation_operation.py new file mode 100644 index 000000000..274880b0a --- /dev/null +++ b/digital_image_processing/morphological_operations/dilation_operation.py @@ -0,0 +1,74 @@ +import numpy as np +from PIL import Image + + +def rgb2gray(rgb: np.array) -> np.array: + """ + Return gray image from rgb image + >>> rgb2gray(np.array([[[127, 255, 0]]])) + array([[187.6453]]) + >>> rgb2gray(np.array([[[0, 0, 0]]])) + array([[0.]]) + >>> rgb2gray(np.array([[[2, 4, 1]]])) + array([[3.0598]]) + >>> rgb2gray(np.array([[[26, 255, 14], [5, 147, 20], [1, 200, 0]]])) + array([[159.0524, 90.0635, 117.6989]]) + """ + r, g, b = rgb[:, :, 0], rgb[:, :, 1], rgb[:, :, 2] + return 0.2989 * r + 0.5870 * g + 0.1140 * b + + +def gray2binary(gray: np.array) -> np.array: + """ + Return binary image from gray image + >>> gray2binary(np.array([[127, 255, 0]])) + array([[False, True, False]]) + >>> gray2binary(np.array([[0]])) + array([[False]]) + >>> gray2binary(np.array([[26.2409, 4.9315, 1.4729]])) + array([[False, False, False]]) + >>> gray2binary(np.array([[26, 255, 14], [5, 147, 20], [1, 200, 0]])) + array([[False, True, False], + [False, True, False], + [False, True, False]]) + """ + return (127 < gray) & (gray <= 255) + + +def dilation(image: np.array, kernel: np.array) -> np.array: + """ + Return dilated image + >>> dilation(np.array([[True, False, True]]), np.array([[0, 1, 0]])) + array([[False, False, False]]) + >>> dilation(np.array([[False, False, True]]), np.array([[1, 0, 1]])) + array([[False, False, False]]) + """ + output = np.zeros_like(image) + image_padded = np.zeros( + (image.shape[0] + kernel.shape[0] - 1, image.shape[1] + kernel.shape[1] - 1) + ) + + # Copy image to padded image + image_padded[kernel.shape[0] - 2 : -1 :, kernel.shape[1] - 2 : -1 :] = image + + # Iterate over image & apply kernel + for x in range(image.shape[1]): + for y in range(image.shape[0]): + summation = ( + kernel * image_padded[y : y + kernel.shape[0], x : x + kernel.shape[1]] + ).sum() + output[y, x] = int(summation > 0) + return output + + +# kernel to be applied +structuring_element = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]]) + + +if __name__ == "__main__": + # read original image + image = np.array(Image.open(r"..\image_data\lena.jpg")) + output = dilation(gray2binary(rgb2gray(image)), structuring_element) + # Save the output image + pil_img = Image.fromarray(output).convert("RGB") + pil_img.save("result_dilation.png") diff --git a/digital_image_processing/morphological_operations/erosion_operation.py b/digital_image_processing/morphological_operations/erosion_operation.py new file mode 100644 index 000000000..4b0a5eee8 --- /dev/null +++ b/digital_image_processing/morphological_operations/erosion_operation.py @@ -0,0 +1,74 @@ +import numpy as np +from PIL import Image + + +def rgb2gray(rgb: np.array) -> np.array: + """ + Return gray image from rgb image + >>> rgb2gray(np.array([[[127, 255, 0]]])) + array([[187.6453]]) + >>> rgb2gray(np.array([[[0, 0, 0]]])) + array([[0.]]) + >>> rgb2gray(np.array([[[2, 4, 1]]])) + array([[3.0598]]) + >>> rgb2gray(np.array([[[26, 255, 14], [5, 147, 20], [1, 200, 0]]])) + array([[159.0524, 90.0635, 117.6989]]) + """ + r, g, b = rgb[:, :, 0], rgb[:, :, 1], rgb[:, :, 2] + return 0.2989 * r + 0.5870 * g + 0.1140 * b + + +def gray2binary(gray: np.array) -> np.array: + """ + Return binary image from gray image + >>> gray2binary(np.array([[127, 255, 0]])) + array([[False, True, False]]) + >>> gray2binary(np.array([[0]])) + array([[False]]) + >>> gray2binary(np.array([[26.2409, 4.9315, 1.4729]])) + array([[False, False, False]]) + >>> gray2binary(np.array([[26, 255, 14], [5, 147, 20], [1, 200, 0]])) + array([[False, True, False], + [False, True, False], + [False, True, False]]) + """ + return (127 < gray) & (gray <= 255) + + +def erosion(image: np.array, kernel: np.array) -> np.array: + """ + Return eroded image + >>> erosion(np.array([[True, True, False]]), np.array([[0, 1, 0]])) + array([[False, False, False]]) + >>> erosion(np.array([[True, False, False]]), np.array([[1, 1, 0]])) + array([[False, False, False]]) + """ + output = np.zeros_like(image) + image_padded = np.zeros( + (image.shape[0] + kernel.shape[0] - 1, image.shape[1] + kernel.shape[1] - 1) + ) + + # Copy image to padded image + image_padded[kernel.shape[0] - 2 : -1 :, kernel.shape[1] - 2 : -1 :] = image + + # Iterate over image & apply kernel + for x in range(image.shape[1]): + for y in range(image.shape[0]): + summation = ( + kernel * image_padded[y : y + kernel.shape[0], x : x + kernel.shape[1]] + ).sum() + output[y, x] = int(summation == 5) + return output + + +# kernel to be applied +structuring_element = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]]) + +if __name__ == "__main__": + # read original image + image = np.array(Image.open(r"..\image_data\lena.jpg")) + # Apply erosion operation to a binary image + output = erosion(gray2binary(rgb2gray(image)), structuring_element) + # Save the output image + pil_img = Image.fromarray(output).convert("RGB") + pil_img.save("result_erosion.png") From 8dc7cdbc57e0a51c7ef0d6a5974d990c5f27cf4a Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 16 Oct 2021 18:57:38 +0200 Subject: [PATCH 071/726] Add tests to morse_code.py (#5337) * Add tests to morse_code.py @dhruvmanila @poyea Your reviews, please. * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 7 +- ciphers/morse_code.py | 58 +++++++++++++++++ ciphers/morse_code_implementation.py | 97 ---------------------------- 3 files changed, 64 insertions(+), 98 deletions(-) create mode 100644 ciphers/morse_code.py delete mode 100644 ciphers/morse_code_implementation.py diff --git a/DIRECTORY.md b/DIRECTORY.md index d92dccca5..219877a3a 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -53,6 +53,7 @@ * [A1Z26](https://github.com/TheAlgorithms/Python/blob/master/ciphers/a1z26.py) * [Affine Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/affine_cipher.py) * [Atbash](https://github.com/TheAlgorithms/Python/blob/master/ciphers/atbash.py) + * [Baconian Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/baconian_cipher.py) * [Base16](https://github.com/TheAlgorithms/Python/blob/master/ciphers/base16.py) * [Base32](https://github.com/TheAlgorithms/Python/blob/master/ciphers/base32.py) * [Base64 Encoding](https://github.com/TheAlgorithms/Python/blob/master/ciphers/base64_encoding.py) @@ -70,7 +71,7 @@ * [Hill Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/hill_cipher.py) * [Mixed Keyword Cypher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/mixed_keyword_cypher.py) * [Mono Alphabetic Ciphers](https://github.com/TheAlgorithms/Python/blob/master/ciphers/mono_alphabetic_ciphers.py) - * [Morse Code Implementation](https://github.com/TheAlgorithms/Python/blob/master/ciphers/morse_code_implementation.py) + * [Morse Code](https://github.com/TheAlgorithms/Python/blob/master/ciphers/morse_code.py) * [Onepad Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/onepad_cipher.py) * [Playfair Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/playfair_cipher.py) * [Porta Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/porta_cipher.py) @@ -328,10 +329,12 @@ * [Graph Matrix](https://github.com/TheAlgorithms/Python/blob/master/graphs/graph_matrix.py) * [Graphs Floyd Warshall](https://github.com/TheAlgorithms/Python/blob/master/graphs/graphs_floyd_warshall.py) * [Greedy Best First](https://github.com/TheAlgorithms/Python/blob/master/graphs/greedy_best_first.py) + * [Greedy Min Vertex Cover](https://github.com/TheAlgorithms/Python/blob/master/graphs/greedy_min_vertex_cover.py) * [Kahns Algorithm Long](https://github.com/TheAlgorithms/Python/blob/master/graphs/kahns_algorithm_long.py) * [Kahns Algorithm Topo](https://github.com/TheAlgorithms/Python/blob/master/graphs/kahns_algorithm_topo.py) * [Karger](https://github.com/TheAlgorithms/Python/blob/master/graphs/karger.py) * [Markov Chain](https://github.com/TheAlgorithms/Python/blob/master/graphs/markov_chain.py) + * [Matching Min Vertex Cover](https://github.com/TheAlgorithms/Python/blob/master/graphs/matching_min_vertex_cover.py) * [Minimum Spanning Tree Boruvka](https://github.com/TheAlgorithms/Python/blob/master/graphs/minimum_spanning_tree_boruvka.py) * [Minimum Spanning Tree Kruskal](https://github.com/TheAlgorithms/Python/blob/master/graphs/minimum_spanning_tree_kruskal.py) * [Minimum Spanning Tree Kruskal2](https://github.com/TheAlgorithms/Python/blob/master/graphs/minimum_spanning_tree_kruskal2.py) @@ -497,6 +500,7 @@ * [Prime Numbers](https://github.com/TheAlgorithms/Python/blob/master/maths/prime_numbers.py) * [Prime Sieve Eratosthenes](https://github.com/TheAlgorithms/Python/blob/master/maths/prime_sieve_eratosthenes.py) * [Primelib](https://github.com/TheAlgorithms/Python/blob/master/maths/primelib.py) + * [Proth Number](https://github.com/TheAlgorithms/Python/blob/master/maths/proth_number.py) * [Pythagoras](https://github.com/TheAlgorithms/Python/blob/master/maths/pythagoras.py) * [Qr Decomposition](https://github.com/TheAlgorithms/Python/blob/master/maths/qr_decomposition.py) * [Quadratic Equations Complex Numbers](https://github.com/TheAlgorithms/Python/blob/master/maths/quadratic_equations_complex_numbers.py) @@ -951,6 +955,7 @@ * [Current Stock Price](https://github.com/TheAlgorithms/Python/blob/master/web_programming/current_stock_price.py) * [Current Weather](https://github.com/TheAlgorithms/Python/blob/master/web_programming/current_weather.py) * [Daily Horoscope](https://github.com/TheAlgorithms/Python/blob/master/web_programming/daily_horoscope.py) + * [Download Images From Google Query](https://github.com/TheAlgorithms/Python/blob/master/web_programming/download_images_from_google_query.py) * [Emails From Url](https://github.com/TheAlgorithms/Python/blob/master/web_programming/emails_from_url.py) * [Fetch Bbc News](https://github.com/TheAlgorithms/Python/blob/master/web_programming/fetch_bbc_news.py) * [Fetch Github Info](https://github.com/TheAlgorithms/Python/blob/master/web_programming/fetch_github_info.py) diff --git a/ciphers/morse_code.py b/ciphers/morse_code.py new file mode 100644 index 000000000..0370c26fe --- /dev/null +++ b/ciphers/morse_code.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 + +""" +Python program to translate to and from Morse code. + +https://en.wikipedia.org/wiki/Morse_code +""" + +# fmt: off +MORSE_CODE_DICT = { + "A": ".-", "B": "-...", "C": "-.-.", "D": "-..", "E": ".", "F": "..-.", "G": "--.", + "H": "....", "I": "..", "J": ".---", "K": "-.-", "L": ".-..", "M": "--", "N": "-.", + "O": "---", "P": ".--.", "Q": "--.-", "R": ".-.", "S": "...", "T": "-", "U": "..-", + "V": "...-", "W": ".--", "X": "-..-", "Y": "-.--", "Z": "--..", "1": ".----", + "2": "..---", "3": "...--", "4": "....-", "5": ".....", "6": "-....", "7": "--...", + "8": "---..", "9": "----.", "0": "-----", "&": ".-...", "@": ".--.-.", + ":": "---...", ",": "--..--", ".": ".-.-.-", "'": ".----.", '"': ".-..-.", + "?": "..--..", "/": "-..-.", "=": "-...-", "+": ".-.-.", "-": "-....-", + "(": "-.--.", ")": "-.--.-", "!": "-.-.--", " ": "/" +} # Exclamation mark is not in ITU-R recommendation +# fmt: on +REVERSE_DICT = {value: key for key, value in MORSE_CODE_DICT.items()} + + +def encrypt(message: str) -> str: + """ + >>> encrypt("Sos!") + '... --- ... -.-.--' + >>> encrypt("SOS!") == encrypt("sos!") + True + """ + return " ".join(MORSE_CODE_DICT[char] for char in message.upper()) + + +def decrypt(message: str) -> str: + """ + >>> decrypt('... --- ... -.-.--') + 'SOS!' + """ + return "".join(REVERSE_DICT[char] for char in message.split()) + + +def main() -> None: + """ + >>> s = "".join(MORSE_CODE_DICT) + >>> decrypt(encrypt(s)) == s + True + """ + message = "Morse code here!" + print(message) + message = encrypt(message) + print(message) + message = decrypt(message) + print(message) + + +if __name__ == "__main__": + main() diff --git a/ciphers/morse_code_implementation.py b/ciphers/morse_code_implementation.py deleted file mode 100644 index eec4183fa..000000000 --- a/ciphers/morse_code_implementation.py +++ /dev/null @@ -1,97 +0,0 @@ -# Python program to implement Morse Code Translator - -# Dictionary representing the morse code chart -MORSE_CODE_DICT = { - "A": ".-", - "B": "-...", - "C": "-.-.", - "D": "-..", - "E": ".", - "F": "..-.", - "G": "--.", - "H": "....", - "I": "..", - "J": ".---", - "K": "-.-", - "L": ".-..", - "M": "--", - "N": "-.", - "O": "---", - "P": ".--.", - "Q": "--.-", - "R": ".-.", - "S": "...", - "T": "-", - "U": "..-", - "V": "...-", - "W": ".--", - "X": "-..-", - "Y": "-.--", - "Z": "--..", - "1": ".----", - "2": "..---", - "3": "...--", - "4": "....-", - "5": ".....", - "6": "-....", - "7": "--...", - "8": "---..", - "9": "----.", - "0": "-----", - "&": ".-...", - "@": ".--.-.", - ":": "---...", - ",": "--..--", - ".": ".-.-.-", - "'": ".----.", - '"': ".-..-.", - "?": "..--..", - "/": "-..-.", - "=": "-...-", - "+": ".-.-.", - "-": "-....-", - "(": "-.--.", - ")": "-.--.-", - # Exclamation mark is not in ITU-R recommendation - "!": "-.-.--", -} - - -def encrypt(message: str) -> str: - cipher = "" - for letter in message: - if letter != " ": - cipher += MORSE_CODE_DICT[letter] + " " - else: - cipher += "/ " - - # Remove trailing space added on line 64 - return cipher[:-1] - - -def decrypt(message: str) -> str: - decipher = "" - letters = message.split(" ") - for letter in letters: - if letter != "/": - decipher += list(MORSE_CODE_DICT.keys())[ - list(MORSE_CODE_DICT.values()).index(letter) - ] - else: - decipher += " " - - return decipher - - -def main() -> None: - message = "Morse code here" - result = encrypt(message.upper()) - print(result) - - message = result - result = decrypt(message) - print(result) - - -if __name__ == "__main__": - main() From 7ef2e4d1d06a0d7497bb7cbca0cad32fc1d9c6cd Mon Sep 17 00:00:00 2001 From: Srishtik Bhandarkar <53395406+srishtik2310@users.noreply.github.com> Date: Sat, 16 Oct 2021 22:38:41 +0530 Subject: [PATCH 072/726] Add Project Euler Problem 092 (#5091) * adde solution to problem 092 * added solution to problem 092 * fixed the pre-comit shebang issue --- project_euler/problem_092/__init__.py | 0 project_euler/problem_092/sol1.py | 93 +++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 project_euler/problem_092/__init__.py create mode 100644 project_euler/problem_092/sol1.py diff --git a/project_euler/problem_092/__init__.py b/project_euler/problem_092/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_092/sol1.py b/project_euler/problem_092/sol1.py new file mode 100644 index 000000000..a02629a7b --- /dev/null +++ b/project_euler/problem_092/sol1.py @@ -0,0 +1,93 @@ +""" +Project Euler Problem 092: https://projecteuler.net/problem=92 +Square digit chains +A number chain is created by continuously adding the square of the digits in +a number to form a new number until it has been seen before. +For example, +44 → 32 → 13 → 10 → 1 → 1 +85 → 89 → 145 → 42 → 20 → 4 → 16 → 37 → 58 → 89 +Therefore any chain that arrives at 1 or 89 will become stuck in an endless loop. +What is most amazing is that EVERY starting number will eventually arrive at 1 or 89. +How many starting numbers below ten million will arrive at 89? +""" + + +def next_number(number: int) -> int: + """ + Returns the next number of the chain by adding the square of each digit + to form a neww number. + For example if number = 12, next_number() will return 1^2 + 2^2 = 5. + Therefore 5 is the next number of the chain. + >>> next_number(44) + 32 + >>> next_number(10) + 1 + >>> next_number(32) + 13 + """ + num = 0 + for i in range(len(str(number))): + num += int(str(number)[i]) ** 2 + + return num + + +def chain(number: int) -> bool: + """ + Generates the chain of numbers until the nest number generated is 1 0r 89. + for example, if starting number is 44, then the function generates the + following chain of numbers. + chain: 44 → 32 → 13 → 10 → 1 → 1 + once the next number generated is 1 or 89, the function + Returns True if the next number generated by next_number() if 1. + Returns False if the next number generated by next_number() is 89. + >>> chain(10) + True + >>> chain(58) + False + >>> chain(1) + True + """ + while number != 1 and number != 89: + number = next_number(number) + + if number == 1: + return True + + elif number == 89: + return False + + +def solution(number: int = 10000000) -> int: + """ + The function returns the total numbers that end up in 89 after the chain generation. + The function accepts a range number and the function checks all the values + under value number. + if the chain generation leads to the end number as 1 or 89. If the chain() + returns True, then total is incremented, implying that the number we + started with ended up with 1 else total2 is incremented, implying that + the number we started with ended up in 89 after chain generation. + But the function returns total2 as the requirement of question is + to find out how many ended up in 89. + + >>> solution(100) + 80 + >>> solution(10000000) + 8581146 + """ + total = 0 + total2 = 0 + for i in range(1, number): + val = chain(i) + + if val is True: + total += 1 + + elif val is False: + total2 += 1 + + return total2 + + +if __name__ == "__main__": + print(f"{solution() = }") From 4bf2eedd3c234eddd04fbea314005ca06d32e923 Mon Sep 17 00:00:00 2001 From: John Law Date: Sun, 17 Oct 2021 14:07:45 +0800 Subject: [PATCH 073/726] [mypy] fix mypy error in Project Euler Problem 092 solution 1 (#5357) * fix mypy error * updating DIRECTORY.md * simplify code * run black * fix doc consistency * Fix doc * fix doc Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 5 +++ project_euler/problem_092/sol1.py | 55 +++++++++++-------------------- 2 files changed, 24 insertions(+), 36 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 219877a3a..c197dd880 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -211,6 +211,9 @@ * Histogram Equalization * [Histogram Stretch](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/histogram_equalization/histogram_stretch.py) * [Index Calculation](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/index_calculation.py) + * Morphological Operations + * [Dilation Operation](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/morphological_operations/dilation_operation.py) + * [Erosion Operation](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/morphological_operations/erosion_operation.py) * Resize * [Resize](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/resize/resize.py) * Rotation @@ -778,6 +781,8 @@ * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_089/sol1.py) * Problem 091 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_091/sol1.py) + * Problem 092 + * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_092/sol1.py) * Problem 097 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_097/sol1.py) * Problem 099 diff --git a/project_euler/problem_092/sol1.py b/project_euler/problem_092/sol1.py index a02629a7b..dcda3a486 100644 --- a/project_euler/problem_092/sol1.py +++ b/project_euler/problem_092/sol1.py @@ -17,7 +17,7 @@ def next_number(number: int) -> int: Returns the next number of the chain by adding the square of each digit to form a neww number. For example if number = 12, next_number() will return 1^2 + 2^2 = 5. - Therefore 5 is the next number of the chain. + Therefore, 5 is the next number of the chain. >>> next_number(44) 32 >>> next_number(10) @@ -25,22 +25,22 @@ def next_number(number: int) -> int: >>> next_number(32) 13 """ - num = 0 - for i in range(len(str(number))): - num += int(str(number)[i]) ** 2 + sum_of_digits_squared = 0 + while number: + sum_of_digits_squared += (number % 10) ** 2 + number //= 10 - return num + return sum_of_digits_squared def chain(number: int) -> bool: """ - Generates the chain of numbers until the nest number generated is 1 0r 89. - for example, if starting number is 44, then the function generates the - following chain of numbers. - chain: 44 → 32 → 13 → 10 → 1 → 1 - once the next number generated is 1 or 89, the function - Returns True if the next number generated by next_number() if 1. - Returns False if the next number generated by next_number() is 89. + The function generates the chain of numbers until the next number is 1 or 89. + For example, if starting number is 44, then the function generates the + following chain of numbers: + 44 → 32 → 13 → 10 → 1 → 1. + Once the next number generated is 1 or 89, the function returns whether + or not the the next number generated by next_number() is 1. >>> chain(10) True >>> chain(58) @@ -51,43 +51,26 @@ def chain(number: int) -> bool: while number != 1 and number != 89: number = next_number(number) - if number == 1: - return True - - elif number == 89: - return False + return number == 1 def solution(number: int = 10000000) -> int: """ - The function returns the total numbers that end up in 89 after the chain generation. + The function returns the number of integers that end up being 89 in each chain. The function accepts a range number and the function checks all the values under value number. - if the chain generation leads to the end number as 1 or 89. If the chain() - returns True, then total is incremented, implying that the number we - started with ended up with 1 else total2 is incremented, implying that - the number we started with ended up in 89 after chain generation. - But the function returns total2 as the requirement of question is - to find out how many ended up in 89. >>> solution(100) 80 >>> solution(10000000) 8581146 """ - total = 0 - total2 = 0 - for i in range(1, number): - val = chain(i) - - if val is True: - total += 1 - - elif val is False: - total2 += 1 - - return total2 + return sum(1 for i in range(1, number) if not chain(i)) if __name__ == "__main__": + import doctest + + doctest.testmod() + print(f"{solution() = }") From 08d4d226d797c94254f53be0c71d3304ea093bd4 Mon Sep 17 00:00:00 2001 From: Meysam Date: Sun, 17 Oct 2021 19:26:12 +0300 Subject: [PATCH 074/726] [mypy] Fix type annotations for graphs/boruvka (#4867) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: type annotations for pypi 🏷️ Fixes #4052 * updating DIRECTORY.md * apply suggestions from code review Co-authored-by: Christian Clauss Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss --- graphs/boruvka.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/graphs/boruvka.py b/graphs/boruvka.py index 3fa5c6fd2..eea0b0009 100644 --- a/graphs/boruvka.py +++ b/graphs/boruvka.py @@ -24,6 +24,7 @@ Details: https://en.wikipedia.org/wiki/Bor%C5%AFvka%27s_algorithm """ +from __future__ import annotations class Graph: @@ -39,8 +40,8 @@ class Graph: """ self.m_num_of_nodes = num_of_nodes - self.m_edges = [] - self.m_component = {} + self.m_edges: list[list[int]] = [] + self.m_component: dict[int, int] = {} def add_edge(self, u_node: int, v_node: int, weight: int) -> None: """Adds an edge in the format [first, second, edge weight] to graph.""" @@ -83,7 +84,7 @@ class Graph: component_size = [] mst_weight = 0 - minimum_weight_edge = [-1] * self.m_num_of_nodes + minimum_weight_edge: list[int] = [-1] * self.m_num_of_nodes # A list of components (initialized to all of the nodes) for node in range(self.m_num_of_nodes): From 1e64bf4600e933e820701a769a453ee379c8ea2c Mon Sep 17 00:00:00 2001 From: Atharva Deshpande Date: Mon, 18 Oct 2021 10:16:23 +0530 Subject: [PATCH 075/726] Re-organize math/series (#5044) * added harmonic mean * Update maths/series/harmonic_mean.py Updated the write-up of reference given in the code. Co-authored-by: John Law * changes in arithmetic and geometric mean code * mean and series added in a single file Co-authored-by: John Law --- .../{arithmetic_mean.py => arithmetic.py} | 25 +++-- .../{geometric_mean.py => geometric.py} | 30 +++--- maths/series/harmonic.py | 92 +++++++++++++++++++ 3 files changed, 129 insertions(+), 18 deletions(-) rename maths/series/{arithmetic_mean.py => arithmetic.py} (68%) rename maths/series/{geometric_mean.py => geometric.py} (75%) create mode 100644 maths/series/harmonic.py diff --git a/maths/series/arithmetic_mean.py b/maths/series/arithmetic.py similarity index 68% rename from maths/series/arithmetic_mean.py rename to maths/series/arithmetic.py index b5d64b63a..dc28c5c7b 100644 --- a/maths/series/arithmetic_mean.py +++ b/maths/series/arithmetic.py @@ -1,20 +1,35 @@ """ -ARITHMETIC MEAN : https://en.wikipedia.org/wiki/Arithmetic_mean +Arithmetic mean +Reference: https://en.wikipedia.org/wiki/Arithmetic_mean +Arithmetic series +Reference: https://en.wikipedia.org/wiki/Arithmetic_series +(The URL above will redirect you to arithmetic progression) """ def is_arithmetic_series(series: list) -> bool: """ checking whether the input series is arithmetic series or not - >>> is_arithmetic_series([2, 4, 6]) True >>> is_arithmetic_series([3, 6, 12, 24]) False >>> is_arithmetic_series([1, 2, 3]) True + >>> is_arithmetic_series(4) + Traceback (most recent call last): + ... + ValueError: Input series is not valid, valid series - [2, 4, 6] + >>> is_arithmetic_series([]) + Traceback (most recent call last): + ... + ValueError: Input list must be a non empty list """ + if not isinstance(series, list): + raise ValueError("Input series is not valid, valid series - [2, 4, 6]") + if len(series) == 0: + raise ValueError("Input list must be a non empty list") if len(series) == 1: return True common_diff = series[1] - series[0] @@ -37,9 +52,7 @@ def arithmetic_mean(series: list) -> float: ... ValueError: Input series is not valid, valid series - [2, 4, 6] >>> arithmetic_mean([4, 8, 1]) - Traceback (most recent call last): - ... - ValueError: Input list is not an arithmetic series + 4.333333333333333 >>> arithmetic_mean([1, 2, 3]) 2.0 >>> arithmetic_mean([]) @@ -52,8 +65,6 @@ def arithmetic_mean(series: list) -> float: raise ValueError("Input series is not valid, valid series - [2, 4, 6]") if len(series) == 0: raise ValueError("Input list must be a non empty list") - if not is_arithmetic_series(series): - raise ValueError("Input list is not an arithmetic series") answer = 0 for val in series: answer += val diff --git a/maths/series/geometric_mean.py b/maths/series/geometric.py similarity index 75% rename from maths/series/geometric_mean.py rename to maths/series/geometric.py index 50ae54ad6..7b6239b15 100644 --- a/maths/series/geometric_mean.py +++ b/maths/series/geometric.py @@ -1,12 +1,15 @@ """ -GEOMETRIC MEAN : https://en.wikipedia.org/wiki/Geometric_mean +Geometric Mean +Reference : https://en.wikipedia.org/wiki/Geometric_mean + +Geometric series +Reference: https://en.wikipedia.org/wiki/Geometric_series """ def is_geometric_series(series: list) -> bool: """ checking whether the input series is geometric series or not - >>> is_geometric_series([2, 4, 8]) True >>> is_geometric_series([3, 6, 12, 24]) @@ -15,8 +18,19 @@ def is_geometric_series(series: list) -> bool: False >>> is_geometric_series([0, 0, 3]) False - + >>> is_geometric_series([]) + Traceback (most recent call last): + ... + ValueError: Input list must be a non empty list + >>> is_geometric_series(4) + Traceback (most recent call last): + ... + ValueError: Input series is not valid, valid series - [2, 4, 8] """ + if not isinstance(series, list): + raise ValueError("Input series is not valid, valid series - [2, 4, 8]") + if len(series) == 0: + raise ValueError("Input list must be a non empty list") if len(series) == 1: return True try: @@ -44,13 +58,9 @@ def geometric_mean(series: list) -> float: ... ValueError: Input series is not valid, valid series - [2, 4, 8] >>> geometric_mean([1, 2, 3]) - Traceback (most recent call last): - ... - ValueError: Input list is not a geometric series + 1.8171205928321397 >>> geometric_mean([0, 2, 3]) - Traceback (most recent call last): - ... - ValueError: Input list is not a geometric series + 0.0 >>> geometric_mean([]) Traceback (most recent call last): ... @@ -61,8 +71,6 @@ def geometric_mean(series: list) -> float: raise ValueError("Input series is not valid, valid series - [2, 4, 8]") if len(series) == 0: raise ValueError("Input list must be a non empty list") - if not is_geometric_series(series): - raise ValueError("Input list is not a geometric series") answer = 1 for value in series: answer *= value diff --git a/maths/series/harmonic.py b/maths/series/harmonic.py new file mode 100644 index 000000000..50f29c93d --- /dev/null +++ b/maths/series/harmonic.py @@ -0,0 +1,92 @@ +""" +Harmonic mean +Reference: https://en.wikipedia.org/wiki/Harmonic_mean + +Harmonic series +Reference: https://en.wikipedia.org/wiki/Harmonic_series(mathematics) +""" + + +def is_harmonic_series(series: list) -> bool: + """ + checking whether the input series is arithmetic series or not + >>> is_harmonic_series([ 1, 2/3, 1/2, 2/5, 1/3]) + True + >>> is_harmonic_series([ 1, 2/3, 2/5, 1/3]) + False + >>> is_harmonic_series([1, 2, 3]) + False + >>> is_harmonic_series([1/2, 1/3, 1/4]) + True + >>> is_harmonic_series([2/5, 2/10, 2/15, 2/20, 2/25]) + True + >>> is_harmonic_series(4) + Traceback (most recent call last): + ... + ValueError: Input series is not valid, valid series - [1, 2/3, 2] + >>> is_harmonic_series([]) + Traceback (most recent call last): + ... + ValueError: Input list must be a non empty list + >>> is_harmonic_series([0]) + Traceback (most recent call last): + ... + ValueError: Input series cannot have 0 as an element + >>> is_harmonic_series([1,2,0,6]) + Traceback (most recent call last): + ... + ValueError: Input series cannot have 0 as an element + """ + if not isinstance(series, list): + raise ValueError("Input series is not valid, valid series - [1, 2/3, 2]") + if len(series) == 0: + raise ValueError("Input list must be a non empty list") + if len(series) == 1 and series[0] != 0: + return True + rec_series = [] + series_len = len(series) + for i in range(0, series_len): + if series[i] == 0: + raise ValueError("Input series cannot have 0 as an element") + rec_series.append(1 / series[i]) + common_diff = rec_series[1] - rec_series[0] + for index in range(2, series_len): + if rec_series[index] - rec_series[index - 1] != common_diff: + return False + return True + + +def harmonic_mean(series: list) -> float: + """ + return the harmonic mean of series + + >>> harmonic_mean([1, 4, 4]) + 2.0 + >>> harmonic_mean([3, 6, 9, 12]) + 5.759999999999999 + >>> harmonic_mean(4) + Traceback (most recent call last): + ... + ValueError: Input series is not valid, valid series - [2, 4, 6] + >>> harmonic_mean([1, 2, 3]) + 1.6363636363636365 + >>> harmonic_mean([]) + Traceback (most recent call last): + ... + ValueError: Input list must be a non empty list + + """ + if not isinstance(series, list): + raise ValueError("Input series is not valid, valid series - [2, 4, 6]") + if len(series) == 0: + raise ValueError("Input list must be a non empty list") + answer = 0 + for val in series: + answer += 1 / val + return len(series) / answer + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 0935ab0cb2c3634b553406eefabb5f97011f2e84 Mon Sep 17 00:00:00 2001 From: Jaydeep Das Date: Mon, 18 Oct 2021 12:46:42 +0530 Subject: [PATCH 076/726] Added giphy.py to fetch gifs on a given topic (#5378) * Added giphy.py to fetch gifs on a given topic * Modified code [*]Added doctest [*]Formatted with black * Minor change * Minor refactoring to avoid name clash * Made necessary changes as per review * Update web_programming/giphy.py Co-authored-by: Christian Clauss * Apply suggestions from code review * Final cleanup * Placate psf/black Co-authored-by: Christian Clauss --- web_programming/giphy.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 web_programming/giphy.py diff --git a/web_programming/giphy.py b/web_programming/giphy.py new file mode 100644 index 000000000..dc8c6be08 --- /dev/null +++ b/web_programming/giphy.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +import requests + +giphy_api_key = "YOUR API KEY" +# Can be fetched from https://developers.giphy.com/dashboard/ + + +def get_gifs(query: str, api_key: str = giphy_api_key) -> list: + """ + Get a list of URLs of GIFs based on a given query.. + """ + formatted_query = "+".join(query.split()) + url = f"http://api.giphy.com/v1/gifs/search?q={formatted_query}&api_key={api_key}" + gifs = requests.get(url).json()["data"] + return [gif["url"] for gif in gifs] + + +if __name__ == "__main__": + print("\n".join(get_gifs("space ship"))) From fa88559cab4aa2e935df97b8e2710b34402fc10f Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj <89947037+Rohanrbharadwaj@users.noreply.github.com> Date: Mon, 18 Oct 2021 19:05:35 +0530 Subject: [PATCH 077/726] Create join.py (#5363) * Create join.py Because we have a split.py * Update join.py * Update join.py * Update join.py * Update join.py * Update join.py * Update strings/join.py Co-authored-by: John Law * Update join.py * Update join.py * Update join.py * Update join.py Co-authored-by: John Law --- strings/join.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 strings/join.py diff --git a/strings/join.py b/strings/join.py new file mode 100644 index 000000000..0cb88b760 --- /dev/null +++ b/strings/join.py @@ -0,0 +1,32 @@ +""" +Program to join a list of strings with a given separator +""" + + +def join(separator: str, separated: list) -> str: + """ + >>> join("", ["a", "b", "c", "d"]) + 'abcd' + >>> join("#", ["a", "b", "c", "d"]) + 'a#b#c#d' + >>> join("#", "a") + 'a' + >>> join(" ", ["You", "are", "amazing!"]) + 'You are amazing!' + >>> join("#", ["a", "b", "c", 1]) + Traceback (most recent call last): + ... + Exception: join() accepts only strings to be joined + """ + joined = "" + for word_or_phrase in separated: + if not isinstance(word_or_phrase, str): + raise Exception("join() accepts only strings to be joined") + joined += word_or_phrase + separator + return joined.strip(separator) + + +if "__name__" == "__main__": + from doctest import testmod + + testmod() From 4af521504227c4cada677538163033779cd4df07 Mon Sep 17 00:00:00 2001 From: iradonov <86876427+iradonov@users.noreply.github.com> Date: Mon, 18 Oct 2021 19:46:47 +0300 Subject: [PATCH 078/726] added Schur complement to linear algebra (#4793) * added schur complement and tests to linear algebra * updated according to checklist * updated variable names and typing * added two testcases for input validation * fixed import order Co-authored-by: Ivan Radonov --- linear_algebra/src/schur_complement.py | 94 ++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 linear_algebra/src/schur_complement.py diff --git a/linear_algebra/src/schur_complement.py b/linear_algebra/src/schur_complement.py new file mode 100644 index 000000000..f3cb736d9 --- /dev/null +++ b/linear_algebra/src/schur_complement.py @@ -0,0 +1,94 @@ +import unittest + +import numpy as np + + +def schur_complement( + mat_a: np.ndarray, + mat_b: np.ndarray, + mat_c: np.ndarray, + pseudo_inv: np.ndarray = None, +) -> np.ndarray: + """ + Schur complement of a symmetric matrix X given as a 2x2 block matrix + consisting of matrices A, B and C. + Matrix A must be quadratic and non-singular. + In case A is singular, a pseudo-inverse may be provided using + the pseudo_inv argument. + + Link to Wiki: https://en.wikipedia.org/wiki/Schur_complement + See also Convex Optimization – Boyd and Vandenberghe, A.5.5 + >>> import numpy as np + >>> a = np.array([[1, 2], [2, 1]]) + >>> b = np.array([[0, 3], [3, 0]]) + >>> c = np.array([[2, 1], [6, 3]]) + >>> schur_complement(a, b, c) + array([[ 5., -5.], + [ 0., 6.]]) + """ + shape_a = np.shape(mat_a) + shape_b = np.shape(mat_b) + shape_c = np.shape(mat_c) + + if shape_a[0] != shape_b[0]: + raise ValueError( + f"Expected the same number of rows for A and B. \ + Instead found A of size {shape_a} and B of size {shape_b}" + ) + + if shape_b[1] != shape_c[1]: + raise ValueError( + f"Expected the same number of columns for B and C. \ + Instead found B of size {shape_b} and C of size {shape_c}" + ) + + a_inv = pseudo_inv + if a_inv is None: + try: + a_inv = np.linalg.inv(mat_a) + except np.linalg.LinAlgError: + raise ValueError( + "Input matrix A is not invertible. Cannot compute Schur complement." + ) + + return mat_c - mat_b.T @ a_inv @ mat_b + + +class TestSchurComplement(unittest.TestCase): + def test_schur_complement(self) -> None: + a = np.array([[1, 2, 1], [2, 1, 2], [3, 2, 4]]) + b = np.array([[0, 3], [3, 0], [2, 3]]) + c = np.array([[2, 1], [6, 3]]) + + s = schur_complement(a, b, c) + + input_matrix = np.block([[a, b], [b.T, c]]) + + det_x = np.linalg.det(input_matrix) + det_a = np.linalg.det(a) + det_s = np.linalg.det(s) + + self.assertAlmostEqual(det_x, det_a * det_s) + + def test_improper_a_b_dimensions(self) -> None: + a = np.array([[1, 2, 1], [2, 1, 2], [3, 2, 4]]) + b = np.array([[0, 3], [3, 0], [2, 3]]) + c = np.array([[2, 1], [6, 3]]) + + with self.assertRaises(ValueError): + schur_complement(a, b, c) + + def test_improper_b_c_dimensions(self) -> None: + a = np.array([[1, 2, 1], [2, 1, 2], [3, 2, 4]]) + b = np.array([[0, 3], [3, 0], [2, 3]]) + c = np.array([[2, 1, 3], [6, 3, 5]]) + + with self.assertRaises(ValueError): + schur_complement(a, b, c) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + unittest.main() From d28463c75df4dbaee795c99c05a4021d4cc5e386 Mon Sep 17 00:00:00 2001 From: Jainendra Mandavi Date: Mon, 18 Oct 2021 22:23:10 +0530 Subject: [PATCH 079/726] Create count_1s_brian_kernighan_method (#5385) Ref - http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan --- .../count_1s_brian_kernighan_method.py | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 bit_manipulation/count_1s_brian_kernighan_method.py diff --git a/bit_manipulation/count_1s_brian_kernighan_method.py b/bit_manipulation/count_1s_brian_kernighan_method.py new file mode 100644 index 000000000..d217af90b --- /dev/null +++ b/bit_manipulation/count_1s_brian_kernighan_method.py @@ -0,0 +1,43 @@ +def get_1s_count(number: int) -> int: + """ + Count the number of set bits in a 32 bit integer using Brian Kernighan's way. + Ref - http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan + >>> get_1s_count(25) + 3 + >>> get_1s_count(37) + 3 + >>> get_1s_count(21) + 3 + >>> get_1s_count(58) + 4 + >>> get_1s_count(0) + 0 + >>> get_1s_count(256) + 1 + >>> get_1s_count(-1) + Traceback (most recent call last): + ... + ValueError: the value of input must be positive + >>> get_1s_count(0.8) + Traceback (most recent call last): + ... + TypeError: Input value must be an 'int' type + """ + if number < 0: + raise ValueError("the value of input must be positive") + elif isinstance(number, float): + raise TypeError("Input value must be an 'int' type") + count = 0 + while number: + # This way we arrive at next set bit (next 1) instead of looping + # through each bit and checking for 1s hence the + # loop won't run 32 times it will only run the number of `1` times + number &= number - 1 + count += 1 + return count + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 66c96aa0378eca8bc2c39ca6ae2204096df4c728 Mon Sep 17 00:00:00 2001 From: Sabari Ganesh <64348740+SabariGanesh-K@users.noreply.github.com> Date: Tue, 19 Oct 2021 10:56:03 +0530 Subject: [PATCH 080/726] Added length unit conversions (#5373) * Added length unit conversions Conversion of length units were added with respective tests being implemented and passed. Available Units:- Metre,Kilometre,Feet,Inch,Centimeter,Yard,Foot,Mile,Millimeter * Formatted File File was formatted to go as per repo rules * Reformatted file * Reformatted code once again * Added more test Added test to evaluate whether the code handles wrong arguements passed * Update length_conversions.py * Update length_conversions.py * Update length_conversions.py * Update length_conversions.py * Update length_conversions.py * Update length_conversions.py * Update length_conversions.py * Fixed Minor errors in test One of the test was failing and it was fixed Co-authored-by: Christian Clauss --- conversions/length_conversions.py | 108 ++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 conversions/length_conversions.py diff --git a/conversions/length_conversions.py b/conversions/length_conversions.py new file mode 100644 index 000000000..811a9a916 --- /dev/null +++ b/conversions/length_conversions.py @@ -0,0 +1,108 @@ +""" +Conversion of length units. +Available Units:- Metre,Kilometre,Feet,Inch,Centimeter,Yard,Foot,Mile,Millimeter + +USAGE : +-> Import this file into their respective project. +-> Use the function length_conversion() for conversion of length units. +-> Parameters : + -> value : The number of from units you want to convert + -> from_type : From which type you want to convert + -> to_type : To which type you want to convert + +REFERENCES : +-> Wikipedia reference: https://en.wikipedia.org/wiki/Meter +-> Wikipedia reference: https://en.wikipedia.org/wiki/Kilometer +-> Wikipedia reference: https://en.wikipedia.org/wiki/Feet +-> Wikipedia reference: https://en.wikipedia.org/wiki/Inch +-> Wikipedia reference: https://en.wikipedia.org/wiki/Centimeter +-> Wikipedia reference: https://en.wikipedia.org/wiki/Yard +-> Wikipedia reference: https://en.wikipedia.org/wiki/Foot +-> Wikipedia reference: https://en.wikipedia.org/wiki/Mile +-> Wikipedia reference: https://en.wikipedia.org/wiki/Millimeter +""" + +from collections import namedtuple + +from_to = namedtuple("from_to", "from_ to") + +METRIC_CONVERSION = { + "meter": from_to(1, 1), + "kilometer": from_to(1000, 0.001), + "feet": from_to(0.3048, 3.28084), + "inch": from_to(0.0254, 39.3701), + "centimeter": from_to(0.01, 100), + "yard": from_to(0.9144, 1.09361), + "foot": from_to(0.3048, 3.28084), + "mile": from_to(1609.34, 0.000621371), + "millimeter": from_to(0.001, 1000), +} + + +def length_conversion(value: float, from_type: str, to_type: str) -> float: + """ + Conversion between length units. + + >>> length_conversion(4, "meter", "feet") + 13.12336 + >>> length_conversion(1, "meter", "kilometer") + 0.001 + >>> length_conversion(1, "kilometer", "inch") + 39370.1 + >>> length_conversion(3, "kilometer", "mile") + 1.8641130000000001 + >>> length_conversion(2, "feet", "meter") + 0.6096 + >>> length_conversion(4, "feet", "yard") + 1.333329312 + >>> length_conversion(1, "inch", "meter") + 0.0254 + >>> length_conversion(2, "inch", "mile") + 3.15656468e-05 + >>> length_conversion(2, "centimeter", "millimeter") + 20.0 + >>> length_conversion(2, "centimeter", "yard") + 0.0218722 + >>> length_conversion(4, "yard", "meter") + 3.6576 + >>> length_conversion(4, "yard", "kilometer") + 0.0036576 + >>> length_conversion(3, "foot", "meter") + 0.9144000000000001 + >>> length_conversion(3, "foot", "inch") + 36.00001944 + >>> length_conversion(4, "mile", "kilometer") + 6.43736 + >>> length_conversion(2, "mile", "inch") + 126719.753468 + >>> length_conversion(3, "millimeter", "centimeter") + 0.3 + >>> length_conversion(3, "millimeter", "inch") + 0.1181103 + >>> length_conversion(4, "wrongUnit", "inch") + Traceback (most recent call last): + File "/usr/lib/python3.8/doctest.py", line 1336, in __run + exec(compile(example.source, filename, "single", + File "", line 1, in + length_conversion(4, "wrongUnit", "inch") + File "", line 85, in length_conversion + ValueError: Invalid 'from_type' value: 'wrongUnit' Supported values are: + meter, kilometer, feet, inch, centimeter, yard, foot, mile, millimeter + """ + if from_type not in METRIC_CONVERSION: + raise ValueError( + f"Invalid 'from_type' value: {from_type!r} Supported values are:\n" + + ", ".join(METRIC_CONVERSION) + ) + if to_type not in METRIC_CONVERSION: + raise ValueError( + f"Invalid 'to_type' value: {to_type!r}. Supported values are:\n" + + ", ".join(METRIC_CONVERSION) + ) + return value * METRIC_CONVERSION[from_type].from_ * METRIC_CONVERSION[to_type].to + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From aa0ace4df7dfff3a70685466e96c51dd264e5083 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 19 Oct 2021 08:05:20 +0200 Subject: [PATCH 081/726] Remove exception detail from doctest (#5430) * Remove exception detail from doctest These details are configuration dependant so should be removed according to https://docs.python.org/3/library/doctest.html * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 10 ++++++++-- conversions/length_conversions.py | 6 +----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index c197dd880..cf187a0db 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -32,6 +32,7 @@ * [Binary Shifts](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_shifts.py) * [Binary Twos Complement](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_twos_complement.py) * [Binary Xor Operator](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_xor_operator.py) + * [Count 1S Brian Kernighan Method](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/count_1s_brian_kernighan_method.py) * [Count Number Of One Bits](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/count_number_of_one_bits.py) * [Reverse Bits](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/reverse_bits.py) * [Single Bit Manipulation Operations](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/single_bit_manipulation_operations.py) @@ -112,6 +113,7 @@ * [Decimal To Octal](https://github.com/TheAlgorithms/Python/blob/master/conversions/decimal_to_octal.py) * [Hex To Bin](https://github.com/TheAlgorithms/Python/blob/master/conversions/hex_to_bin.py) * [Hexadecimal To Decimal](https://github.com/TheAlgorithms/Python/blob/master/conversions/hexadecimal_to_decimal.py) + * [Length Conversions](https://github.com/TheAlgorithms/Python/blob/master/conversions/length_conversions.py) * [Molecular Chemistry](https://github.com/TheAlgorithms/Python/blob/master/conversions/molecular_chemistry.py) * [Octal To Decimal](https://github.com/TheAlgorithms/Python/blob/master/conversions/octal_to_decimal.py) * [Prefix Conversions](https://github.com/TheAlgorithms/Python/blob/master/conversions/prefix_conversions.py) @@ -381,6 +383,7 @@ * [Polynom For Points](https://github.com/TheAlgorithms/Python/blob/master/linear_algebra/src/polynom_for_points.py) * [Power Iteration](https://github.com/TheAlgorithms/Python/blob/master/linear_algebra/src/power_iteration.py) * [Rayleigh Quotient](https://github.com/TheAlgorithms/Python/blob/master/linear_algebra/src/rayleigh_quotient.py) + * [Schur Complement](https://github.com/TheAlgorithms/Python/blob/master/linear_algebra/src/schur_complement.py) * [Test Linear Algebra](https://github.com/TheAlgorithms/Python/blob/master/linear_algebra/src/test_linear_algebra.py) * [Transformations 2D](https://github.com/TheAlgorithms/Python/blob/master/linear_algebra/src/transformations_2d.py) @@ -513,9 +516,10 @@ * [Runge Kutta](https://github.com/TheAlgorithms/Python/blob/master/maths/runge_kutta.py) * [Segmented Sieve](https://github.com/TheAlgorithms/Python/blob/master/maths/segmented_sieve.py) * Series - * [Arithmetic Mean](https://github.com/TheAlgorithms/Python/blob/master/maths/series/arithmetic_mean.py) - * [Geometric Mean](https://github.com/TheAlgorithms/Python/blob/master/maths/series/geometric_mean.py) + * [Arithmetic](https://github.com/TheAlgorithms/Python/blob/master/maths/series/arithmetic.py) + * [Geometric](https://github.com/TheAlgorithms/Python/blob/master/maths/series/geometric.py) * [Geometric Series](https://github.com/TheAlgorithms/Python/blob/master/maths/series/geometric_series.py) + * [Harmonic](https://github.com/TheAlgorithms/Python/blob/master/maths/series/harmonic.py) * [Harmonic Series](https://github.com/TheAlgorithms/Python/blob/master/maths/series/harmonic_series.py) * [P Series](https://github.com/TheAlgorithms/Python/blob/master/maths/series/p_series.py) * [Sieve Of Eratosthenes](https://github.com/TheAlgorithms/Python/blob/master/maths/sieve_of_eratosthenes.py) @@ -933,6 +937,7 @@ * [Indian Phone Validator](https://github.com/TheAlgorithms/Python/blob/master/strings/indian_phone_validator.py) * [Is Palindrome](https://github.com/TheAlgorithms/Python/blob/master/strings/is_palindrome.py) * [Jaro Winkler](https://github.com/TheAlgorithms/Python/blob/master/strings/jaro_winkler.py) + * [Join](https://github.com/TheAlgorithms/Python/blob/master/strings/join.py) * [Knuth Morris Pratt](https://github.com/TheAlgorithms/Python/blob/master/strings/knuth_morris_pratt.py) * [Levenshtein Distance](https://github.com/TheAlgorithms/Python/blob/master/strings/levenshtein_distance.py) * [Lower](https://github.com/TheAlgorithms/Python/blob/master/strings/lower.py) @@ -967,6 +972,7 @@ * [Fetch Jobs](https://github.com/TheAlgorithms/Python/blob/master/web_programming/fetch_jobs.py) * [Get Imdb Top 250 Movies Csv](https://github.com/TheAlgorithms/Python/blob/master/web_programming/get_imdb_top_250_movies_csv.py) * [Get Imdbtop](https://github.com/TheAlgorithms/Python/blob/master/web_programming/get_imdbtop.py) + * [Giphy](https://github.com/TheAlgorithms/Python/blob/master/web_programming/giphy.py) * [Instagram Crawler](https://github.com/TheAlgorithms/Python/blob/master/web_programming/instagram_crawler.py) * [Instagram Pic](https://github.com/TheAlgorithms/Python/blob/master/web_programming/instagram_pic.py) * [Instagram Video](https://github.com/TheAlgorithms/Python/blob/master/web_programming/instagram_video.py) diff --git a/conversions/length_conversions.py b/conversions/length_conversions.py index 811a9a916..8d0d3a424 100644 --- a/conversions/length_conversions.py +++ b/conversions/length_conversions.py @@ -81,11 +81,7 @@ def length_conversion(value: float, from_type: str, to_type: str) -> float: 0.1181103 >>> length_conversion(4, "wrongUnit", "inch") Traceback (most recent call last): - File "/usr/lib/python3.8/doctest.py", line 1336, in __run - exec(compile(example.source, filename, "single", - File "", line 1, in - length_conversion(4, "wrongUnit", "inch") - File "", line 85, in length_conversion + ... ValueError: Invalid 'from_type' value: 'wrongUnit' Supported values are: meter, kilometer, feet, inch, centimeter, yard, foot, mile, millimeter """ From 4880931c2451d00a6b9b830f84b23af847b276a0 Mon Sep 17 00:00:00 2001 From: Vinicius Cordeiro <78505368+cordeirossauro@users.noreply.github.com> Date: Tue, 19 Oct 2021 03:37:51 -0300 Subject: [PATCH 082/726] Add Polybius cipher (#5409) * Add polybius cipher * Fix polybius.py build issues and add test --- ciphers/polybius.py | 96 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 ciphers/polybius.py diff --git a/ciphers/polybius.py b/ciphers/polybius.py new file mode 100644 index 000000000..9e1dc4cbb --- /dev/null +++ b/ciphers/polybius.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 + +""" +A Polybius Square is a table that allows someone to translate letters into numbers. + +https://www.braingle.com/brainteasers/codes/polybius.php +""" + +import numpy as np + + +class PolybiusCipher: + def __init__(self) -> None: + SQUARE = [ + ["a", "b", "c", "d", "e"], + ["f", "g", "h", "i", "k"], + ["l", "m", "n", "o", "p"], + ["q", "r", "s", "t", "u"], + ["v", "w", "x", "y", "z"], + ] + self.SQUARE = np.array(SQUARE) + + def letter_to_numbers(self, letter: str) -> np.ndarray: + """ + Return the pair of numbers that represents the given letter in the + polybius square + >>> np.array_equal(PolybiusCipher().letter_to_numbers('a'), [1,1]) + True + + >>> np.array_equal(PolybiusCipher().letter_to_numbers('u'), [4,5]) + True + """ + index1, index2 = np.where(self.SQUARE == letter) + indexes = np.concatenate([index1 + 1, index2 + 1]) + return indexes + + def numbers_to_letter(self, index1: int, index2: int) -> str: + """ + Return the letter corresponding to the position [index1, index2] in + the polybius square + + >>> PolybiusCipher().numbers_to_letter(4, 5) == "u" + True + + >>> PolybiusCipher().numbers_to_letter(1, 1) == "a" + True + """ + letter = self.SQUARE[index1 - 1, index2 - 1] + return letter + + def encode(self, message: str) -> str: + """ + Return the encoded version of message according to the polybius cipher + + >>> PolybiusCipher().encode("test message") == "44154344 32154343112215" + True + + >>> PolybiusCipher().encode("Test Message") == "44154344 32154343112215" + True + """ + message = message.lower() + message = message.replace("j", "i") + + encoded_message = "" + for letter_index in range(len(message)): + if message[letter_index] != " ": + numbers = self.letter_to_numbers(message[letter_index]) + encoded_message = encoded_message + str(numbers[0]) + str(numbers[1]) + elif message[letter_index] == " ": + encoded_message = encoded_message + " " + + return encoded_message + + def decode(self, message: str) -> str: + """ + Return the decoded version of message according to the polybius cipher + + >>> PolybiusCipher().decode("44154344 32154343112215") == "test message" + True + + >>> PolybiusCipher().decode("4415434432154343112215") == "testmessage" + True + """ + message = message.replace(" ", " ") + decoded_message = "" + for numbers_index in range(int(len(message) / 2)): + if message[numbers_index * 2] != " ": + index1 = message[numbers_index * 2] + index2 = message[numbers_index * 2 + 1] + + letter = self.numbers_to_letter(int(index1), int(index2)) + decoded_message = decoded_message + letter + elif message[numbers_index * 2] == " ": + decoded_message = decoded_message + " " + + return decoded_message From f7804334f15681510d4f3a008bafe742cb65d97f Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 19 Oct 2021 11:11:49 +0200 Subject: [PATCH 083/726] length_conversion.py: Deal with uppercase and abbreviations (#5433) * length_conversion.py: Deal with uppercase and abbreviations * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 2 +- ...th_conversions.py => length_conversion.py} | 60 ++++++++++++------- 2 files changed, 40 insertions(+), 22 deletions(-) rename conversions/{length_conversions.py => length_conversion.py} (60%) diff --git a/DIRECTORY.md b/DIRECTORY.md index cf187a0db..e3b40530a 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -113,7 +113,7 @@ * [Decimal To Octal](https://github.com/TheAlgorithms/Python/blob/master/conversions/decimal_to_octal.py) * [Hex To Bin](https://github.com/TheAlgorithms/Python/blob/master/conversions/hex_to_bin.py) * [Hexadecimal To Decimal](https://github.com/TheAlgorithms/Python/blob/master/conversions/hexadecimal_to_decimal.py) - * [Length Conversions](https://github.com/TheAlgorithms/Python/blob/master/conversions/length_conversions.py) + * [Length Conversion](https://github.com/TheAlgorithms/Python/blob/master/conversions/length_conversion.py) * [Molecular Chemistry](https://github.com/TheAlgorithms/Python/blob/master/conversions/molecular_chemistry.py) * [Octal To Decimal](https://github.com/TheAlgorithms/Python/blob/master/conversions/octal_to_decimal.py) * [Prefix Conversions](https://github.com/TheAlgorithms/Python/blob/master/conversions/prefix_conversions.py) diff --git a/conversions/length_conversions.py b/conversions/length_conversion.py similarity index 60% rename from conversions/length_conversions.py rename to conversions/length_conversion.py index 8d0d3a424..790d9c116 100644 --- a/conversions/length_conversions.py +++ b/conversions/length_conversion.py @@ -26,16 +26,28 @@ from collections import namedtuple from_to = namedtuple("from_to", "from_ to") +TYPE_CONVERSION = { + "millimeter": "mm", + "centimeter": "cm", + "meter": "m", + "kilometer": "km", + "inch": "in", + "inche": "in", # Trailing 's' has been stripped off + "feet": "ft", + "foot": "ft", + "yard": "yd", + "mile": "mi", +} + METRIC_CONVERSION = { - "meter": from_to(1, 1), - "kilometer": from_to(1000, 0.001), - "feet": from_to(0.3048, 3.28084), - "inch": from_to(0.0254, 39.3701), - "centimeter": from_to(0.01, 100), - "yard": from_to(0.9144, 1.09361), - "foot": from_to(0.3048, 3.28084), - "mile": from_to(1609.34, 0.000621371), - "millimeter": from_to(0.001, 1000), + "mm": from_to(0.001, 1000), + "cm": from_to(0.01, 100), + "m": from_to(1, 1), + "km": from_to(1000, 0.001), + "in": from_to(0.0254, 39.3701), + "ft": from_to(0.3048, 3.28084), + "yd": from_to(0.9144, 1.09361), + "mi": from_to(1609.34, 0.000621371), } @@ -43,7 +55,9 @@ def length_conversion(value: float, from_type: str, to_type: str) -> float: """ Conversion between length units. - >>> length_conversion(4, "meter", "feet") + >>> length_conversion(4, "METER", "FEET") + 13.12336 + >>> length_conversion(4, "M", "FT") 13.12336 >>> length_conversion(1, "meter", "kilometer") 0.001 @@ -73,29 +87,33 @@ def length_conversion(value: float, from_type: str, to_type: str) -> float: 36.00001944 >>> length_conversion(4, "mile", "kilometer") 6.43736 - >>> length_conversion(2, "mile", "inch") + >>> length_conversion(2, "miles", "InChEs") 126719.753468 >>> length_conversion(3, "millimeter", "centimeter") 0.3 - >>> length_conversion(3, "millimeter", "inch") + >>> length_conversion(3, "mm", "in") 0.1181103 >>> length_conversion(4, "wrongUnit", "inch") Traceback (most recent call last): ... - ValueError: Invalid 'from_type' value: 'wrongUnit' Supported values are: - meter, kilometer, feet, inch, centimeter, yard, foot, mile, millimeter + ValueError: Invalid 'from_type' value: 'wrongUnit'. + Conversion abbreviations are: mm, cm, m, km, in, ft, yd, mi """ - if from_type not in METRIC_CONVERSION: + new_from = from_type.lower().rstrip("s") + new_from = TYPE_CONVERSION.get(new_from, new_from) + new_to = to_type.lower().rstrip("s") + new_to = TYPE_CONVERSION.get(new_to, new_to) + if new_from not in METRIC_CONVERSION: raise ValueError( - f"Invalid 'from_type' value: {from_type!r} Supported values are:\n" - + ", ".join(METRIC_CONVERSION) + f"Invalid 'from_type' value: {from_type!r}.\n" + f"Conversion abbreviations are: {', '.join(METRIC_CONVERSION)}" ) - if to_type not in METRIC_CONVERSION: + if new_to not in METRIC_CONVERSION: raise ValueError( - f"Invalid 'to_type' value: {to_type!r}. Supported values are:\n" - + ", ".join(METRIC_CONVERSION) + f"Invalid 'to_type' value: {to_type!r}.\n" + f"Conversion abbreviations are: {', '.join(METRIC_CONVERSION)}" ) - return value * METRIC_CONVERSION[from_type].from_ * METRIC_CONVERSION[to_type].to + return value * METRIC_CONVERSION[new_from].from_ * METRIC_CONVERSION[new_to].to if __name__ == "__main__": From 21cf3cc2603de8598b717ef13a530f5fa12b9c47 Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj <89947037+Rohanrbharadwaj@users.noreply.github.com> Date: Wed, 20 Oct 2021 01:06:01 +0530 Subject: [PATCH 084/726] Typo (#5443) --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e9cf0e6a1..4723c6c39 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,7 +13,7 @@ We are very happy that you consider implementing algorithms and data structure f - You did your work - no plagiarism allowed - Any plagiarized work will not be merged. - Your work will be distributed under [MIT License](LICENSE.md) once your pull request is merged -- You submitted work fulfils or mostly fulfils our styles and standards +- Your submitted work fulfils or mostly fulfils our styles and standards __New implementation__ is welcome! For example, new solutions for a problem, different representations for a graph data structure or algorithm designs with different complexity but __identical implementation__ of an existing implementation is not allowed. Please check whether the solution is already implemented or not before submitting your pull request. From d32d0158a3b56a4a4ad7bcfdd66e5835f2d594c7 Mon Sep 17 00:00:00 2001 From: Alvin Philips Date: Wed, 20 Oct 2021 01:09:15 +0530 Subject: [PATCH 085/726] Fixed typo (#5439) Changed it's (it is) to its --- data_structures/binary_tree/binary_tree_mirror.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/binary_tree/binary_tree_mirror.py b/data_structures/binary_tree/binary_tree_mirror.py index dc7f657b3..cdd56e35d 100644 --- a/data_structures/binary_tree/binary_tree_mirror.py +++ b/data_structures/binary_tree/binary_tree_mirror.py @@ -1,6 +1,6 @@ """ Problem Description: -Given a binary tree, return it's mirror. +Given a binary tree, return its mirror. """ From c886a66d34b1bf8796d261c94f983a43453828d7 Mon Sep 17 00:00:00 2001 From: Snimerjot Singh Date: Wed, 20 Oct 2021 11:05:41 +0530 Subject: [PATCH 086/726] Added check_strong_password.py (#4950) * Added check_strong_password.py * Corrected Comment * Updated * Updated check_strong_password.py * Ran Pre-Commit --- other/check_strong_password.py | 47 ++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 other/check_strong_password.py diff --git a/other/check_strong_password.py b/other/check_strong_password.py new file mode 100644 index 000000000..95bb327ad --- /dev/null +++ b/other/check_strong_password.py @@ -0,0 +1,47 @@ +# This Will Check Whether A Given Password Is Strong Or Not +# It Follows The Rule that Length Of Password Should Be At Least 8 Characters +# And At Least 1 Lower, 1 Upper, 1 Number And 1 Special Character + +from string import ascii_lowercase, ascii_uppercase, digits, punctuation + + +def strong_password_detector(password: str, min_length: int = 8) -> str: + """ + >>> strong_password_detector('Hwea7$2!') + 'This is a strong Password' + + >>> strong_password_detector('Sh0r1') + 'Your Password must be at least 8 characters long' + + >>> strong_password_detector('Hello123') + 'Password should contain UPPERCASE, lowercase, numbers, special characters' + + >>> strong_password_detector('Hello1238udfhiaf038fajdvjjf!jaiuFhkqi1') + 'This is a strong Password' + + >>> strong_password_detector(0) + 'Your Password must be at least 8 characters long' + """ + + if len(str(password)) < 8: + return "Your Password must be at least 8 characters long" + + upper = any(char in ascii_uppercase for char in password) + lower = any(char in ascii_lowercase for char in password) + num = any(char in digits for char in password) + spec_char = any(char in punctuation for char in password) + + if upper and lower and num and spec_char: + return "This is a strong Password" + + else: + return ( + "Password should contain UPPERCASE, lowercase, " + "numbers, special characters" + ) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 2e2e1b656cf12789c0cc93ad4d2a4771be86cbab Mon Sep 17 00:00:00 2001 From: Immiel Date: Wed, 20 Oct 2021 15:08:39 +0700 Subject: [PATCH 087/726] singly_linked_list: Added additional documentation, type hints and test cases (#4988) This is a followup to https://github.com/TheAlgorithms/Python/pull/4973#issuecomment-933117382 As per given suggestion, I've added type hints to certain methods that don't have them. I have also added documentation and example doctests as a usage example for (most of) those that don't have them. I have also added another test case following the previous test case's format. I noticed that the existing test case from previous pull request might be redundant with the ones I've made, so I decided to create a specific situation where the linked list would have to keep different kinds of data types for each node, in `test_singly_linked_list_2` test function. Some minor changes in strings has been done to keep things consistent with other parts of the document. If it is undesirable, please let me know. --- .../linked_list/singly_linked_list.py | 295 +++++++++++++++++- 1 file changed, 280 insertions(+), 15 deletions(-) diff --git a/data_structures/linked_list/singly_linked_list.py b/data_structures/linked_list/singly_linked_list.py index e45a210a1..4a5dc8263 100644 --- a/data_structures/linked_list/singly_linked_list.py +++ b/data_structures/linked_list/singly_linked_list.py @@ -1,17 +1,53 @@ +from typing import Any + + class Node: - def __init__(self, data): + def __init__(self, data: Any): + """ + Create and initialize Node class instance. + >>> Node(20) + Node(20) + >>> Node("Hello, world!") + Node(Hello, world!) + >>> Node(None) + Node(None) + >>> Node(True) + Node(True) + """ self.data = data self.next = None - def __repr__(self): + def __repr__(self) -> str: + """ + Get the string representation of this node. + >>> Node(10).__repr__() + 'Node(10)' + """ return f"Node({self.data})" class LinkedList: def __init__(self): + """ + Create and initialize LinkedList class instance. + >>> linked_list = LinkedList() + """ self.head = None - def __iter__(self): + def __iter__(self) -> Any: + """ + This function is intended for iterators to access + and iterate through data inside linked list. + >>> linked_list = LinkedList() + >>> linked_list.insert_tail("tail") + >>> linked_list.insert_tail("tail_1") + >>> linked_list.insert_tail("tail_2") + >>> for node in linked_list: # __iter__ used here. + ... node + 'tail' + 'tail_1' + 'tail_2' + """ node = self.head while node: yield node.data @@ -23,7 +59,7 @@ class LinkedList: >>> linked_list = LinkedList() >>> len(linked_list) 0 - >>> linked_list.insert_tail("head") + >>> linked_list.insert_tail("tail") >>> len(linked_list) 1 >>> linked_list.insert_head("head") @@ -38,13 +74,18 @@ class LinkedList: """ return len(tuple(iter(self))) - def __repr__(self): + def __repr__(self) -> str: """ String representation/visualization of a Linked Lists + >>> linked_list = LinkedList() + >>> linked_list.insert_tail(1) + >>> linked_list.insert_tail(3) + >>> linked_list.__repr__() + '1->3' """ return "->".join([str(item) for item in self]) - def __getitem__(self, index): + def __getitem__(self, index: int) -> Any: """ Indexing Support. Used to get a node at particular position >>> linked_list = LinkedList() @@ -68,7 +109,7 @@ class LinkedList: return node # Used to change the data of a particular node - def __setitem__(self, index, data): + def __setitem__(self, index: int, data: Any) -> None: """ >>> linked_list = LinkedList() >>> for i in range(0, 10): @@ -95,13 +136,54 @@ class LinkedList: current = current.next current.data = data - def insert_tail(self, data) -> None: + def insert_tail(self, data: Any) -> None: + """ + Insert data to the end of linked list. + >>> linked_list = LinkedList() + >>> linked_list.insert_tail("tail") + >>> linked_list + tail + >>> linked_list.insert_tail("tail_2") + >>> linked_list + tail->tail_2 + >>> linked_list.insert_tail("tail_3") + >>> linked_list + tail->tail_2->tail_3 + """ self.insert_nth(len(self), data) - def insert_head(self, data) -> None: + def insert_head(self, data: Any) -> None: + """ + Insert data to the beginning of linked list. + >>> linked_list = LinkedList() + >>> linked_list.insert_head("head") + >>> linked_list + head + >>> linked_list.insert_head("head_2") + >>> linked_list + head_2->head + >>> linked_list.insert_head("head_3") + >>> linked_list + head_3->head_2->head + """ self.insert_nth(0, data) - def insert_nth(self, index: int, data) -> None: + def insert_nth(self, index: int, data: Any) -> None: + """ + Insert data at given index. + >>> linked_list = LinkedList() + >>> linked_list.insert_tail("first") + >>> linked_list.insert_tail("second") + >>> linked_list.insert_tail("third") + >>> linked_list + first->second->third + >>> linked_list.insert_nth(1, "fourth") + >>> linked_list + first->fourth->second->third + >>> linked_list.insert_nth(3, "fifth") + >>> linked_list + first->fourth->second->fifth->third + """ if not 0 <= index <= len(self): raise IndexError("list index out of range") new_node = Node(data) @@ -118,17 +200,96 @@ class LinkedList: temp.next = new_node def print_list(self) -> None: # print every node data + """ + This method prints every node data. + >>> linked_list = LinkedList() + >>> linked_list.insert_tail("first") + >>> linked_list.insert_tail("second") + >>> linked_list.insert_tail("third") + >>> linked_list + first->second->third + """ print(self) - def delete_head(self): + def delete_head(self) -> Any: + """ + Delete the first node and return the + node's data. + >>> linked_list = LinkedList() + >>> linked_list.insert_tail("first") + >>> linked_list.insert_tail("second") + >>> linked_list.insert_tail("third") + >>> linked_list + first->second->third + >>> linked_list.delete_head() + 'first' + >>> linked_list + second->third + >>> linked_list.delete_head() + 'second' + >>> linked_list + third + >>> linked_list.delete_head() + 'third' + >>> linked_list.delete_head() + Traceback (most recent call last): + ... + IndexError: List index out of range. + """ return self.delete_nth(0) - def delete_tail(self): # delete from tail + def delete_tail(self) -> Any: # delete from tail + """ + Delete the tail end node and return the + node's data. + >>> linked_list = LinkedList() + >>> linked_list.insert_tail("first") + >>> linked_list.insert_tail("second") + >>> linked_list.insert_tail("third") + >>> linked_list + first->second->third + >>> linked_list.delete_tail() + 'third' + >>> linked_list + first->second + >>> linked_list.delete_tail() + 'second' + >>> linked_list + first + >>> linked_list.delete_tail() + 'first' + >>> linked_list.delete_tail() + Traceback (most recent call last): + ... + IndexError: List index out of range. + """ return self.delete_nth(len(self) - 1) - def delete_nth(self, index: int = 0): + def delete_nth(self, index: int = 0) -> Any: + """ + Delete node at given index and return the + node's data. + >>> linked_list = LinkedList() + >>> linked_list.insert_tail("first") + >>> linked_list.insert_tail("second") + >>> linked_list.insert_tail("third") + >>> linked_list + first->second->third + >>> linked_list.delete_nth(1) # delete middle + 'second' + >>> linked_list + first->third + >>> linked_list.delete_nth(5) # this raises error + Traceback (most recent call last): + ... + IndexError: List index out of range. + >>> linked_list.delete_nth(-1) # this also raises error + Traceback (most recent call last): + ... + IndexError: List index out of range. + """ if not 0 <= index <= len(self) - 1: # test if index is valid - raise IndexError("list index out of range") + raise IndexError("List index out of range.") delete_node = self.head # default first node if index == 0: self.head = self.head.next @@ -141,9 +302,30 @@ class LinkedList: return delete_node.data def is_empty(self) -> bool: + """ + Check if linked list is empty. + >>> linked_list = LinkedList() + >>> linked_list.is_empty() + True + >>> linked_list.insert_head("first") + >>> linked_list.is_empty() + False + """ return self.head is None - def reverse(self): + def reverse(self) -> None: + """ + This reverses the linked list order. + >>> linked_list = LinkedList() + >>> linked_list.insert_tail("first") + >>> linked_list.insert_tail("second") + >>> linked_list.insert_tail("third") + >>> linked_list + first->second->third + >>> linked_list.reverse() + >>> linked_list + third->second->first + """ prev = None current = self.head @@ -201,6 +383,89 @@ def test_singly_linked_list() -> None: linked_list[i] = -i assert all(linked_list[i] == -i for i in range(0, 9)) is True + linked_list.reverse() + assert str(linked_list) == "->".join(str(i) for i in range(-8, 1)) + + +def test_singly_linked_list_2() -> None: + """ + This section of the test used varying data types for input. + >>> test_singly_linked_list_2() + """ + input = [ + -9, + 100, + Node(77345112), + "dlrow olleH", + 7, + 5555, + 0, + -192.55555, + "Hello, world!", + 77.9, + Node(10), + None, + None, + 12.20, + ] + linked_list = LinkedList() + [linked_list.insert_tail(i) for i in input] + + # Check if it's empty or not + assert linked_list.is_empty() is False + assert ( + str(linked_list) == "-9->100->Node(77345112)->dlrow olleH->7->5555->0->" + "-192.55555->Hello, world!->77.9->Node(10)->None->None->12.2" + ) + + # Delete the head + result = linked_list.delete_head() + assert result == -9 + assert ( + str(linked_list) == "100->Node(77345112)->dlrow olleH->7->5555->0->-192.55555->" + "Hello, world!->77.9->Node(10)->None->None->12.2" + ) + + # Delete the tail + result = linked_list.delete_tail() + assert result == 12.2 + assert ( + str(linked_list) == "100->Node(77345112)->dlrow olleH->7->5555->0->-192.55555->" + "Hello, world!->77.9->Node(10)->None->None" + ) + + # Delete a node in specific location in linked list + result = linked_list.delete_nth(10) + assert result is None + assert ( + str(linked_list) == "100->Node(77345112)->dlrow olleH->7->5555->0->-192.55555->" + "Hello, world!->77.9->Node(10)->None" + ) + + # Add a Node instance to its head + linked_list.insert_head(Node("Hello again, world!")) + assert ( + str(linked_list) + == "Node(Hello again, world!)->100->Node(77345112)->dlrow olleH->" + "7->5555->0->-192.55555->Hello, world!->77.9->Node(10)->None" + ) + + # Add None to its tail + linked_list.insert_tail(None) + assert ( + str(linked_list) + == "Node(Hello again, world!)->100->Node(77345112)->dlrow olleH->" + "7->5555->0->-192.55555->Hello, world!->77.9->Node(10)->None->None" + ) + + # Reverse the linked list + linked_list.reverse() + assert ( + str(linked_list) + == "None->None->Node(10)->77.9->Hello, world!->-192.55555->0->5555->" + "7->dlrow olleH->Node(77345112)->100->Node(Hello again, world!)" + ) + def main(): from doctest import testmod From 83cf5786cddd694a2af25827f8861b7dbcbf706c Mon Sep 17 00:00:00 2001 From: P U N I T H <55887644+punithbajaj@users.noreply.github.com> Date: Wed, 20 Oct 2021 14:00:58 +0530 Subject: [PATCH 088/726] Add wildcard pattern matching using dynamic programming (#5334) * Added regular expression implimentation using dp * replaced input() with example values * Apply suggestions from code review Co-authored-by: Christian Clauss * changed returning value to bool and added test cases * added doctest Co-authored-by: John Law * added test cases * Apply suggestions from code review Co-authored-by: John Law * shifted to strings * Changed filename * Update function name to match_pattern Co-authored-by: John Law * Update function name to match_pattern Co-authored-by: John Law Co-authored-by: Christian Clauss Co-authored-by: John Law --- strings/wildcard_pattern_matching.py | 112 +++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 strings/wildcard_pattern_matching.py diff --git a/strings/wildcard_pattern_matching.py b/strings/wildcard_pattern_matching.py new file mode 100644 index 000000000..83c8d834c --- /dev/null +++ b/strings/wildcard_pattern_matching.py @@ -0,0 +1,112 @@ +""" +Implementation of regular expression matching with support for '.' and '*'. +'.' Matches any single character. +'*' Matches zero or more of the preceding element. +The matching should cover the entire input string (not partial). + +""" + + +def match_pattern(input_string: str, pattern: str) -> bool: + """ + uses bottom-up dynamic programming solution for matching the input + string with a given pattern. + + Runtime: O(len(input_string)*len(pattern)) + + Arguments + -------- + input_string: str, any string which should be compared with the pattern + pattern: str, the string that represents a pattern and may contain + '.' for single character matches and '*' for zero or more of preceding character + matches + + Note + ---- + the pattern cannot start with a '*', + because there should be at least one character before * + + Returns + ------- + A Boolean denoting whether the given string follows the pattern + + Examples + ------- + >>> match_pattern("aab", "c*a*b") + True + >>> match_pattern("dabc", "*abc") + False + >>> match_pattern("aaa", "aa") + False + >>> match_pattern("aaa", "a.a") + True + >>> match_pattern("aaab", "aa*") + False + >>> match_pattern("aaab", ".*") + True + >>> match_pattern("a", "bbbb") + False + >>> match_pattern("", "bbbb") + False + >>> match_pattern("a", "") + False + >>> match_pattern("", "") + True + """ + + len_string = len(input_string) + 1 + len_pattern = len(pattern) + 1 + + # dp is a 2d matrix where dp[i][j] denotes whether prefix string of + # length i of input_string matches with prefix string of length j of + # given pattern. + # "dp" stands for dynamic programming. + dp = [[0 for i in range(len_pattern)] for j in range(len_string)] + + # since string of zero length match pattern of zero length + dp[0][0] = 1 + + # since pattern of zero length will never match with string of non-zero length + for i in range(1, len_string): + dp[i][0] = 0 + + # since string of zero length will match with pattern where there + # is at least one * alternatively + for j in range(1, len_pattern): + dp[0][j] = dp[0][j - 2] if pattern[j - 1] == "*" else 0 + + # now using bottom-up approach to find for all remaining lengths + for i in range(1, len_string): + for j in range(1, len_pattern): + if input_string[i - 1] == pattern[j - 1] or pattern[j - 1] == ".": + dp[i][j] = dp[i - 1][j - 1] + + elif pattern[j - 1] == "*": + if dp[i][j - 2] == 1: + dp[i][j] = 1 + elif pattern[j - 2] in (input_string[i - 1], "."): + dp[i][j] = dp[i - 1][j] + else: + dp[i][j] = 0 + else: + dp[i][j] = 0 + + return bool(dp[-1][-1]) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + # inputing the strings + # input_string = input("input a string :") + # pattern = input("input a pattern :") + + input_string = "aab" + pattern = "c*a*b" + + # using function to check whether given string matches the given pattern + if match_pattern(input_string, pattern): + print(f"{input_string} matches the given pattern {pattern}") + else: + print(f"{input_string} does not match with the given pattern {pattern}") From 50485f7c8e33b0a3bf6e603cdae3505d40b1d97a Mon Sep 17 00:00:00 2001 From: Manan Rathi <76519771+Manan-Rathi@users.noreply.github.com> Date: Wed, 20 Oct 2021 14:12:32 +0530 Subject: [PATCH 089/726] Fix typos in Sorts and Bit_manipulation (#4949) * Fix several typos * Update bit_manipulation/README.md Co-authored-by: John Law * Update double_sort.py Co-authored-by: John Law --- bit_manipulation/README.md | 13 ++++++------- bit_manipulation/binary_and_operator.py | 4 ++-- bit_manipulation/binary_or_operator.py | 4 ++-- bit_manipulation/binary_xor_operator.py | 4 ++-- sorts/bead_sort.py | 6 +++--- sorts/double_sort.py | 6 +++--- 6 files changed, 18 insertions(+), 19 deletions(-) diff --git a/bit_manipulation/README.md b/bit_manipulation/README.md index 2ef166152..e5f82a270 100644 --- a/bit_manipulation/README.md +++ b/bit_manipulation/README.md @@ -1,7 +1,6 @@ -https://docs.python.org/3/reference/expressions.html#binary-bitwise-operations -https://docs.python.org/3/reference/expressions.html#unary-arithmetic-and-bitwise-operations -https://docs.python.org/3/library/stdtypes.html#bitwise-operations-on-integer-types - -https://wiki.python.org/moin/BitManipulation -https://wiki.python.org/moin/BitwiseOperators -https://www.tutorialspoint.com/python3/bitwise_operators_example.htm +* https://docs.python.org/3/reference/expressions.html#binary-bitwise-operations +* https://docs.python.org/3/reference/expressions.html#unary-arithmetic-and-bitwise-operations +* https://docs.python.org/3/library/stdtypes.html#bitwise-operations-on-integer-types +* https://wiki.python.org/moin/BitManipulation +* https://wiki.python.org/moin/BitwiseOperators +* https://www.tutorialspoint.com/python3/bitwise_operators_example.htm diff --git a/bit_manipulation/binary_and_operator.py b/bit_manipulation/binary_and_operator.py index 191ff8eb4..36f6c668d 100644 --- a/bit_manipulation/binary_and_operator.py +++ b/bit_manipulation/binary_and_operator.py @@ -22,7 +22,7 @@ def binary_and(a: int, b: int) -> str: >>> binary_and(0, -1) Traceback (most recent call last): ... - ValueError: the value of both input must be positive + ValueError: the value of both inputs must be positive >>> binary_and(0, 1.1) Traceback (most recent call last): ... @@ -33,7 +33,7 @@ def binary_and(a: int, b: int) -> str: TypeError: '<' not supported between instances of 'str' and 'int' """ if a < 0 or b < 0: - raise ValueError("the value of both input must be positive") + raise ValueError("the value of both inputs must be positive") a_binary = str(bin(a))[2:] # remove the leading "0b" b_binary = str(bin(b))[2:] # remove the leading "0b" diff --git a/bit_manipulation/binary_or_operator.py b/bit_manipulation/binary_or_operator.py index dabf5bcb0..95f61f1da 100644 --- a/bit_manipulation/binary_or_operator.py +++ b/bit_manipulation/binary_or_operator.py @@ -21,7 +21,7 @@ def binary_or(a: int, b: int) -> str: >>> binary_or(0, -1) Traceback (most recent call last): ... - ValueError: the value of both input must be positive + ValueError: the value of both inputs must be positive >>> binary_or(0, 1.1) Traceback (most recent call last): ... @@ -32,7 +32,7 @@ def binary_or(a: int, b: int) -> str: TypeError: '<' not supported between instances of 'str' and 'int' """ if a < 0 or b < 0: - raise ValueError("the value of both input must be positive") + raise ValueError("the value of both inputs must be positive") a_binary = str(bin(a))[2:] # remove the leading "0b" b_binary = str(bin(b))[2:] max_len = max(len(a_binary), len(b_binary)) diff --git a/bit_manipulation/binary_xor_operator.py b/bit_manipulation/binary_xor_operator.py index 6f8962192..6206c70a9 100644 --- a/bit_manipulation/binary_xor_operator.py +++ b/bit_manipulation/binary_xor_operator.py @@ -22,7 +22,7 @@ def binary_xor(a: int, b: int) -> str: >>> binary_xor(0, -1) Traceback (most recent call last): ... - ValueError: the value of both input must be positive + ValueError: the value of both inputs must be positive >>> binary_xor(0, 1.1) Traceback (most recent call last): ... @@ -33,7 +33,7 @@ def binary_xor(a: int, b: int) -> str: TypeError: '<' not supported between instances of 'str' and 'int' """ if a < 0 or b < 0: - raise ValueError("the value of both input must be positive") + raise ValueError("the value of both inputs must be positive") a_binary = str(bin(a))[2:] # remove the leading "0b" b_binary = str(bin(b))[2:] # remove the leading "0b" diff --git a/sorts/bead_sort.py b/sorts/bead_sort.py index 26a3fabc4..d22367c52 100644 --- a/sorts/bead_sort.py +++ b/sorts/bead_sort.py @@ -21,15 +21,15 @@ def bead_sort(sequence: list) -> list: >>> bead_sort([1, .9, 0.0, 0, -1, -.9]) Traceback (most recent call last): ... - TypeError: Sequence must be list of nonnegative integers + TypeError: Sequence must be list of non-negative integers >>> bead_sort("Hello world") Traceback (most recent call last): ... - TypeError: Sequence must be list of nonnegative integers + TypeError: Sequence must be list of non-negative integers """ if any(not isinstance(x, int) or x < 0 for x in sequence): - raise TypeError("Sequence must be list of nonnegative integers") + raise TypeError("Sequence must be list of non-negative integers") for _ in range(len(sequence)): for i, (rod_upper, rod_lower) in enumerate(zip(sequence, sequence[1:])): if rod_upper > rod_lower: diff --git a/sorts/double_sort.py b/sorts/double_sort.py index 04e186820..4e08e27b3 100644 --- a/sorts/double_sort.py +++ b/sorts/double_sort.py @@ -1,7 +1,7 @@ def double_sort(lst): - """this sorting algorithm sorts an array using the principle of bubble sort, - but does it both from left to right and right to left, - hence i decided to call it "double sort" + """This sorting algorithm sorts an array using the principle of bubble sort, + but does it both from left to right and right to left. + Hence, it's called "Double sort" :param collection: mutable ordered sequence of elements :return: the same collection in ascending order Examples: From 672a0c8816fcebd8e426d64c0053cef4c42d7ec6 Mon Sep 17 00:00:00 2001 From: Hithru De Alwis Date: Wed, 20 Oct 2021 19:04:31 +0530 Subject: [PATCH 090/726] Fixed Typo (#5477) Change how many "=" sign to how many "=" signs --- ciphers/base64_encoding.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ciphers/base64_encoding.py b/ciphers/base64_encoding.py index 634afcb89..38a952acc 100644 --- a/ciphers/base64_encoding.py +++ b/ciphers/base64_encoding.py @@ -7,7 +7,7 @@ def base64_encode(data: bytes) -> bytes: The data is first transformed to binary and appended with binary digits so that its length becomes a multiple of 6, then each 6 binary digits will match a character in the B64_CHARSET string. The number of appended binary digits would later determine - how many "=" sign should be added, the padding. + how many "=" signs should be added, the padding. For every 2 binary digits added, a "=" sign is added in the output. We can add any binary digits to make it a multiple of 6, for instance, consider the following example: From 2e955aea460d6ac173d5bfeab0c71db0658e2bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjam=C3=ADn=20Garc=C3=ADa=20Roqu=C3=A9s?= <62822419+grbenjamin@users.noreply.github.com> Date: Thu, 21 Oct 2021 00:38:04 -0300 Subject: [PATCH 091/726] Replace double_ended_queue.py (#5429) * Add deque_from_scratch.py * added deque_from_scratch.py * add extend, extendleft and make comparison * updated operations list * fix doctest on Deque.__iter__ * pre-commit fix * time complexity comments, change type hints * pre-commit fix * added more doctests --- data_structures/queue/double_ended_queue.py | 495 ++++++++++++++++++-- 1 file changed, 454 insertions(+), 41 deletions(-) diff --git a/data_structures/queue/double_ended_queue.py b/data_structures/queue/double_ended_queue.py index dd003b7c9..36106d8bc 100644 --- a/data_structures/queue/double_ended_queue.py +++ b/data_structures/queue/double_ended_queue.py @@ -1,57 +1,470 @@ -# Python code to demonstrate working of -# extend(), extendleft(), rotate(), reverse() +""" +Implementation of double ended queue. +""" +from dataclasses import dataclass +from typing import Any, Iterable -# importing "collections" for deque operations -import collections -# initializing deque -de = collections.deque([1, 2, 3]) +class Deque: + """ + Deque data structure. -# using extend() to add numbers to right end -# adds 4,5,6 to right end -de.extend([4, 5, 6]) + Operations + ---------- + append(val: Any) -> None -# printing modified deque -print("The deque after extending deque at end is : ") -print(de) + appendleft(val: Any) -> None -# using extendleft() to add numbers to left end -# adds 7,8,9 to right end -de.extendleft([7, 8, 9]) + extend(iter: Iterable) -> None -# printing modified deque -print("The deque after extending deque at beginning is : ") -print(de) + extendleft(iter: Iterable) -> None -# using rotate() to rotate the deque -# rotates by 3 to left -de.rotate(-3) + pop() -> Any -# printing modified deque -print("The deque after rotating deque is : ") -print(de) + popleft() -> Any -# using reverse() to reverse the deque -de.reverse() -# printing modified deque -print("The deque after reversing deque is : ") -print(de) + Observers + --------- + is_empty() -> bool -# get right-end value and eliminate -startValue = de.pop() -print("The deque after popping value at end is : ") -print(de) + Attributes + ---------- + _front: _Node + front of the deque a.k.a. the first element -# get left-end value and eliminate -endValue = de.popleft() + _back: _Node + back of the element a.k.a. the last element -print("The deque after popping value at start is : ") -print(de) + _len: int + the number of nodes + """ -# eliminate element searched by value -de.remove(5) + __slots__ = ["_front", "_back", "_len"] -print("The deque after eliminating element searched by value : ") -print(de) + @dataclass + class _Node: + """ + Representation of a node. + Contains a value and a pointer to the next node as well as to the previous one. + """ + + val: Any = None + next: "Deque._Node" = None + prev: "Deque._Node" = None + + class _Iterator: + """ + Helper class for iteration. Will be used to implement iteration. + + Attributes + ---------- + _cur: _Node + the current node of the iteration. + """ + + __slots__ = ["_cur"] + + def __init__(self, cur: "Deque._Node") -> None: + self._cur = cur + + def __iter__(self) -> "Deque._Iterator": + """ + >>> our_deque = Deque([1, 2, 3]) + >>> iterator = iter(our_deque) + """ + return self + + def __next__(self) -> Any: + """ + >>> our_deque = Deque([1, 2, 3]) + >>> iterator = iter(our_deque) + >>> next(iterator) + 1 + >>> next(iterator) + 2 + >>> next(iterator) + 3 + """ + if self._cur is None: + # finished iterating + raise StopIteration + val = self._cur.val + self._cur = self._cur.next + + return val + + def __init__(self, iterable: Iterable = None) -> None: + self._front = self._back = None + self._len = 0 + + if iterable is not None: + # append every value to the deque + for val in iterable: + self.append(val) + + def append(self, val: Any) -> None: + """ + Adds val to the end of the deque. + Time complexity: O(1) + + >>> our_deque_1 = Deque([1, 2, 3]) + >>> our_deque_1.append(4) + >>> our_deque_1 + [1, 2, 3, 4] + >>> our_deque_2 = Deque('ab') + >>> our_deque_2.append('c') + >>> our_deque_2 + ['a', 'b', 'c'] + + >>> from collections import deque + >>> deque_collections_1 = deque([1, 2, 3]) + >>> deque_collections_1.append(4) + >>> deque_collections_1 + deque([1, 2, 3, 4]) + >>> deque_collections_2 = deque('ab') + >>> deque_collections_2.append('c') + >>> deque_collections_2 + deque(['a', 'b', 'c']) + + >>> list(our_deque_1) == list(deque_collections_1) + True + >>> list(our_deque_2) == list(deque_collections_2) + True + """ + node = self._Node(val, None, None) + if self.is_empty(): + # front = back + self._front = self._back = node + self._len = 1 + else: + # connect nodes + self._back.next = node + node.prev = self._back + self._back = node # assign new back to the new node + + self._len += 1 + + # make sure there were no errors + assert not self.is_empty(), "Error on appending value." + + def appendleft(self, val: Any) -> None: + """ + Adds val to the beginning of the deque. + Time complexity: O(1) + + >>> our_deque_1 = Deque([2, 3]) + >>> our_deque_1.appendleft(1) + >>> our_deque_1 + [1, 2, 3] + >>> our_deque_2 = Deque('bc') + >>> our_deque_2.appendleft('a') + >>> our_deque_2 + ['a', 'b', 'c'] + + >>> from collections import deque + >>> deque_collections_1 = deque([2, 3]) + >>> deque_collections_1.appendleft(1) + >>> deque_collections_1 + deque([1, 2, 3]) + >>> deque_collections_2 = deque('bc') + >>> deque_collections_2.appendleft('a') + >>> deque_collections_2 + deque(['a', 'b', 'c']) + + >>> list(our_deque_1) == list(deque_collections_1) + True + >>> list(our_deque_2) == list(deque_collections_2) + True + """ + node = self._Node(val, None, None) + if self.is_empty(): + # front = back + self._front = self._back = node + self._len = 1 + else: + # connect nodes + node.next = self._front + self._front.prev = node + self._front = node # assign new front to the new node + + self._len += 1 + + # make sure there were no errors + assert not self.is_empty(), "Error on appending value." + + def extend(self, iter: Iterable) -> None: + """ + Appends every value of iter to the end of the deque. + Time complexity: O(n) + + >>> our_deque_1 = Deque([1, 2, 3]) + >>> our_deque_1.extend([4, 5]) + >>> our_deque_1 + [1, 2, 3, 4, 5] + >>> our_deque_2 = Deque('ab') + >>> our_deque_2.extend('cd') + >>> our_deque_2 + ['a', 'b', 'c', 'd'] + + >>> from collections import deque + >>> deque_collections_1 = deque([1, 2, 3]) + >>> deque_collections_1.extend([4, 5]) + >>> deque_collections_1 + deque([1, 2, 3, 4, 5]) + >>> deque_collections_2 = deque('ab') + >>> deque_collections_2.extend('cd') + >>> deque_collections_2 + deque(['a', 'b', 'c', 'd']) + + >>> list(our_deque_1) == list(deque_collections_1) + True + >>> list(our_deque_2) == list(deque_collections_2) + True + """ + for val in iter: + self.append(val) + + def extendleft(self, iter: Iterable) -> None: + """ + Appends every value of iter to the beginning of the deque. + Time complexity: O(n) + + >>> our_deque_1 = Deque([1, 2, 3]) + >>> our_deque_1.extendleft([0, -1]) + >>> our_deque_1 + [-1, 0, 1, 2, 3] + >>> our_deque_2 = Deque('cd') + >>> our_deque_2.extendleft('ba') + >>> our_deque_2 + ['a', 'b', 'c', 'd'] + + >>> from collections import deque + >>> deque_collections_1 = deque([1, 2, 3]) + >>> deque_collections_1.extendleft([0, -1]) + >>> deque_collections_1 + deque([-1, 0, 1, 2, 3]) + >>> deque_collections_2 = deque('cd') + >>> deque_collections_2.extendleft('ba') + >>> deque_collections_2 + deque(['a', 'b', 'c', 'd']) + + >>> list(our_deque_1) == list(deque_collections_1) + True + >>> list(our_deque_2) == list(deque_collections_2) + True + """ + for val in iter: + self.appendleft(val) + + def pop(self) -> Any: + """ + Removes the last element of the deque and returns it. + Time complexity: O(1) + + @returns topop.val: the value of the node to pop. + + >>> our_deque = Deque([1, 2, 3, 15182]) + >>> our_popped = our_deque.pop() + >>> our_popped + 15182 + >>> our_deque + [1, 2, 3] + + >>> from collections import deque + >>> deque_collections = deque([1, 2, 3, 15182]) + >>> collections_popped = deque_collections.pop() + >>> collections_popped + 15182 + >>> deque_collections + deque([1, 2, 3]) + + >>> list(our_deque) == list(deque_collections) + True + >>> our_popped == collections_popped + True + """ + # make sure the deque has elements to pop + assert not self.is_empty(), "Deque is empty." + + topop = self._back + self._back = self._back.prev # set new back + self._back.next = ( + None # drop the last node - python will deallocate memory automatically + ) + + self._len -= 1 + + return topop.val + + def popleft(self) -> Any: + """ + Removes the first element of the deque and returns it. + Time complexity: O(1) + + @returns topop.val: the value of the node to pop. + + >>> our_deque = Deque([15182, 1, 2, 3]) + >>> our_popped = our_deque.popleft() + >>> our_popped + 15182 + >>> our_deque + [1, 2, 3] + + >>> from collections import deque + >>> deque_collections = deque([15182, 1, 2, 3]) + >>> collections_popped = deque_collections.popleft() + >>> collections_popped + 15182 + >>> deque_collections + deque([1, 2, 3]) + + >>> list(our_deque) == list(deque_collections) + True + >>> our_popped == collections_popped + True + """ + # make sure the deque has elements to pop + assert not self.is_empty(), "Deque is empty." + + topop = self._front + self._front = self._front.next # set new front and drop the first node + self._front.prev = None + + self._len -= 1 + + return topop.val + + def is_empty(self) -> bool: + """ + Checks if the deque is empty. + Time complexity: O(1) + + >>> our_deque = Deque([1, 2, 3]) + >>> our_deque.is_empty() + False + >>> our_empty_deque = Deque() + >>> our_empty_deque.is_empty() + True + + >>> from collections import deque + >>> empty_deque_collections = deque() + >>> list(our_empty_deque) == list(empty_deque_collections) + True + """ + return self._front is None + + def __len__(self) -> int: + """ + Implements len() function. Returns the length of the deque. + Time complexity: O(1) + + >>> our_deque = Deque([1, 2, 3]) + >>> len(our_deque) + 3 + >>> our_empty_deque = Deque() + >>> len(our_empty_deque) + 0 + + >>> from collections import deque + >>> deque_collections = deque([1, 2, 3]) + >>> len(deque_collections) + 3 + >>> empty_deque_collections = deque() + >>> len(empty_deque_collections) + 0 + >>> len(our_empty_deque) == len(empty_deque_collections) + True + """ + return self._len + + def __eq__(self, other: "Deque") -> bool: + """ + Implements "==" operator. Returns if *self* is equal to *other*. + Time complexity: O(n) + + >>> our_deque_1 = Deque([1, 2, 3]) + >>> our_deque_2 = Deque([1, 2, 3]) + >>> our_deque_1 == our_deque_2 + True + >>> our_deque_3 = Deque([1, 2]) + >>> our_deque_1 == our_deque_3 + False + + >>> from collections import deque + >>> deque_collections_1 = deque([1, 2, 3]) + >>> deque_collections_2 = deque([1, 2, 3]) + >>> deque_collections_1 == deque_collections_2 + True + >>> deque_collections_3 = deque([1, 2]) + >>> deque_collections_1 == deque_collections_3 + False + + >>> (our_deque_1 == our_deque_2) == (deque_collections_1 == deque_collections_2) + True + >>> (our_deque_1 == our_deque_3) == (deque_collections_1 == deque_collections_3) + True + """ + me = self._front + oth = other._front + + # if the length of the deques are not the same, they are not equal + if len(self) != len(other): + return False + + while me is not None and oth is not None: + # compare every value + if me.val != oth.val: + return False + me = me.next + oth = oth.next + + return True + + def __iter__(self) -> "_Iterator": + """ + Implements iteration. + Time complexity: O(1) + + >>> our_deque = Deque([1, 2, 3]) + >>> for v in our_deque: + ... print(v) + 1 + 2 + 3 + + >>> from collections import deque + >>> deque_collections = deque([1, 2, 3]) + >>> for v in deque_collections: + ... print(v) + 1 + 2 + 3 + """ + return Deque._Iterator(self._front) + + def __repr__(self) -> str: + """ + Implements representation of the deque. + Represents it as a list, with its values between '[' and ']'. + Time complexity: O(n) + + >>> our_deque = Deque([1, 2, 3]) + >>> our_deque + [1, 2, 3] + """ + values_list = [] + aux = self._front + while aux is not None: + # append the values in a list to display + values_list.append(aux.val) + aux = aux.next + + return "[" + ", ".join(repr(val) for val in values_list) + "]" + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From c0acfd46cbd6b29847d9e0e226431ab6004b8e9b Mon Sep 17 00:00:00 2001 From: John Law Date: Thu, 21 Oct 2021 15:06:32 +0800 Subject: [PATCH 092/726] Fix factorial issues (#5496) * updating DIRECTORY.md * pass integer to `math.factorial` in `project_euler/problem_015` * remove duplicated factorial function * updating DIRECTORY.md * Update maths/factorial_iterative.py Co-authored-by: Christian Clauss * Update factorial_iterative.py Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss --- DIRECTORY.md | 4 +++- maths/factorial_iterative.py | 23 ++++++++++++++++----- maths/factorial_python.py | 34 ------------------------------- project_euler/problem_015/sol1.py | 2 +- 4 files changed, 22 insertions(+), 41 deletions(-) delete mode 100644 maths/factorial_python.py diff --git a/DIRECTORY.md b/DIRECTORY.md index e3b40530a..10149eac5 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -75,6 +75,7 @@ * [Morse Code](https://github.com/TheAlgorithms/Python/blob/master/ciphers/morse_code.py) * [Onepad Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/onepad_cipher.py) * [Playfair Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/playfair_cipher.py) + * [Polybius](https://github.com/TheAlgorithms/Python/blob/master/ciphers/polybius.py) * [Porta Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/porta_cipher.py) * [Rabin Miller](https://github.com/TheAlgorithms/Python/blob/master/ciphers/rabin_miller.py) * [Rail Fence Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/rail_fence_cipher.py) @@ -453,7 +454,6 @@ * [Eulers Totient](https://github.com/TheAlgorithms/Python/blob/master/maths/eulers_totient.py) * [Extended Euclidean Algorithm](https://github.com/TheAlgorithms/Python/blob/master/maths/extended_euclidean_algorithm.py) * [Factorial Iterative](https://github.com/TheAlgorithms/Python/blob/master/maths/factorial_iterative.py) - * [Factorial Python](https://github.com/TheAlgorithms/Python/blob/master/maths/factorial_python.py) * [Factorial Recursive](https://github.com/TheAlgorithms/Python/blob/master/maths/factorial_recursive.py) * [Factors](https://github.com/TheAlgorithms/Python/blob/master/maths/factors.py) * [Fermat Little Theorem](https://github.com/TheAlgorithms/Python/blob/master/maths/fermat_little_theorem.py) @@ -565,6 +565,7 @@ ## Other * [Activity Selection](https://github.com/TheAlgorithms/Python/blob/master/other/activity_selection.py) + * [Check Strong Password](https://github.com/TheAlgorithms/Python/blob/master/other/check_strong_password.py) * [Date To Weekday](https://github.com/TheAlgorithms/Python/blob/master/other/date_to_weekday.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) @@ -952,6 +953,7 @@ * [Reverse Words](https://github.com/TheAlgorithms/Python/blob/master/strings/reverse_words.py) * [Split](https://github.com/TheAlgorithms/Python/blob/master/strings/split.py) * [Upper](https://github.com/TheAlgorithms/Python/blob/master/strings/upper.py) + * [Wildcard Pattern Matching](https://github.com/TheAlgorithms/Python/blob/master/strings/wildcard_pattern_matching.py) * [Word Occurrence](https://github.com/TheAlgorithms/Python/blob/master/strings/word_occurrence.py) * [Word Patterns](https://github.com/TheAlgorithms/Python/blob/master/strings/word_patterns.py) * [Z Function](https://github.com/TheAlgorithms/Python/blob/master/strings/z_function.py) diff --git a/maths/factorial_iterative.py b/maths/factorial_iterative.py index 64314790c..c6cf7de57 100644 --- a/maths/factorial_iterative.py +++ b/maths/factorial_iterative.py @@ -1,8 +1,11 @@ -# factorial of a positive integer -- https://en.wikipedia.org/wiki/Factorial +"""Factorial of a positive integer -- https://en.wikipedia.org/wiki/Factorial +""" -def factorial(n: int) -> int: +def factorial(number: int) -> int: """ + Calculate the factorial of specified number (n!). + >>> import math >>> all(factorial(i) == math.factorial(i) for i in range(20)) True @@ -14,17 +17,27 @@ def factorial(n: int) -> int: Traceback (most recent call last): ... ValueError: factorial() not defined for negative values + >>> factorial(1) + 1 + >>> factorial(6) + 720 + >>> factorial(0) + 1 """ - if n != int(n): + if number != int(number): raise ValueError("factorial() only accepts integral values") - if n < 0: + if number < 0: raise ValueError("factorial() not defined for negative values") value = 1 - for i in range(1, n + 1): + for i in range(1, number + 1): value *= i return value if __name__ == "__main__": + import doctest + + doctest.testmod() + n = int(input("Enter a positive integer: ").strip() or 0) print(f"factorial{n} is {factorial(n)}") diff --git a/maths/factorial_python.py b/maths/factorial_python.py deleted file mode 100644 index 46688261a..000000000 --- a/maths/factorial_python.py +++ /dev/null @@ -1,34 +0,0 @@ -def factorial(input_number: int) -> int: - """ - Calculate the factorial of specified number - - >>> factorial(1) - 1 - >>> factorial(6) - 720 - >>> factorial(0) - 1 - >>> factorial(-1) - Traceback (most recent call last): - ... - ValueError: factorial() not defined for negative values - >>> factorial(0.1) - Traceback (most recent call last): - ... - ValueError: factorial() only accepts integral values - """ - - if input_number < 0: - raise ValueError("factorial() not defined for negative values") - if not isinstance(input_number, int): - raise ValueError("factorial() only accepts integral values") - result = 1 - for i in range(1, input_number): - result = result * (i + 1) - return result - - -if __name__ == "__main__": - import doctest - - doctest.testmod() diff --git a/project_euler/problem_015/sol1.py b/project_euler/problem_015/sol1.py index da079d261..fb2020d61 100644 --- a/project_euler/problem_015/sol1.py +++ b/project_euler/problem_015/sol1.py @@ -26,7 +26,7 @@ def solution(n: int = 20) -> int: """ n = 2 * n # middle entry of odd rows starting at row 3 is the solution for n = 1, # 2, 3,... - k = n / 2 + k = n // 2 return int(factorial(n) / (factorial(k) * factorial(n - k))) From fdf095f69f428b161e939b18971812285608495a Mon Sep 17 00:00:00 2001 From: poloso Date: Thu, 21 Oct 2021 08:13:42 -0500 Subject: [PATCH 093/726] [mypy] check polygon and corrections (#5419) * Update annotations to Python 3.10 #4052 * Add floats doctest * Copy list to avoid changing input unpredictably * Refactor code to make it readable * updating DIRECTORY.md * Improve raised ValueErrors and add doctest * Split doctest in multiples lines * Change ValueError to Monogons and Digons are not poly * Correct doctest refering number of sides Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- maths/check_polygon.py | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/maths/check_polygon.py b/maths/check_polygon.py index 0e7711973..1e8dce718 100644 --- a/maths/check_polygon.py +++ b/maths/check_polygon.py @@ -1,7 +1,7 @@ -from typing import List +from __future__ import annotations -def check_polygon(nums: List) -> bool: +def check_polygon(nums: list[float]) -> bool: """ Takes list of possible side lengths and determines whether a two-dimensional polygon with such side lengths can exist. @@ -14,15 +14,28 @@ def check_polygon(nums: List) -> bool: True >>> check_polygon([3, 7, 13, 2]) False + >>> check_polygon([1, 4.3, 5.2, 12.2]) + False + >>> nums = [3, 7, 13, 2] + >>> _ = check_polygon(nums) # Run function, do not show answer in output + >>> nums # Check numbers are not reordered + [3, 7, 13, 2] >>> check_polygon([]) Traceback (most recent call last): ... - ValueError: List is invalid + ValueError: Monogons and Digons are not polygons in the Euclidean space + >>> check_polygon([-2, 5, 6]) + Traceback (most recent call last): + ... + ValueError: All values must be greater than 0 """ - if not nums: - raise ValueError("List is invalid") - nums.sort() - return nums.pop() < sum(nums) + if len(nums) < 2: + raise ValueError("Monogons and Digons are not polygons in the Euclidean space") + if any(i <= 0 for i in nums): + raise ValueError("All values must be greater than 0") + copy_nums = nums.copy() + copy_nums.sort() + return copy_nums[-1] < sum(copy_nums[:-1]) if __name__ == "__main__": From 9153db2d275086bb951b696b3a4628c76a14ac90 Mon Sep 17 00:00:00 2001 From: Sherman Hui <11592023+shermanhui@users.noreply.github.com> Date: Thu, 21 Oct 2021 20:39:18 -0700 Subject: [PATCH 094/726] [mypy] fix: fix mypy error in singly_linked_list.py (#5517) The list comprehension shortcut was implicitly expecting a return value causing a mypy error since `insert_tail` doesn't return a value --- data_structures/linked_list/singly_linked_list.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/data_structures/linked_list/singly_linked_list.py b/data_structures/linked_list/singly_linked_list.py index 4a5dc8263..a4156b650 100644 --- a/data_structures/linked_list/singly_linked_list.py +++ b/data_structures/linked_list/singly_linked_list.py @@ -409,7 +409,9 @@ def test_singly_linked_list_2() -> None: 12.20, ] linked_list = LinkedList() - [linked_list.insert_tail(i) for i in input] + + for i in input: + linked_list.insert_tail(i) # Check if it's empty or not assert linked_list.is_empty() is False From b373c991f69e20d7e1dc92d1613e60a5605bf1a8 Mon Sep 17 00:00:00 2001 From: Sherman Hui <11592023+shermanhui@users.noreply.github.com> Date: Thu, 21 Oct 2021 20:40:17 -0700 Subject: [PATCH 095/726] [mypy] fix: fix mypy error in trie.py(#5516) --- data_structures/trie/trie.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/trie/trie.py b/data_structures/trie/trie.py index 6582be24f..766294c23 100644 --- a/data_structures/trie/trie.py +++ b/data_structures/trie/trie.py @@ -11,7 +11,7 @@ class TrieNode: self.nodes = dict() # Mapping from char to TrieNode self.is_leaf = False - def insert_many(self, words: [str]): + def insert_many(self, words: list[str]): """ Inserts a list of words into the Trie :param words: list of string words From 57a7e5738b8224f58941019964da67ece679eab9 Mon Sep 17 00:00:00 2001 From: Jenny Vo <40080855+ovynnej@users.noreply.github.com> Date: Fri, 22 Oct 2021 04:52:39 +0100 Subject: [PATCH 096/726] Add implementation of Coulomb's Law (#4897) --- electronics/coulombs_law.py | 86 +++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 electronics/coulombs_law.py diff --git a/electronics/coulombs_law.py b/electronics/coulombs_law.py new file mode 100644 index 000000000..e4c8391c9 --- /dev/null +++ b/electronics/coulombs_law.py @@ -0,0 +1,86 @@ +# https://en.wikipedia.org/wiki/Coulomb%27s_law + +from __future__ import annotations + +COULOMBS_CONSTANT = 8.988e9 # units = N * m^s * C^-2 + + +def couloumbs_law( + force: float, charge1: float, charge2: float, distance: float +) -> dict[str, float]: + + """ + Apply Coulomb's Law on any three given values. These can be force, charge1, + charge2, or distance, and then in a Python dict return name/value pair of + the zero value. + + Coulomb's Law states that the magnitude of the electrostatic force of + attraction or repulsion between two point charges is directly proportional + to the product of the magnitudes of charges and inversely proportional to + the square of the distance between them. + + Reference + ---------- + Coulomb (1785) "Premier mémoire sur l’électricité et le magnétisme," + Histoire de l’Académie Royale des Sciences, pp. 569–577. + + Parameters + ---------- + force : float with units in Newtons + + charge1 : float with units in Coulombs + + charge2 : float with units in Coulombs + + distance : float with units in meters + + Returns + ------- + result : dict name/value pair of the zero value + + >>> couloumbs_law(force=0, charge1=3, charge2=5, distance=2000) + {'force': 33705.0} + + >>> couloumbs_law(force=10, charge1=3, charge2=5, distance=0) + {'distance': 116112.01488218177} + + >>> couloumbs_law(force=10, charge1=0, charge2=5, distance=2000) + {'charge1': 0.0008900756564307966} + + >>> couloumbs_law(force=0, charge1=0, charge2=5, distance=2000) + Traceback (most recent call last): + ... + ValueError: One and only one argument must be 0 + + >>> couloumbs_law(force=0, charge1=3, charge2=5, distance=-2000) + Traceback (most recent call last): + ... + ValueError: Distance cannot be negative + + """ + + charge_product = abs(charge1 * charge2) + + if (force, charge1, charge2, distance).count(0) != 1: + raise ValueError("One and only one argument must be 0") + if distance < 0: + raise ValueError("Distance cannot be negative") + if force == 0: + force = COULOMBS_CONSTANT * charge_product / (distance ** 2) + return {"force": force} + elif charge1 == 0: + charge1 = abs(force) * (distance ** 2) / (COULOMBS_CONSTANT * charge2) + return {"charge1": charge1} + elif charge2 == 0: + charge2 = abs(force) * (distance ** 2) / (COULOMBS_CONSTANT * charge1) + return {"charge2": charge2} + elif distance == 0: + distance = (COULOMBS_CONSTANT * charge_product / abs(force)) ** 0.5 + return {"distance": distance} + raise ValueError("Exactly one argument must be 0") + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 83a63d9c22cb0003c4e279cf5e22a2f07b83d652 Mon Sep 17 00:00:00 2001 From: Erwin Junge Date: Fri, 22 Oct 2021 06:14:45 +0200 Subject: [PATCH 097/726] [mypy] Add missing type annotation in conways_game_of_life.py (#5490) --- cellular_automata/conways_game_of_life.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cellular_automata/conways_game_of_life.py b/cellular_automata/conways_game_of_life.py index 079fb4d04..84f4d5be4 100644 --- a/cellular_automata/conways_game_of_life.py +++ b/cellular_automata/conways_game_of_life.py @@ -70,7 +70,7 @@ def new_generation(cells: list[list[int]]) -> list[list[int]]: return next_generation -def generate_images(cells: list[list[int]], frames) -> list[Image.Image]: +def generate_images(cells: list[list[int]], frames: int) -> list[Image.Image]: """ Generates a list of images of subsequent Game of Life states. """ From 08254eb2e4da3fba23d019f39f7f22a05532cd0e Mon Sep 17 00:00:00 2001 From: Erwin Junge Date: Fri, 22 Oct 2021 11:45:19 +0200 Subject: [PATCH 098/726] [mypy] Fix type annotations for boolean_algebra/quine_mc_cluskey.py (#5489) * Add missing type annotation * Fix conversion bug This failed when called with the documented example of `1.5` and was correctly pointed out by `mypy --strict` --- boolean_algebra/quine_mc_cluskey.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boolean_algebra/quine_mc_cluskey.py b/boolean_algebra/quine_mc_cluskey.py index 9cc99b1ee..0342e5c67 100644 --- a/boolean_algebra/quine_mc_cluskey.py +++ b/boolean_algebra/quine_mc_cluskey.py @@ -146,10 +146,10 @@ def prime_implicant_chart( return chart -def main(): +def main() -> None: no_of_variable = int(input("Enter the no. of variables\n")) minterms = [ - int(x) + float(x) for x in input( "Enter the decimal representation of Minterms 'Spaces Separated'\n" ).split() From d924a8051bfe0fe8de164e5074eb4f5f8fa6afb3 Mon Sep 17 00:00:00 2001 From: Erwin Junge Date: Fri, 22 Oct 2021 11:45:30 +0200 Subject: [PATCH 099/726] [mypy] Add missing type annotation (#5491) --- cellular_automata/game_of_life.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/cellular_automata/game_of_life.py b/cellular_automata/game_of_life.py index 09863993d..c5324da73 100644 --- a/cellular_automata/game_of_life.py +++ b/cellular_automata/game_of_life.py @@ -40,18 +40,18 @@ choice = [0] * 100 + [1] * 10 random.shuffle(choice) -def create_canvas(size): +def create_canvas(size: int) -> list[list[bool]]: canvas = [[False for i in range(size)] for j in range(size)] return canvas -def seed(canvas): +def seed(canvas: list[list[bool]]) -> None: for i, row in enumerate(canvas): for j, _ in enumerate(row): canvas[i][j] = bool(random.getrandbits(1)) -def run(canvas): +def run(canvas: list[list[bool]]) -> list[list[bool]]: """This function runs the rules of game through all points, and changes their status accordingly.(in the same canvas) @Args: @@ -62,21 +62,22 @@ def run(canvas): -- None """ - canvas = np.array(canvas) - next_gen_canvas = np.array(create_canvas(canvas.shape[0])) - for r, row in enumerate(canvas): + current_canvas = np.array(canvas) + next_gen_canvas = np.array(create_canvas(current_canvas.shape[0])) + for r, row in enumerate(current_canvas): for c, pt in enumerate(row): # print(r-1,r+2,c-1,c+2) next_gen_canvas[r][c] = __judge_point( - pt, canvas[r - 1 : r + 2, c - 1 : c + 2] + pt, current_canvas[r - 1 : r + 2, c - 1 : c + 2] ) - canvas = next_gen_canvas + current_canvas = next_gen_canvas del next_gen_canvas # cleaning memory as we move on. - return canvas.tolist() + return_canvas: list[list[bool]] = current_canvas.tolist() + return return_canvas -def __judge_point(pt, neighbours): +def __judge_point(pt: bool, neighbours: list[list[bool]]) -> bool: dead = 0 alive = 0 # finding dead or alive neighbours count. From 061614880d0c4e1b3483665b1b82cc124932ff51 Mon Sep 17 00:00:00 2001 From: poloso Date: Fri, 22 Oct 2021 05:07:28 -0500 Subject: [PATCH 100/726] [mypy] fix type annotations for graphs/a_star.py #4052 (#5224) * [mypy] fix type annotations for graphs/a_star.py #4052 * updating DIRECTORY.md * Add from __future__ import anotations * rename delta by DIRECTIONS Co-authored-by: John Law * Rename delta by DIRECTIONS in all code * Enclose script in __main__ code block * Refactor DIRECTIONS with comments for readibility * Delete heuristic example comment * Do not print, return all values * Fix multilines * fix black * Update a_star.py Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: John Law --- graphs/a_star.py | 92 ++++++++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 42 deletions(-) diff --git a/graphs/a_star.py b/graphs/a_star.py index d3657cb19..e0f24734a 100644 --- a/graphs/a_star.py +++ b/graphs/a_star.py @@ -1,37 +1,21 @@ -grid = [ - [0, 1, 0, 0, 0, 0], - [0, 1, 0, 0, 0, 0], # 0 are free path whereas 1's are obstacles - [0, 1, 0, 0, 0, 0], - [0, 1, 0, 0, 1, 0], - [0, 0, 0, 0, 1, 0], +from __future__ import annotations + +DIRECTIONS = [ + [-1, 0], # left + [0, -1], # down + [1, 0], # right + [0, 1], # up ] -""" -heuristic = [[9, 8, 7, 6, 5, 4], - [8, 7, 6, 5, 4, 3], - [7, 6, 5, 4, 3, 2], - [6, 5, 4, 3, 2, 1], - [5, 4, 3, 2, 1, 0]]""" - -init = [0, 0] -goal = [len(grid) - 1, len(grid[0]) - 1] # all coordinates are given in format [y,x] -cost = 1 - -# the cost map which pushes the path closer to the goal -heuristic = [[0 for row in range(len(grid[0]))] for col in range(len(grid))] -for i in range(len(grid)): - for j in range(len(grid[0])): - heuristic[i][j] = abs(i - goal[0]) + abs(j - goal[1]) - if grid[i][j] == 1: - heuristic[i][j] = 99 # added extra penalty in the heuristic map - - -# the actions we can take -delta = [[-1, 0], [0, -1], [1, 0], [0, 1]] # go up # go left # go down # go right - # function to search the path -def search(grid, init, goal, cost, heuristic): +def search( + grid: list[list[int]], + init: list[int], + goal: list[int], + cost: int, + heuristic: list[list[int]], +) -> tuple[list[list[int]], list[list[int]]]: closed = [ [0 for col in range(len(grid[0]))] for row in range(len(grid)) @@ -52,7 +36,7 @@ def search(grid, init, goal, cost, heuristic): while not found and not resign: if len(cell) == 0: - return "FAIL" + raise ValueError("Algorithm is unable to find solution") else: # to choose the least costliest action so as to move closer to the goal cell.sort() cell.reverse() @@ -64,9 +48,9 @@ def search(grid, init, goal, cost, heuristic): if x == goal[0] and y == goal[1]: found = True else: - for i in range(len(delta)): # to try out different valid actions - x2 = x + delta[i][0] - y2 = y + delta[i][1] + for i in range(len(DIRECTIONS)): # to try out different valid actions + x2 = x + DIRECTIONS[i][0] + y2 = y + DIRECTIONS[i][1] if x2 >= 0 and x2 < len(grid) and y2 >= 0 and y2 < len(grid[0]): if closed[x2][y2] == 0 and grid[x2][y2] == 0: g2 = g + cost @@ -79,8 +63,8 @@ def search(grid, init, goal, cost, heuristic): y = goal[1] invpath.append([x, y]) # we get the reverse path from here while x != init[0] or y != init[1]: - x2 = x - delta[action[x][y]][0] - y2 = y - delta[action[x][y]][1] + x2 = x - DIRECTIONS[action[x][y]][0] + y2 = y - DIRECTIONS[action[x][y]][1] x = x2 y = y2 invpath.append([x, y]) @@ -88,13 +72,37 @@ def search(grid, init, goal, cost, heuristic): path = [] for i in range(len(invpath)): path.append(invpath[len(invpath) - 1 - i]) + return path, action + + +if __name__ == "__main__": + grid = [ + [0, 1, 0, 0, 0, 0], + [0, 1, 0, 0, 0, 0], # 0 are free path whereas 1's are obstacles + [0, 1, 0, 0, 0, 0], + [0, 1, 0, 0, 1, 0], + [0, 0, 0, 0, 1, 0], + ] + + init = [0, 0] + # all coordinates are given in format [y,x] + goal = [len(grid) - 1, len(grid[0]) - 1] + cost = 1 + + # the cost map which pushes the path closer to the goal + heuristic = [[0 for row in range(len(grid[0]))] for col in range(len(grid))] + for i in range(len(grid)): + for j in range(len(grid[0])): + heuristic[i][j] = abs(i - goal[0]) + abs(j - goal[1]) + if grid[i][j] == 1: + # added extra penalty in the heuristic map + heuristic[i][j] = 99 + + path, action = search(grid, init, goal, cost, heuristic) + print("ACTION MAP") for i in range(len(action)): print(action[i]) - return path - - -a = search(grid, init, goal, cost, heuristic) -for i in range(len(a)): - print(a[i]) + for i in range(len(path)): + print(path[i]) From d82cf5292fbd0ffe1764a1da5c96a39b244618eb Mon Sep 17 00:00:00 2001 From: QuartzAl <55610038+QuartzAl@users.noreply.github.com> Date: Fri, 22 Oct 2021 18:14:35 +0700 Subject: [PATCH 101/726] split into usable functions and added docstrings for base32 cipher (#5466) * split into usable functions and added docstrings * Simplified code Co-authored-by: Christian Clauss * Simplified code Co-authored-by: Christian Clauss Co-authored-by: Christian Clauss --- ciphers/base32.py | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/ciphers/base32.py b/ciphers/base32.py index da289a721..fee53ccaf 100644 --- a/ciphers/base32.py +++ b/ciphers/base32.py @@ -1,13 +1,42 @@ import base64 -def main() -> None: - inp = input("->") - encoded = inp.encode("utf-8") # encoded the input (we need a bytes like object) - b32encoded = base64.b32encode(encoded) # b32encoded the encoded string - print(b32encoded) - print(base64.b32decode(b32encoded).decode("utf-8")) # decoded it +def base32_encode(string: str) -> bytes: + """ + Encodes a given string to base32, returning a bytes-like object + >>> base32_encode("Hello World!") + b'JBSWY3DPEBLW64TMMQQQ====' + >>> base32_encode("123456") + b'GEZDGNBVGY======' + >>> base32_encode("some long complex string") + b'ONXW2ZJANRXW4ZZAMNXW24DMMV4CA43UOJUW4ZY=' + """ + + # encoded the input (we need a bytes like object) + # then, b32encoded the bytes-like object + return base64.b32encode(string.encode("utf-8")) + + +def base32_decode(encoded_bytes: bytes) -> str: + """ + Decodes a given bytes-like object to a string, returning a string + >>> base32_decode(b'JBSWY3DPEBLW64TMMQQQ====') + 'Hello World!' + >>> base32_decode(b'GEZDGNBVGY======') + '123456' + >>> base32_decode(b'ONXW2ZJANRXW4ZZAMNXW24DMMV4CA43UOJUW4ZY=') + 'some long complex string' + """ + + # decode the bytes from base32 + # then, decode the bytes-like object to return as a string + return base64.b32decode(encoded_bytes).decode("utf-8") if __name__ == "__main__": - main() + test = "Hello World!" + encoded = base32_encode(test) + print(encoded) + + decoded = base32_decode(encoded) + print(decoded) From 629848e3721d9354d25fad6cb4729e6afdbbf799 Mon Sep 17 00:00:00 2001 From: Sherman Hui <11592023+shermanhui@users.noreply.github.com> Date: Fri, 22 Oct 2021 07:07:05 -0700 Subject: [PATCH 102/726] [mypy] Fix type annotations in `data_structures/binary_tree` (#5518) * fix: fix mypy errors Update binary_search_tree `arr` argument to be typed as a list within `find_kth_smallest` function Update return type of `merge_two_binary_trees` as both inputs can be None which means that a None type value can be returned from this function * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 1 + data_structures/binary_tree/binary_search_tree.py | 2 +- data_structures/binary_tree/merge_two_binary_trees.py | 4 +++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 10149eac5..950d8e2c0 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -272,6 +272,7 @@ ## Electronics * [Carrier Concentration](https://github.com/TheAlgorithms/Python/blob/master/electronics/carrier_concentration.py) + * [Coulombs Law](https://github.com/TheAlgorithms/Python/blob/master/electronics/coulombs_law.py) * [Electric Power](https://github.com/TheAlgorithms/Python/blob/master/electronics/electric_power.py) * [Ohms Law](https://github.com/TheAlgorithms/Python/blob/master/electronics/ohms_law.py) diff --git a/data_structures/binary_tree/binary_search_tree.py b/data_structures/binary_tree/binary_search_tree.py index a1ed1d0ac..ce490fd98 100644 --- a/data_structures/binary_tree/binary_search_tree.py +++ b/data_structures/binary_tree/binary_search_tree.py @@ -151,7 +151,7 @@ class BinarySearchTree: def find_kth_smallest(self, k: int, node: Node) -> int: """Return the kth smallest element in a binary search tree""" - arr = [] + arr: list = [] self.inorder(arr, node) # append all values to list using inorder traversal return arr[k - 1] diff --git a/data_structures/binary_tree/merge_two_binary_trees.py b/data_structures/binary_tree/merge_two_binary_trees.py index d169e0e75..748726894 100644 --- a/data_structures/binary_tree/merge_two_binary_trees.py +++ b/data_structures/binary_tree/merge_two_binary_trees.py @@ -7,6 +7,8 @@ will be used as the node of new tree. """ from __future__ import annotations +from typing import Optional + class Node: """ @@ -19,7 +21,7 @@ class Node: self.right: Node | None = None -def merge_two_binary_trees(tree1: Node | None, tree2: Node | None) -> Node: +def merge_two_binary_trees(tree1: Node | None, tree2: Node | None) -> Optional[Node]: """ Returns root node of the merged tree. From 0ca12799974aa2d0756aec608d38fea04f1239d7 Mon Sep 17 00:00:00 2001 From: Toki345 <91814435+Toki345@users.noreply.github.com> Date: Fri, 22 Oct 2021 22:07:57 +0800 Subject: [PATCH 103/726] Fixed grammar on Anagram Description (#5512) Made the description more formal, also fixed a few grammatical issues. --- strings/check_anagrams.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/strings/check_anagrams.py b/strings/check_anagrams.py index 3083000cb..62a4441a0 100644 --- a/strings/check_anagrams.py +++ b/strings/check_anagrams.py @@ -5,7 +5,7 @@ wiki: https://en.wikipedia.org/wiki/Anagram def check_anagrams(first_str: str, second_str: str) -> bool: """ - Two strings are anagrams if they are made of the same letters + Two strings are anagrams if they are made up of the same letters but are arranged differently (ignoring the case). >>> check_anagrams('Silent', 'Listen') True From 2ddd81df211332b580887a929367a1d529c56dbe Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj <89947037+Rohanrbharadwaj@users.noreply.github.com> Date: Fri, 22 Oct 2021 22:44:08 +0530 Subject: [PATCH 104/726] Remove wrongly placed double qoutes (#5530) * Update baconian_cipher.py * Update join.py * Updated type hint --- ciphers/baconian_cipher.py | 2 +- strings/join.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ciphers/baconian_cipher.py b/ciphers/baconian_cipher.py index 027fbc50e..f146ba91b 100644 --- a/ciphers/baconian_cipher.py +++ b/ciphers/baconian_cipher.py @@ -83,7 +83,7 @@ def decode(coded: str) -> str: return decoded.strip() -if "__name__" == "__main__": +if __name__ == "__main__": from doctest import testmod testmod() diff --git a/strings/join.py b/strings/join.py index 0cb88b760..c17ddd144 100644 --- a/strings/join.py +++ b/strings/join.py @@ -3,7 +3,7 @@ Program to join a list of strings with a given separator """ -def join(separator: str, separated: list) -> str: +def join(separator: str, separated: list[str]) -> str: """ >>> join("", ["a", "b", "c", "d"]) 'abcd' @@ -26,7 +26,7 @@ def join(separator: str, separated: list) -> str: return joined.strip(separator) -if "__name__" == "__main__": +if __name__ == "__main__": from doctest import testmod testmod() From 07141e4bcce7770300f4cf7c3042bdfc5e3c9934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Murilo=20Gon=C3=A7alves?= <38800183+murilo-goncalves@users.noreply.github.com> Date: Fri, 22 Oct 2021 14:14:27 -0300 Subject: [PATCH 105/726] Add doctests to prime_check function (#5503) * added doctests to prime_check function * fix doctests function name --- maths/prime_check.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/maths/prime_check.py b/maths/prime_check.py index e2bcb7b8f..92d31cfee 100644 --- a/maths/prime_check.py +++ b/maths/prime_check.py @@ -5,9 +5,28 @@ import unittest def prime_check(number: int) -> bool: - """Checks to see if a number is a prime. + """Checks to see if a number is a prime in O(sqrt(n)). A number is prime if it has exactly two factors: 1 and itself. + + >>> prime_check(0) + False + >>> prime_check(1) + False + >>> prime_check(2) + True + >>> prime_check(3) + True + >>> prime_check(27) + False + >>> prime_check(87) + False + >>> prime_check(563) + True + >>> prime_check(2999) + True + >>> prime_check(67483) + False """ if 1 < number < 4: From 11ec2fd3fb472a8bcac738f372e6e0f731326d3b Mon Sep 17 00:00:00 2001 From: Edward Nuno Date: Fri, 22 Oct 2021 10:21:41 -0700 Subject: [PATCH 106/726] [mypy] Fix type annotations for trie.py (#5022) * Fix type annotations for trie.py * Add strict type annotations to trie.py Annotate return type for all functions and type for "nodes" * updating DIRECTORY.md * Format trie.py Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- data_structures/trie/trie.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/data_structures/trie/trie.py b/data_structures/trie/trie.py index 766294c23..162d08d1d 100644 --- a/data_structures/trie/trie.py +++ b/data_structures/trie/trie.py @@ -7,11 +7,11 @@ longest word)) lookup time making it an optimal approach when space is not an is class TrieNode: - def __init__(self): - self.nodes = dict() # Mapping from char to TrieNode + def __init__(self) -> None: + self.nodes: dict[str, TrieNode] = dict() # Mapping from char to TrieNode self.is_leaf = False - def insert_many(self, words: list[str]): + def insert_many(self, words: list[str]) -> None: """ Inserts a list of words into the Trie :param words: list of string words @@ -20,7 +20,7 @@ class TrieNode: for word in words: self.insert(word) - def insert(self, word: str): + def insert(self, word: str) -> None: """ Inserts a word into the Trie :param word: word to be inserted @@ -46,14 +46,14 @@ class TrieNode: curr = curr.nodes[char] return curr.is_leaf - def delete(self, word: str): + def delete(self, word: str) -> None: """ Deletes a word in a Trie :param word: word to delete :return: None """ - def _delete(curr: TrieNode, word: str, index: int): + def _delete(curr: TrieNode, word: str, index: int) -> bool: if index == len(word): # If word does not exist if not curr.is_leaf: @@ -75,7 +75,7 @@ class TrieNode: _delete(self, word, 0) -def print_words(node: TrieNode, word: str): +def print_words(node: TrieNode, word: str) -> None: """ Prints all the words in a Trie :param node: root node of Trie @@ -89,7 +89,7 @@ def print_words(node: TrieNode, word: str): print_words(value, word + key) -def test_trie(): +def test_trie() -> bool: words = "banana bananas bandana band apple all beast".split() root = TrieNode() root.insert_many(words) @@ -112,11 +112,11 @@ def print_results(msg: str, passes: bool) -> None: print(str(msg), "works!" if passes else "doesn't work :(") -def pytests(): +def pytests() -> None: assert test_trie() -def main(): +def main() -> None: """ >>> pytests() """ From 20e09c3ec2021edf7e6cfd85299544c651012919 Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Sat, 23 Oct 2021 06:56:58 -0300 Subject: [PATCH 107/726] [mypy] Add type annotations for linked queue in data structures (#5533) * [mypy] Add/fix type annotations for linked queue in data_structures * add return type annotation to __iter__ * Add more readable syntax --- data_structures/queue/linked_queue.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/data_structures/queue/linked_queue.py b/data_structures/queue/linked_queue.py index 8526ad311..21970e7df 100644 --- a/data_structures/queue/linked_queue.py +++ b/data_structures/queue/linked_queue.py @@ -1,11 +1,13 @@ """ A Queue using a linked list like structure """ -from typing import Any +from __future__ import annotations + +from typing import Any, Iterator class Node: def __init__(self, data: Any) -> None: - self.data = data - self.next = None + self.data: Any = data + self.next: Node | None = None def __str__(self) -> str: return f"{self.data}" @@ -39,9 +41,10 @@ class LinkedQueue: """ def __init__(self) -> None: - self.front = self.rear = None + self.front: Node | None = None + self.rear: Node | None = None - def __iter__(self): + def __iter__(self) -> Iterator[Any]: node = self.front while node: yield node.data @@ -87,7 +90,7 @@ class LinkedQueue: """ return len(self) == 0 - def put(self, item) -> None: + def put(self, item: Any) -> None: """ >>> queue = LinkedQueue() >>> queue.get() From c50f0c56aa23e8ab9ab019bc61f80465da135ef8 Mon Sep 17 00:00:00 2001 From: Atishaye Jain <64211411+atishaye@users.noreply.github.com> Date: Sat, 23 Oct 2021 15:59:42 +0530 Subject: [PATCH 108/726] add check_cycle.py (#5475) * add check_cycle.py * Update graphs/check_cycle.py Co-authored-by: John Law * Update check_cycle.py * Apply suggestions from code review Co-authored-by: John Law Co-authored-by: Christian Clauss --- graphs/check_cycle.py | 55 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 graphs/check_cycle.py diff --git a/graphs/check_cycle.py b/graphs/check_cycle.py new file mode 100644 index 000000000..71d42b468 --- /dev/null +++ b/graphs/check_cycle.py @@ -0,0 +1,55 @@ +""" +Program to check if a cycle is present in a given graph +""" + + +def check_cycle(graph: dict) -> bool: + """ + Returns True if graph is cyclic else False + + >>> check_cycle(graph={0:[], 1:[0, 3], 2:[0, 4], 3:[5], 4:[5], 5:[]}) + False + >>> check_cycle(graph={0:[1, 2], 1:[2], 2:[0, 3], 3:[3]}) + True + """ + # Keep track of visited nodes + visited = set() + # To detect a back edge, keep track of vertices currently in the recursion stack + rec_stk = set() + for node in graph: + if node not in visited: + if depth_first_search(graph, node, visited, rec_stk): + return True + return False + + +def depth_first_search(graph: dict, vertex: int, visited: set, rec_stk: set) -> bool: + """ + Recur for all neighbours. + If any neighbour is visited and in rec_stk then graph is cyclic. + + >>> graph = {0:[], 1:[0, 3], 2:[0, 4], 3:[5], 4:[5], 5:[]} + >>> vertex, visited, rec_stk = 0, set(), set() + >>> depth_first_search(graph, vertex, visited, rec_stk) + False + """ + # Mark current node as visited and add to recursion stack + visited.add(vertex) + rec_stk.add(vertex) + + for node in graph[vertex]: + if node not in visited: + if depth_first_search(graph, node, visited, rec_stk): + return True + elif node in rec_stk: + return True + + # The node needs to be removed from recursion stack before function ends + rec_stk.remove(vertex) + return False + + +if __name__ == "__main__": + from doctest import testmod + + testmod() From 27f2465135dc00abb6ec569b050780e9e62d02f3 Mon Sep 17 00:00:00 2001 From: Jaydeep Das Date: Sat, 23 Oct 2021 16:26:26 +0530 Subject: [PATCH 109/726] Added new file: nasa_data.py (#5543) * Added new file: nasa_data.py * Modified as per review * Minor change * print(get_archive_data("apollo 2011")["collection"]["items"][0]["data"][0]["description"]) * Update nasa_data.py Co-authored-by: Christian Clauss --- web_programming/nasa_data.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 web_programming/nasa_data.py diff --git a/web_programming/nasa_data.py b/web_programming/nasa_data.py new file mode 100644 index 000000000..9b15c38a7 --- /dev/null +++ b/web_programming/nasa_data.py @@ -0,0 +1,27 @@ +import requests + + +def get_apod_data(api_key: str) -> dict: + """ + Get the APOD(Astronomical Picture of the day) data + Get the API Key from : https://api.nasa.gov/ + """ + url = "https://api.nasa.gov/planetary/apod/" + return requests.get(url, params={"api_key": api_key}).json() + + +def get_archive_data(query: str) -> dict: + """ + Get the data of a particular query from NASA archives + """ + endpoint = "https://images-api.nasa.gov/search" + return requests.get(endpoint, params={"q": query}).json() + + +if __name__ == "__main__": + print(get_apod_data("YOUR API KEY")) + print( + get_archive_data("apollo 2011")["collection"]["items"][0]["data"][0][ + "description" + ] + ) From b64fd56776f03342559034df27948269d49c3375 Mon Sep 17 00:00:00 2001 From: Jaydeep Das Date: Sat, 23 Oct 2021 18:08:25 +0530 Subject: [PATCH 110/726] Added feature to `web_programming/nasa_data.py` : Can download the APOD image to a specified location on disk. (#5551) * Added a feature to download images. * Minor changes * Update nasa_data.py * : Co-authored-by: Christian Clauss --- web_programming/nasa_data.py | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/web_programming/nasa_data.py b/web_programming/nasa_data.py index 9b15c38a7..c0a2c4fdd 100644 --- a/web_programming/nasa_data.py +++ b/web_programming/nasa_data.py @@ -1,27 +1,38 @@ +import shutil + import requests -def get_apod_data(api_key: str) -> dict: +def get_apod_data(api_key: str, download: bool = False, path: str = ".") -> dict: """ Get the APOD(Astronomical Picture of the day) data - Get the API Key from : https://api.nasa.gov/ + Get your API Key from: https://api.nasa.gov/ """ - url = "https://api.nasa.gov/planetary/apod/" + url = "https://api.nasa.gov/planetary/apod" return requests.get(url, params={"api_key": api_key}).json() +def save_apod(api_key: str, path: str = ".") -> dict: + apod_data = get_apod_data(api_key) + img_url = apod_data["url"] + img_name = img_url.split("/")[-1] + response = requests.get(img_url, stream=True) + + with open(f"{path}/{img_name}", "wb+") as img_file: + shutil.copyfileobj(response.raw, img_file) + del response + return apod_data + + def get_archive_data(query: str) -> dict: """ Get the data of a particular query from NASA archives """ - endpoint = "https://images-api.nasa.gov/search" - return requests.get(endpoint, params={"q": query}).json() + url = "https://images-api.nasa.gov/search" + return requests.get(url, params={"q": query}).json() if __name__ == "__main__": - print(get_apod_data("YOUR API KEY")) - print( - get_archive_data("apollo 2011")["collection"]["items"][0]["data"][0][ - "description" - ] - ) + print(save_apod("YOUR API KEY")) + apollo_2011_items = get_archive_data("apollo 2011")["collection"]["items"] + print(apollo_2011_items[0]["data"][0]["description"]) From b72a66b713bb998354df7bfd165c179a756e3b91 Mon Sep 17 00:00:00 2001 From: Mitheel <81575947+mitheelgajare@users.noreply.github.com> Date: Sat, 23 Oct 2021 18:24:41 +0530 Subject: [PATCH 111/726] Fixed grammatical errors in CONTRIBUTING.md (#5555) --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4723c6c39..f5c123674 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ Welcome to [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python)! Befo ### Contributor -We are very happy that you consider implementing algorithms and data structure for others! This repository is referenced and used by learners from all over the globe. Being one of our contributors, you agree and confirm that: +We are very happy that you consider implementing algorithms and data structures for others! This repository is referenced and used by learners from all over the globe. Being one of our contributors, you agree and confirm that: - You did your work - no plagiarism allowed - Any plagiarized work will not be merged. @@ -25,7 +25,7 @@ We appreciate any contribution, from fixing a grammar mistake in a comment to im Your contribution will be tested by our [automated testing on Travis CI](https://travis-ci.org/TheAlgorithms/Python/pull_requests) to save time and mental energy. After you have submitted your pull request, you should see the Travis tests start to run at the bottom of your submission page. If those tests fail, then click on the ___details___ button try to read through the Travis output to understand the failure. If you do not understand, please leave a comment on your submission page and a community member will try to help. -Please help us keep our issue list small by adding fixes: #{$ISSUE_NO} to the commit message of pull requests that resolve open issues. GitHub will use this tag to auto close the issue when the PR is merged. +Please help us keep our issue list small by adding fixes: #{$ISSUE_NO} to the commit message of pull requests that resolve open issues. GitHub will use this tag to auto-close the issue when the PR is merged. #### What is an Algorithm? From 80a885c97563ffc3d93a0678bd7219945be1a166 Mon Sep 17 00:00:00 2001 From: Limbad Yash <56826569+limbad-YK@users.noreply.github.com> Date: Sat, 23 Oct 2021 18:48:09 +0530 Subject: [PATCH 112/726] Update pop function (#5544) * Updated Pop function Added underflow condition * Update Pop Function Added condition to check underflow of stack * Update stack.py * if not self.stack: raise StackUnderflowError * Add doctests * StackUnderflowError * ..., not .... * Update stack.py Co-authored-by: Christian Clauss --- data_structures/stacks/stack.py | 38 ++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/data_structures/stacks/stack.py b/data_structures/stacks/stack.py index c62412150..4bc032f72 100644 --- a/data_structures/stacks/stack.py +++ b/data_structures/stacks/stack.py @@ -5,6 +5,10 @@ class StackOverflowError(BaseException): pass +class StackUnderflowError(BaseException): + pass + + class Stack: """A stack is an abstract data type that serves as a collection of elements with two principal operations: push() and pop(). push() adds an @@ -31,11 +35,29 @@ class Stack: self.stack.append(data) def pop(self): - """Pop an element off of the top of the stack.""" + """ + Pop an element off of the top of the stack. + + >>> Stack().pop() + Traceback (most recent call last): + ... + data_structures.stacks.stack.StackUnderflowError + """ + if not self.stack: + raise StackUnderflowError return self.stack.pop() def peek(self): - """Peek at the top-most element of the stack.""" + """ + Peek at the top-most element of the stack. + + >>> Stack().pop() + Traceback (most recent call last): + ... + data_structures.stacks.stack.StackUnderflowError + """ + if not self.stack: + raise StackUnderflowError return self.stack[-1] def is_empty(self) -> bool: @@ -67,22 +89,22 @@ def test_stack() -> None: try: _ = stack.pop() assert False # This should not happen - except IndexError: + except StackUnderflowError: assert True # This should happen try: _ = stack.peek() assert False # This should not happen - except IndexError: + except StackUnderflowError: assert True # This should happen for i in range(10): assert stack.size() == i stack.push(i) - assert bool(stack) is True - assert stack.is_empty() is False - assert stack.is_full() is True + assert bool(stack) + assert not stack.is_empty() + assert stack.is_full() assert str(stack) == str(list(range(10))) assert stack.pop() == 9 assert stack.peek() == 8 @@ -96,7 +118,7 @@ def test_stack() -> None: except StackOverflowError: assert True # This should happen - assert stack.is_empty() is False + assert not stack.is_empty() assert stack.size() == 10 assert 5 in stack From 218d8921dbb264c9636bef5bd10e23acafd032eb Mon Sep 17 00:00:00 2001 From: Studiex <80968515+Studiex@users.noreply.github.com> Date: Sat, 23 Oct 2021 17:20:52 +0400 Subject: [PATCH 113/726] Implementation of SHA-256 using Python (#5532) * Add files via upload * Update sha256.py * Update sha256.py * Update sha256.py * Update sha256.py * Update sha256.py * Update sha256.py * Update sha256.py * Update sha256.py * @staticmethod def preprocessing(data: bytes) -> bytes: Co-authored-by: Christian Clauss --- hashes/sha256.py | 248 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 hashes/sha256.py diff --git a/hashes/sha256.py b/hashes/sha256.py new file mode 100644 index 000000000..9d4f250fe --- /dev/null +++ b/hashes/sha256.py @@ -0,0 +1,248 @@ +# Author: M. Yathurshan +# Black Formatter: True + +""" +Implementation of SHA256 Hash function in a Python class and provides utilities +to find hash of string or hash of text from a file. + +Usage: python sha256.py --string "Hello World!!" + python sha256.py --file "hello_world.txt" + When run without any arguments, + it prints the hash of the string "Hello World!! Welcome to Cryptography" + +References: +https://qvault.io/cryptography/how-sha-2-works-step-by-step-sha-256/ +https://en.wikipedia.org/wiki/SHA-2 +""" + +import argparse +import struct +import unittest + + +class SHA256: + """ + Class to contain the entire pipeline for SHA1 Hashing Algorithm + + >>> SHA256(b'Python').hash + '18885f27b5af9012df19e496460f9294d5ab76128824c6f993787004f6d9a7db' + + >>> SHA256(b'hello world').hash + 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9' + """ + + def __init__(self, data: bytes) -> None: + self.data = data + + # Initialize hash values + self.hashes = [ + 0x6A09E667, + 0xBB67AE85, + 0x3C6EF372, + 0xA54FF53A, + 0x510E527F, + 0x9B05688C, + 0x1F83D9AB, + 0x5BE0CD19, + ] + + # Initialize round constants + self.round_constants = [ + 0x428A2F98, + 0x71374491, + 0xB5C0FBCF, + 0xE9B5DBA5, + 0x3956C25B, + 0x59F111F1, + 0x923F82A4, + 0xAB1C5ED5, + 0xD807AA98, + 0x12835B01, + 0x243185BE, + 0x550C7DC3, + 0x72BE5D74, + 0x80DEB1FE, + 0x9BDC06A7, + 0xC19BF174, + 0xE49B69C1, + 0xEFBE4786, + 0x0FC19DC6, + 0x240CA1CC, + 0x2DE92C6F, + 0x4A7484AA, + 0x5CB0A9DC, + 0x76F988DA, + 0x983E5152, + 0xA831C66D, + 0xB00327C8, + 0xBF597FC7, + 0xC6E00BF3, + 0xD5A79147, + 0x06CA6351, + 0x14292967, + 0x27B70A85, + 0x2E1B2138, + 0x4D2C6DFC, + 0x53380D13, + 0x650A7354, + 0x766A0ABB, + 0x81C2C92E, + 0x92722C85, + 0xA2BFE8A1, + 0xA81A664B, + 0xC24B8B70, + 0xC76C51A3, + 0xD192E819, + 0xD6990624, + 0xF40E3585, + 0x106AA070, + 0x19A4C116, + 0x1E376C08, + 0x2748774C, + 0x34B0BCB5, + 0x391C0CB3, + 0x4ED8AA4A, + 0x5B9CCA4F, + 0x682E6FF3, + 0x748F82EE, + 0x78A5636F, + 0x84C87814, + 0x8CC70208, + 0x90BEFFFA, + 0xA4506CEB, + 0xBEF9A3F7, + 0xC67178F2, + ] + + self.preprocessed_data = self.preprocessing(self.data) + self.final_hash() + + @staticmethod + def preprocessing(data: bytes) -> bytes: + padding = b"\x80" + (b"\x00" * (63 - (len(data) + 8) % 64)) + big_endian_integer = struct.pack(">Q", (len(data) * 8)) + return data + padding + big_endian_integer + + def final_hash(self) -> None: + # Convert into blocks of 64 bytes + self.blocks = [ + self.preprocessed_data[x : x + 64] + for x in range(0, len(self.preprocessed_data), 64) + ] + + for block in self.blocks: + # Convert the given block into a list of 4 byte integers + words = list(struct.unpack(">16L", block)) + # add 48 0-ed integers + words += [0] * 48 + + a, b, c, d, e, f, g, h = self.hashes + + for index in range(0, 64): + if index > 15: + # modify the zero-ed indexes at the end of the array + s0 = ( + self.ror(words[index - 15], 7) + ^ self.ror(words[index - 15], 18) + ^ (words[index - 15] >> 3) + ) + s1 = ( + self.ror(words[index - 2], 17) + ^ self.ror(words[index - 2], 19) + ^ (words[index - 2] >> 10) + ) + + words[index] = ( + words[index - 16] + s0 + words[index - 7] + s1 + ) % 0x100000000 + + # Compression + S1 = self.ror(e, 6) ^ self.ror(e, 11) ^ self.ror(e, 25) + ch = (e & f) ^ ((~e & (0xFFFFFFFF)) & g) + temp1 = ( + h + S1 + ch + self.round_constants[index] + words[index] + ) % 0x100000000 + S0 = self.ror(a, 2) ^ self.ror(a, 13) ^ self.ror(a, 22) + maj = (a & b) ^ (a & c) ^ (b & c) + temp2 = (S0 + maj) % 0x100000000 + + h, g, f, e, d, c, b, a = ( + g, + f, + e, + ((d + temp1) % 0x100000000), + c, + b, + a, + ((temp1 + temp2) % 0x100000000), + ) + + mutated_hash_values = [a, b, c, d, e, f, g, h] + + # Modify final values + self.hashes = [ + ((element + mutated_hash_values[index]) % 0x100000000) + for index, element in enumerate(self.hashes) + ] + + self.hash = "".join([hex(value)[2:].zfill(8) for value in self.hashes]) + + def ror(self, value: int, rotations: int) -> int: + """ + Right rotate a given unsigned number by a certain amount of rotations + """ + return 0xFFFFFFFF & (value << (32 - rotations)) | (value >> rotations) + + +class SHA256HashTest(unittest.TestCase): + """ + Test class for the SHA256 class. Inherits the TestCase class from unittest + """ + + def test_match_hashes(self) -> None: + import hashlib + + msg = bytes("Test String", "utf-8") + self.assertEqual(SHA256(msg).hash, hashlib.sha256(msg).hexdigest()) + + +def main() -> None: + """ + Provides option 'string' or 'file' to take input + and prints the calculated SHA-256 hash + """ + + # unittest.main() + + import doctest + + doctest.testmod() + + parser = argparse.ArgumentParser() + parser.add_argument( + "-s", + "--string", + dest="input_string", + default="Hello World!! Welcome to Cryptography", + help="Hash the string", + ) + parser.add_argument( + "-f", "--file", dest="input_file", help="Hash contents of a file" + ) + + args = parser.parse_args() + + input_string = args.input_string + + # hash input should be a bytestring + if args.input_file: + with open(args.input_file, "rb") as f: + hash_input = f.read() + else: + hash_input = bytes(input_string, "utf-8") + + print(SHA256(hash_input).hash) + + +if __name__ == "__main__": + main() From bd9464e4ac6ccccd4699bf52bddefa2bfb1dafea Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 23 Oct 2021 18:15:30 +0200 Subject: [PATCH 114/726] mandelbrot.py: Commenting out long running tests (#5558) * mandelbrot.py: Commenting out long running tests * updating DIRECTORY.md * Comment out 9 sec doctests * Update bidirectional_breadth_first_search.py * Comment out slow tests * Comment out slow (9.15 sec) pytests... * # Comment out slow (4.20s call) doctests * Comment out slow (3.45s) doctests * Update miller_rabin.py * Update miller_rabin.py Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 3 +++ fractals/mandelbrot.py | 6 ++++-- graphs/bidirectional_breadth_first_search.py | 15 +++++++++------ maths/miller_rabin.py | 3 ++- .../download_images_from_google_query.py | 5 +++-- 5 files changed, 21 insertions(+), 11 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 950d8e2c0..66d5f8040 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -317,6 +317,7 @@ * [Breadth First Search Shortest Path](https://github.com/TheAlgorithms/Python/blob/master/graphs/breadth_first_search_shortest_path.py) * [Check Bipartite Graph Bfs](https://github.com/TheAlgorithms/Python/blob/master/graphs/check_bipartite_graph_bfs.py) * [Check Bipartite Graph Dfs](https://github.com/TheAlgorithms/Python/blob/master/graphs/check_bipartite_graph_dfs.py) + * [Check Cycle](https://github.com/TheAlgorithms/Python/blob/master/graphs/check_cycle.py) * [Connected Components](https://github.com/TheAlgorithms/Python/blob/master/graphs/connected_components.py) * [Depth First Search](https://github.com/TheAlgorithms/Python/blob/master/graphs/depth_first_search.py) * [Depth First Search 2](https://github.com/TheAlgorithms/Python/blob/master/graphs/depth_first_search_2.py) @@ -370,6 +371,7 @@ * [Md5](https://github.com/TheAlgorithms/Python/blob/master/hashes/md5.py) * [Sdbm](https://github.com/TheAlgorithms/Python/blob/master/hashes/sdbm.py) * [Sha1](https://github.com/TheAlgorithms/Python/blob/master/hashes/sha1.py) + * [Sha256](https://github.com/TheAlgorithms/Python/blob/master/hashes/sha256.py) ## Knapsack * [Greedy Knapsack](https://github.com/TheAlgorithms/Python/blob/master/knapsack/greedy_knapsack.py) @@ -979,6 +981,7 @@ * [Instagram Crawler](https://github.com/TheAlgorithms/Python/blob/master/web_programming/instagram_crawler.py) * [Instagram Pic](https://github.com/TheAlgorithms/Python/blob/master/web_programming/instagram_pic.py) * [Instagram Video](https://github.com/TheAlgorithms/Python/blob/master/web_programming/instagram_video.py) + * [Nasa Data](https://github.com/TheAlgorithms/Python/blob/master/web_programming/nasa_data.py) * [Random Anime Character](https://github.com/TheAlgorithms/Python/blob/master/web_programming/random_anime_character.py) * [Recaptcha Verification](https://github.com/TheAlgorithms/Python/blob/master/web_programming/recaptcha_verification.py) * [Slack Message](https://github.com/TheAlgorithms/Python/blob/master/web_programming/slack_message.py) diff --git a/fractals/mandelbrot.py b/fractals/mandelbrot.py index de795bb3f..5d61b72e1 100644 --- a/fractals/mandelbrot.py +++ b/fractals/mandelbrot.py @@ -101,9 +101,11 @@ def get_image( of the Mandelbrot set is viewed. The main area of the Mandelbrot set is roughly between "-1.5 < x < 0.5" and "-1 < y < 1" in the figure-coordinates. - >>> get_image().load()[0,0] + Commenting out tests that slow down pytest... + # 13.35s call fractals/mandelbrot.py::mandelbrot.get_image + # >>> get_image().load()[0,0] (255, 0, 0) - >>> get_image(use_distance_color_coding = False).load()[0,0] + # >>> get_image(use_distance_color_coding = False).load()[0,0] (255, 255, 255) """ img = Image.new("RGB", (image_width, image_height)) diff --git a/graphs/bidirectional_breadth_first_search.py b/graphs/bidirectional_breadth_first_search.py index 27e4f0b16..511b080a9 100644 --- a/graphs/bidirectional_breadth_first_search.py +++ b/graphs/bidirectional_breadth_first_search.py @@ -34,16 +34,19 @@ class Node: class BreadthFirstSearch: """ - >>> bfs = BreadthFirstSearch((0, 0), (len(grid) - 1, len(grid[0]) - 1)) - >>> (bfs.start.pos_y + delta[3][0], bfs.start.pos_x + delta[3][1]) + # Comment out slow pytests... + # 9.15s call graphs/bidirectional_breadth_first_search.py:: \ + # graphs.bidirectional_breadth_first_search.BreadthFirstSearch + # >>> bfs = BreadthFirstSearch((0, 0), (len(grid) - 1, len(grid[0]) - 1)) + # >>> (bfs.start.pos_y + delta[3][0], bfs.start.pos_x + delta[3][1]) (0, 1) - >>> [x.pos for x in bfs.get_successors(bfs.start)] + # >>> [x.pos for x in bfs.get_successors(bfs.start)] [(1, 0), (0, 1)] - >>> (bfs.start.pos_y + delta[2][0], bfs.start.pos_x + delta[2][1]) + # >>> (bfs.start.pos_y + delta[2][0], bfs.start.pos_x + delta[2][1]) (1, 0) - >>> bfs.retrace_path(bfs.start) + # >>> bfs.retrace_path(bfs.start) [(0, 0)] - >>> bfs.search() # doctest: +NORMALIZE_WHITESPACE + # >>> bfs.search() # doctest: +NORMALIZE_WHITESPACE [(0, 0), (1, 0), (2, 0), (3, 0), (3, 1), (4, 1), (5, 1), (5, 2), (5, 3), (5, 4), (5, 5), (6, 5), (6, 6)] """ diff --git a/maths/miller_rabin.py b/maths/miller_rabin.py index fe9920271..2b0944508 100644 --- a/maths/miller_rabin.py +++ b/maths/miller_rabin.py @@ -9,7 +9,8 @@ from .binary_exp_mod import bin_exp_mod def is_prime(n, prec=1000): """ >>> from .prime_check import prime_check - >>> all(is_prime(i) == prime_check(i) for i in range(1000)) + >>> # all(is_prime(i) == prime_check(i) for i in range(1000)) # 3.45s + >>> all(is_prime(i) == prime_check(i) for i in range(256)) True """ if n < 2: diff --git a/web_programming/download_images_from_google_query.py b/web_programming/download_images_from_google_query.py index c26262788..b11a7f883 100644 --- a/web_programming/download_images_from_google_query.py +++ b/web_programming/download_images_from_google_query.py @@ -24,9 +24,10 @@ def download_images_from_google_query(query: str = "dhaka", max_images: int = 5) Returns: The number of images successfully downloaded. - >>> download_images_from_google_query() + # Comment out slow (4.20s call) doctests + # >>> download_images_from_google_query() 5 - >>> download_images_from_google_query("potato") + # >>> download_images_from_google_query("potato") 5 """ max_images = min(max_images, 50) # Prevent abuse! From 00a67010e8c28cdaa6142d0c4a386282bbf29421 Mon Sep 17 00:00:00 2001 From: Martmists Date: Sat, 23 Oct 2021 23:19:25 +0200 Subject: [PATCH 115/726] Simple audio filters (#5230) * Add IIR Filter and Butterworth design functions Signed-off-by: Martmists * naming conventions and missing type hints Signed-off-by: Martmists * Link wikipedia in IIRFilter Signed-off-by: Martmists * Add doctests and None return types Signed-off-by: Martmists * More doctests Signed-off-by: Martmists * Requested changes Signed-off-by: Martmists * run pre-commit Signed-off-by: Martmists * Make mypy stop complaining about ints vs floats Signed-off-by: Martmists * Use slower listcomp to make it more readable Signed-off-by: Martmists * Make doctests happy Signed-off-by: Martmists * Remove scipy Signed-off-by: Martmists * Test coefficients from bw filters Signed-off-by: Martmists * Protocol test Co-authored-by: Christian Clauss * Make requested change Signed-off-by: Martmists * Types Signed-off-by: Martmists * Apply suggestions from code review * Apply suggestions from code review * Update butterworth_filter.py Co-authored-by: Christian Clauss --- audio_filters/__init__.py | 0 audio_filters/butterworth_filter.py | 217 ++++++++++++++++++++++++++++ audio_filters/iir_filter.py | 92 ++++++++++++ audio_filters/show_response.py | 94 ++++++++++++ 4 files changed, 403 insertions(+) create mode 100644 audio_filters/__init__.py create mode 100644 audio_filters/butterworth_filter.py create mode 100644 audio_filters/iir_filter.py create mode 100644 audio_filters/show_response.py diff --git a/audio_filters/__init__.py b/audio_filters/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/audio_filters/butterworth_filter.py b/audio_filters/butterworth_filter.py new file mode 100644 index 000000000..409cfeb1d --- /dev/null +++ b/audio_filters/butterworth_filter.py @@ -0,0 +1,217 @@ +from math import cos, sin, sqrt, tau + +from audio_filters.iir_filter import IIRFilter + +""" +Create 2nd-order IIR filters with Butterworth design. + +Code based on https://webaudio.github.io/Audio-EQ-Cookbook/audio-eq-cookbook.html +Alternatively you can use scipy.signal.butter, which should yield the same results. +""" + + +def make_lowpass( + frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2) +) -> IIRFilter: + """ + Creates a low-pass filter + + >>> filter = make_lowpass(1000, 48000) + >>> filter.a_coeffs + filter.b_coeffs # doctest: +NORMALIZE_WHITESPACE + [1.0922959556412573, -1.9828897227476208, 0.9077040443587427, 0.004277569313094809, + 0.008555138626189618, 0.004277569313094809] + """ + w0 = tau * frequency / samplerate + _sin = sin(w0) + _cos = cos(w0) + alpha = _sin / (2 * q_factor) + + b0 = (1 - _cos) / 2 + b1 = 1 - _cos + + a0 = 1 + alpha + a1 = -2 * _cos + a2 = 1 - alpha + + filt = IIRFilter(2) + filt.set_coefficients([a0, a1, a2], [b0, b1, b0]) + return filt + + +def make_highpass( + frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2) +) -> IIRFilter: + """ + Creates a high-pass filter + + >>> filter = make_highpass(1000, 48000) + >>> filter.a_coeffs + filter.b_coeffs # doctest: +NORMALIZE_WHITESPACE + [1.0922959556412573, -1.9828897227476208, 0.9077040443587427, 0.9957224306869052, + -1.9914448613738105, 0.9957224306869052] + """ + w0 = tau * frequency / samplerate + _sin = sin(w0) + _cos = cos(w0) + alpha = _sin / (2 * q_factor) + + b0 = (1 + _cos) / 2 + b1 = -1 - _cos + + a0 = 1 + alpha + a1 = -2 * _cos + a2 = 1 - alpha + + filt = IIRFilter(2) + filt.set_coefficients([a0, a1, a2], [b0, b1, b0]) + return filt + + +def make_bandpass( + frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2) +) -> IIRFilter: + """ + Creates a band-pass filter + + >>> filter = make_bandpass(1000, 48000) + >>> filter.a_coeffs + filter.b_coeffs # doctest: +NORMALIZE_WHITESPACE + [1.0922959556412573, -1.9828897227476208, 0.9077040443587427, 0.06526309611002579, + 0, -0.06526309611002579] + """ + w0 = tau * frequency / samplerate + _sin = sin(w0) + _cos = cos(w0) + alpha = _sin / (2 * q_factor) + + b0 = _sin / 2 + b1 = 0 + b2 = -b0 + + a0 = 1 + alpha + a1 = -2 * _cos + a2 = 1 - alpha + + filt = IIRFilter(2) + filt.set_coefficients([a0, a1, a2], [b0, b1, b2]) + return filt + + +def make_allpass( + frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2) +) -> IIRFilter: + """ + Creates an all-pass filter + + >>> filter = make_allpass(1000, 48000) + >>> filter.a_coeffs + filter.b_coeffs # doctest: +NORMALIZE_WHITESPACE + [1.0922959556412573, -1.9828897227476208, 0.9077040443587427, 0.9077040443587427, + -1.9828897227476208, 1.0922959556412573] + """ + w0 = tau * frequency / samplerate + _sin = sin(w0) + _cos = cos(w0) + alpha = _sin / (2 * q_factor) + + b0 = 1 - alpha + b1 = -2 * _cos + b2 = 1 + alpha + + filt = IIRFilter(2) + filt.set_coefficients([b2, b1, b0], [b0, b1, b2]) + return filt + + +def make_peak( + frequency: int, samplerate: int, gain_db: float, q_factor: float = 1 / sqrt(2) +) -> IIRFilter: + """ + Creates a peak filter + + >>> filter = make_peak(1000, 48000, 6) + >>> filter.a_coeffs + filter.b_coeffs # doctest: +NORMALIZE_WHITESPACE + [1.0653405327119334, -1.9828897227476208, 0.9346594672880666, 1.1303715025601122, + -1.9828897227476208, 0.8696284974398878] + """ + w0 = tau * frequency / samplerate + _sin = sin(w0) + _cos = cos(w0) + alpha = _sin / (2 * q_factor) + big_a = 10 ** (gain_db / 40) + + b0 = 1 + alpha * big_a + b1 = -2 * _cos + b2 = 1 - alpha * big_a + a0 = 1 + alpha / big_a + a1 = -2 * _cos + a2 = 1 - alpha / big_a + + filt = IIRFilter(2) + filt.set_coefficients([a0, a1, a2], [b0, b1, b2]) + return filt + + +def make_lowshelf( + frequency: int, samplerate: int, gain_db: float, q_factor: float = 1 / sqrt(2) +) -> IIRFilter: + """ + Creates a low-shelf filter + + >>> filter = make_lowshelf(1000, 48000, 6) + >>> filter.a_coeffs + filter.b_coeffs # doctest: +NORMALIZE_WHITESPACE + [3.0409336710888786, -5.608870992220748, 2.602157875636628, 3.139954022810743, + -5.591841778072785, 2.5201667380627257] + """ + w0 = tau * frequency / samplerate + _sin = sin(w0) + _cos = cos(w0) + alpha = _sin / (2 * q_factor) + big_a = 10 ** (gain_db / 40) + pmc = (big_a + 1) - (big_a - 1) * _cos + ppmc = (big_a + 1) + (big_a - 1) * _cos + mpc = (big_a - 1) - (big_a + 1) * _cos + pmpc = (big_a - 1) + (big_a + 1) * _cos + aa2 = 2 * sqrt(big_a) * alpha + + b0 = big_a * (pmc + aa2) + b1 = 2 * big_a * mpc + b2 = big_a * (pmc - aa2) + a0 = ppmc + aa2 + a1 = -2 * pmpc + a2 = ppmc - aa2 + + filt = IIRFilter(2) + filt.set_coefficients([a0, a1, a2], [b0, b1, b2]) + return filt + + +def make_highshelf( + frequency: int, samplerate: int, gain_db: float, q_factor: float = 1 / sqrt(2) +) -> IIRFilter: + """ + Creates a high-shelf filter + + >>> filter = make_highshelf(1000, 48000, 6) + >>> filter.a_coeffs + filter.b_coeffs # doctest: +NORMALIZE_WHITESPACE + [2.2229172136088806, -3.9587208137297303, 1.7841414181566304, 4.295432981120543, + -7.922740859457287, 3.6756456963725253] + """ + w0 = tau * frequency / samplerate + _sin = sin(w0) + _cos = cos(w0) + alpha = _sin / (2 * q_factor) + big_a = 10 ** (gain_db / 40) + pmc = (big_a + 1) - (big_a - 1) * _cos + ppmc = (big_a + 1) + (big_a - 1) * _cos + mpc = (big_a - 1) - (big_a + 1) * _cos + pmpc = (big_a - 1) + (big_a + 1) * _cos + aa2 = 2 * sqrt(big_a) * alpha + + b0 = big_a * (ppmc + aa2) + b1 = -2 * big_a * pmpc + b2 = big_a * (ppmc - aa2) + a0 = pmc + aa2 + a1 = 2 * mpc + a2 = pmc - aa2 + + filt = IIRFilter(2) + filt.set_coefficients([a0, a1, a2], [b0, b1, b2]) + return filt diff --git a/audio_filters/iir_filter.py b/audio_filters/iir_filter.py new file mode 100644 index 000000000..aae320365 --- /dev/null +++ b/audio_filters/iir_filter.py @@ -0,0 +1,92 @@ +from __future__ import annotations + + +class IIRFilter: + r""" + N-Order IIR filter + Assumes working with float samples normalized on [-1, 1] + + --- + + Implementation details: + Based on the 2nd-order function from + https://en.wikipedia.org/wiki/Digital_biquad_filter, + this generalized N-order function was made. + + Using the following transfer function + H(z)=\frac{b_{0}+b_{1}z^{-1}+b_{2}z^{-2}+...+b_{k}z^{-k}}{a_{0}+a_{1}z^{-1}+a_{2}z^{-2}+...+a_{k}z^{-k}} + we can rewrite this to + y[n]={\frac{1}{a_{0}}}\left(\left(b_{0}x[n]+b_{1}x[n-1]+b_{2}x[n-2]+...+b_{k}x[n-k]\right)-\left(a_{1}y[n-1]+a_{2}y[n-2]+...+a_{k}y[n-k]\right)\right) + """ + + def __init__(self, order: int) -> None: + self.order = order + + # a_{0} ... a_{k} + self.a_coeffs = [1.0] + [0.0] * order + # b_{0} ... b_{k} + self.b_coeffs = [1.0] + [0.0] * order + + # x[n-1] ... x[n-k] + self.input_history = [0.0] * self.order + # y[n-1] ... y[n-k] + self.output_history = [0.0] * self.order + + def set_coefficients(self, a_coeffs: list[float], b_coeffs: list[float]) -> None: + """ + Set the coefficients for the IIR filter. These should both be of size order + 1. + a_0 may be left out, and it will use 1.0 as default value. + + This method works well with scipy's filter design functions + >>> # Make a 2nd-order 1000Hz butterworth lowpass filter + >>> import scipy.signal + >>> b_coeffs, a_coeffs = scipy.signal.butter(2, 1000, + ... btype='lowpass', + ... fs=48000) + >>> filt = IIRFilter(2) + >>> filt.set_coefficients(a_coeffs, b_coeffs) + """ + if len(a_coeffs) < self.order: + a_coeffs = [1.0] + a_coeffs + + if len(a_coeffs) != self.order + 1: + raise ValueError( + f"Expected a_coeffs to have {self.order + 1} elements for {self.order}" + f"-order filter, got {len(a_coeffs)}" + ) + + if len(b_coeffs) != self.order + 1: + raise ValueError( + f"Expected b_coeffs to have {self.order + 1} elements for {self.order}" + f"-order filter, got {len(a_coeffs)}" + ) + + self.a_coeffs = a_coeffs + self.b_coeffs = b_coeffs + + def process(self, sample: float) -> float: + """ + Calculate y[n] + + >>> filt = IIRFilter(2) + >>> filt.process(0) + 0.0 + """ + result = 0.0 + + # Start at index 1 and do index 0 at the end. + for i in range(1, self.order + 1): + result += ( + self.b_coeffs[i] * self.input_history[i - 1] + - self.a_coeffs[i] * self.output_history[i - 1] + ) + + result = (result + self.b_coeffs[0] * sample) / self.a_coeffs[0] + + self.input_history[1:] = self.input_history[:-1] + self.output_history[1:] = self.output_history[:-1] + + self.input_history[0] = sample + self.output_history[0] = result + + return result diff --git a/audio_filters/show_response.py b/audio_filters/show_response.py new file mode 100644 index 000000000..6e2731a58 --- /dev/null +++ b/audio_filters/show_response.py @@ -0,0 +1,94 @@ +from __future__ import annotations + +from math import pi +from typing import Protocol + +import matplotlib.pyplot as plt +import numpy as np + + +class FilterType(Protocol): + def process(self, sample: float) -> float: + """ + Calculate y[n] + + >>> issubclass(FilterType, Protocol) + True + """ + return 0.0 + + +def get_bounds( + fft_results: np.ndarray, samplerate: int +) -> tuple[int | float, int | float]: + """ + Get bounds for printing fft results + + >>> import numpy + >>> array = numpy.linspace(-20.0, 20.0, 1000) + >>> get_bounds(array, 1000) + (-20, 20) + """ + lowest = min([-20, np.min(fft_results[1 : samplerate // 2 - 1])]) + highest = max([20, np.max(fft_results[1 : samplerate // 2 - 1])]) + return lowest, highest + + +def show_frequency_response(filter: FilterType, samplerate: int) -> None: + """ + Show frequency response of a filter + + >>> from audio_filters.iir_filter import IIRFilter + >>> filt = IIRFilter(4) + >>> show_frequency_response(filt, 48000) + """ + + size = 512 + inputs = [1] + [0] * (size - 1) + outputs = [filter.process(item) for item in inputs] + + filler = [0] * (samplerate - size) # zero-padding + outputs += filler + fft_out = np.abs(np.fft.fft(outputs)) + fft_db = 20 * np.log10(fft_out) + + # Frequencies on log scale from 24 to nyquist frequency + plt.xlim(24, samplerate / 2 - 1) + plt.xlabel("Frequency (Hz)") + plt.xscale("log") + + # Display within reasonable bounds + bounds = get_bounds(fft_db, samplerate) + plt.ylim(max([-80, bounds[0]]), min([80, bounds[1]])) + plt.ylabel("Gain (dB)") + + plt.plot(fft_db) + plt.show() + + +def show_phase_response(filter: FilterType, samplerate: int) -> None: + """ + Show phase response of a filter + + >>> from audio_filters.iir_filter import IIRFilter + >>> filt = IIRFilter(4) + >>> show_phase_response(filt, 48000) + """ + + size = 512 + inputs = [1] + [0] * (size - 1) + outputs = [filter.process(item) for item in inputs] + + filler = [0] * (samplerate - size) # zero-padding + outputs += filler + fft_out = np.angle(np.fft.fft(outputs)) + + # Frequencies on log scale from 24 to nyquist frequency + plt.xlim(24, samplerate / 2 - 1) + plt.xlabel("Frequency (Hz)") + plt.xscale("log") + + plt.ylim(-2 * pi, 2 * pi) + plt.ylabel("Phase shift (Radians)") + plt.plot(np.unwrap(fft_out, -2 * pi)) + plt.show() From aaaa175b66f2b335023433a3c40635388b98c489 Mon Sep 17 00:00:00 2001 From: Erwin Junge Date: Sat, 23 Oct 2021 23:26:21 +0200 Subject: [PATCH 116/726] [mypy] annotate `computer_vision` (#5571) --- computer_vision/harris_corner.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/computer_vision/harris_corner.py b/computer_vision/harris_corner.py index fb7f560f7..02deb5408 100644 --- a/computer_vision/harris_corner.py +++ b/computer_vision/harris_corner.py @@ -21,11 +21,11 @@ class Harris_Corner: else: raise ValueError("invalid k value") - def __str__(self): + def __str__(self) -> str: return f"Harris Corner detection with k : {self.k}" - def detect(self, img_path: str): + def detect(self, img_path: str) -> tuple[cv2.Mat, list[list[int]]]: """ Returns the image with corners identified @@ -35,7 +35,7 @@ class Harris_Corner: img = cv2.imread(img_path, 0) h, w = img.shape - corner_list = [] + corner_list: list[list[int]] = [] color_img = img.copy() color_img = cv2.cvtColor(color_img, cv2.COLOR_GRAY2RGB) dy, dx = np.gradient(img) From 5772d0734b72c307c0e08c76121b3eca589f50d4 Mon Sep 17 00:00:00 2001 From: Marcel Kuhmann Date: Sun, 24 Oct 2021 18:44:15 +0200 Subject: [PATCH 117/726] fix dead link (#5572) --- project_euler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project_euler/README.md b/project_euler/README.md index 1cc6f8150..c4c0a8544 100644 --- a/project_euler/README.md +++ b/project_euler/README.md @@ -28,7 +28,7 @@ Welcome to [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python)! Befo * When the `solution` function is called without any arguments like so: `solution()`, it should return the answer to the problem. * Every function, which includes all the helper functions, if any, and the main solution function, should have `doctest` in the function docstring along with a brief statement mentioning what the function is about. - * There should not be a `doctest` for testing the answer as that is done by our Travis CI build using this [script](https://github.com/TheAlgorithms/Python/blob/master/project_euler/validate_solutions.py). Keeping in mind the above example of [Problem 1](https://projecteuler.net/problem=1): + * There should not be a `doctest` for testing the answer as that is done by our Travis CI build using this [script](https://github.com/TheAlgorithms/Python/blob/master/scripts/validate_solutions.py). Keeping in mind the above example of [Problem 1](https://projecteuler.net/problem=1): ```python def solution(limit: int = 1000): From fc5d29e214c5624edec43300311b24c9d3962ac2 Mon Sep 17 00:00:00 2001 From: Vinicius Cordeiro Date: Sun, 24 Oct 2021 17:33:53 -0300 Subject: [PATCH 118/726] Add Bifid cipher (#5493) * Add Bifid cipher * Add missing type hint * Fix variable names --- ciphers/bifid.py | 110 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 ciphers/bifid.py diff --git a/ciphers/bifid.py b/ciphers/bifid.py new file mode 100644 index 000000000..c1b071155 --- /dev/null +++ b/ciphers/bifid.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 + +""" +The Bifid Cipher uses a Polybius Square to encipher a message in a way that +makes it fairly difficult to decipher without knowing the secret. + +https://www.braingle.com/brainteasers/codes/bifid.php +""" + +import numpy as np + + +class BifidCipher: + def __init__(self) -> None: + SQUARE = [ + ["a", "b", "c", "d", "e"], + ["f", "g", "h", "i", "k"], + ["l", "m", "n", "o", "p"], + ["q", "r", "s", "t", "u"], + ["v", "w", "x", "y", "z"], + ] + self.SQUARE = np.array(SQUARE) + + def letter_to_numbers(self, letter: str) -> np.ndarray: + """ + Return the pair of numbers that represents the given letter in the + polybius square + + >>> np.array_equal(BifidCipher().letter_to_numbers('a'), [1,1]) + True + + >>> np.array_equal(BifidCipher().letter_to_numbers('u'), [4,5]) + True + """ + index1, index2 = np.where(self.SQUARE == letter) + indexes = np.concatenate([index1 + 1, index2 + 1]) + return indexes + + def numbers_to_letter(self, index1: int, index2: int) -> str: + """ + Return the letter corresponding to the position [index1, index2] in + the polybius square + + >>> BifidCipher().numbers_to_letter(4, 5) == "u" + True + + >>> BifidCipher().numbers_to_letter(1, 1) == "a" + True + """ + letter = self.SQUARE[index1 - 1, index2 - 1] + return letter + + def encode(self, message: str) -> str: + """ + Return the encoded version of message according to the polybius cipher + + >>> BifidCipher().encode('testmessage') == 'qtltbdxrxlk' + True + + >>> BifidCipher().encode('Test Message') == 'qtltbdxrxlk' + True + + >>> BifidCipher().encode('test j') == BifidCipher().encode('test i') + True + """ + message = message.lower() + message = message.replace(" ", "") + message = message.replace("j", "i") + + first_step = np.empty((2, len(message))) + for letter_index in range(len(message)): + numbers = self.letter_to_numbers(message[letter_index]) + + first_step[0, letter_index] = numbers[0] + first_step[1, letter_index] = numbers[1] + + second_step = first_step.reshape(2 * len(message)) + encoded_message = "" + for numbers_index in range(len(message)): + index1 = int(second_step[numbers_index * 2]) + index2 = int(second_step[(numbers_index * 2) + 1]) + letter = self.numbers_to_letter(index1, index2) + encoded_message = encoded_message + letter + + return encoded_message + + def decode(self, message: str) -> str: + """ + Return the decoded version of message according to the polybius cipher + + >>> BifidCipher().decode('qtltbdxrxlk') == 'testmessage' + True + """ + message = message.lower() + message.replace(" ", "") + first_step = np.empty(2 * len(message)) + for letter_index in range(len(message)): + numbers = self.letter_to_numbers(message[letter_index]) + first_step[letter_index * 2] = numbers[0] + first_step[letter_index * 2 + 1] = numbers[1] + + second_step = first_step.reshape((2, len(message))) + decoded_message = "" + for numbers_index in range(len(message)): + index1 = int(second_step[0, numbers_index]) + index2 = int(second_step[1, numbers_index]) + letter = self.numbers_to_letter(index1, index2) + decoded_message = decoded_message + letter + + return decoded_message From 568c107e6802dbcb8e6b9b82a31c9884645ac6b4 Mon Sep 17 00:00:00 2001 From: Francisco Perez <92104963+franciscoperez2021@users.noreply.github.com> Date: Mon, 25 Oct 2021 08:58:24 +0100 Subject: [PATCH 119/726] add bin_to_hexadecimal (#5156) --- DIRECTORY.md | 1 + conversions/binary_to_hexadecimal.py | 65 ++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 conversions/binary_to_hexadecimal.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 66d5f8040..13a360ab6 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -107,6 +107,7 @@ ## Conversions * [Binary To Decimal](https://github.com/TheAlgorithms/Python/blob/master/conversions/binary_to_decimal.py) * [Binary To Octal](https://github.com/TheAlgorithms/Python/blob/master/conversions/binary_to_octal.py) + * [Binary To Hexadecimal](https://github.com/TheAlgorithms/Python/blob/master/conversions/binary_to_hexadecimal.py) * [Decimal To Any](https://github.com/TheAlgorithms/Python/blob/master/conversions/decimal_to_any.py) * [Decimal To Binary](https://github.com/TheAlgorithms/Python/blob/master/conversions/decimal_to_binary.py) * [Decimal To Binary Recursion](https://github.com/TheAlgorithms/Python/blob/master/conversions/decimal_to_binary_recursion.py) diff --git a/conversions/binary_to_hexadecimal.py b/conversions/binary_to_hexadecimal.py new file mode 100644 index 000000000..f94a12390 --- /dev/null +++ b/conversions/binary_to_hexadecimal.py @@ -0,0 +1,65 @@ +def bin_to_hexadecimal(binary_str: str) -> str: + """ + Converting a binary string into hexadecimal using Grouping Method + + >>> bin_to_hexadecimal('101011111') + '0x15f' + >>> bin_to_hexadecimal(' 1010 ') + '0x0a' + >>> bin_to_hexadecimal('-11101') + '-0x1d' + >>> bin_to_hexadecimal('a') + Traceback (most recent call last): + ... + ValueError: Non-binary value was passed to the function + >>> bin_to_hexadecimal('') + Traceback (most recent call last): + ... + ValueError: Empty string was passed to the function + """ + BITS_TO_HEX = { + "0000": "0", + "0001": "1", + "0010": "2", + "0011": "3", + "0100": "4", + "0101": "5", + "0110": "6", + "0111": "7", + "1000": "8", + "1001": "9", + "1010": "a", + "1011": "b", + "1100": "c", + "1101": "d", + "1110": "e", + "1111": "f", + } + + # Sanitising parameter + binary_str = str(binary_str).strip() + + # Exceptions + if not binary_str: + raise ValueError("Empty string was passed to the function") + is_negative = binary_str[0] == "-" + binary_str = binary_str[1:] if is_negative else binary_str + if not all(char in "01" for char in binary_str): + raise ValueError("Non-binary value was passed to the function") + + binary_str = ( + "0" * (4 * (divmod(len(binary_str), 4)[0] + 1) - len(binary_str)) + binary_str + ) + + hexadecimal = [] + for x in range(0, len(binary_str), 4): + hexadecimal.append(BITS_TO_HEX[binary_str[x : x + 4]]) + hexadecimal_str = "0x" + "".join(hexadecimal) + + return "-" + hexadecimal_str if is_negative else hexadecimal_str + + +if __name__ == "__main__": + from doctest import testmod + + testmod() From ba710054844fde4ccca666464c4bd08207e64a0d Mon Sep 17 00:00:00 2001 From: Manuel Di Lullo <39048927+manueldilullo@users.noreply.github.com> Date: Mon, 25 Oct 2021 09:59:52 +0200 Subject: [PATCH 120/726] Add random graph generator (#5240) * added complete graph generator function * added doctest, type hints, wikipedia explanation * added return type hint for function complete_graph * added descriptive name for the parameter: n * random graph generator with doctest and type hints * validated using pre-commit * Delete complete_graph_generator.py * fixed doctest * updated following reviews * simplified the code following reviews * fixed doctest and solved consistency issues * consistency fixes --- graphs/random_graph_generator.py | 67 ++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 graphs/random_graph_generator.py diff --git a/graphs/random_graph_generator.py b/graphs/random_graph_generator.py new file mode 100644 index 000000000..d7d5de8a3 --- /dev/null +++ b/graphs/random_graph_generator.py @@ -0,0 +1,67 @@ +""" +* Author: Manuel Di Lullo (https://github.com/manueldilullo) +* Description: Random graphs generator. + Uses graphs represented with an adjacency list. + +URL: https://en.wikipedia.org/wiki/Random_graph +""" + +import random + + +def random_graph( + vertices_number: int, probability: float, directed: bool = False +) -> dict: + """ + Generate a random graph + @input: vertices_number (number of vertices), + probability (probability that a generic edge (u,v) exists), + directed (if True: graph will be a directed graph, + otherwise it will be an undirected graph) + @examples: + >>> random.seed(1) + >>> random_graph(4, 0.5) + {0: [1], 1: [0, 2, 3], 2: [1, 3], 3: [1, 2]} + >>> random.seed(1) + >>> random_graph(4, 0.5, True) + {0: [1], 1: [2, 3], 2: [3], 3: []} + """ + graph = {i: [] for i in range(vertices_number)} + + # if probability is greater or equal than 1, then generate a complete graph + if probability >= 1: + return complete_graph(vertices_number) + # if probability is lower or equal than 0, then return a graph without edges + if probability <= 0: + return graph + + # for each couple of nodes, add an edge from u to v + # if the number randomly generated is greater than probability probability + for i in range(vertices_number): + for j in range(i + 1, vertices_number): + if random.random() < probability: + graph[i].append(j) + if not directed: + # if the graph is undirected, add an edge in from j to i, either + graph[j].append(i) + return graph + + +def complete_graph(vertices_number: int) -> dict: + """ + Generate a complete graph with vertices_number vertices. + @input: vertices_number (number of vertices), + directed (False if the graph is undirected, True otherwise) + @example: + >>> print(complete_graph(3)) + {0: [1, 2], 1: [0, 2], 2: [0, 1]} + """ + return { + i: [j for j in range(vertices_number) if i != j] for i in range(vertices_number) + } + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 5f7bb3e9f7b458d039e1027b48b3d24d9a577f96 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Mon, 25 Oct 2021 11:03:22 +0300 Subject: [PATCH 121/726] Improve Project Euler problem 034 solution 1 (#5165) --- project_euler/problem_034/sol1.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/project_euler/problem_034/sol1.py b/project_euler/problem_034/sol1.py index 11c84ab96..8d8432dbb 100644 --- a/project_euler/problem_034/sol1.py +++ b/project_euler/problem_034/sol1.py @@ -8,6 +8,8 @@ Note: As 1! = 1 and 2! = 2 are not sums they are not included. from math import factorial +DIGIT_FACTORIAL = {str(d): factorial(d) for d in range(10)} + def sum_of_digit_factorial(n: int) -> int: """ @@ -17,7 +19,7 @@ def sum_of_digit_factorial(n: int) -> int: >>> sum_of_digit_factorial(0) 1 """ - return sum(factorial(int(char)) for char in str(n)) + return sum(DIGIT_FACTORIAL[d] for d in str(n)) def solution() -> int: From b55da046029e681c1811f5f1cb24c35117d462ce Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Mon, 25 Oct 2021 11:07:10 +0300 Subject: [PATCH 122/726] Improve Project Euler problem 058 solution 1 (#4782) * Fix typo * Improve solution * Retest * Replace n with number --- project_euler/problem_058/sol1.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/project_euler/problem_058/sol1.py b/project_euler/problem_058/sol1.py index d3b15157f..ed407edf7 100644 --- a/project_euler/problem_058/sol1.py +++ b/project_euler/problem_058/sol1.py @@ -33,11 +33,12 @@ So we check individually each one of these before incrementing our count of current primes. """ +from math import isqrt -def isprime(d: int) -> int: +def isprime(number: int) -> int: """ - returns whether the given digit is prime or not + returns whether the given number is prime or not >>> isprime(1) 0 >>> isprime(17) @@ -45,14 +46,15 @@ def isprime(d: int) -> int: >>> isprime(10000) 0 """ - if d == 1: + if number == 1: return 0 - i = 2 - while i * i <= d: - if d % i == 0: + if number % 2 == 0 and number > 2: + return 0 + + for i in range(3, isqrt(number) + 1, 2): + if number % i == 0: return 0 - i = i + 1 return 1 From 74e442e979b1ffdbafa97765193ec04058893fca Mon Sep 17 00:00:00 2001 From: Mohammad Firmansyah <76118762+dimasdh842@users.noreply.github.com> Date: Mon, 25 Oct 2021 17:18:41 +0000 Subject: [PATCH 123/726] add an algorithm to spin some words (#5597) * add an algorithm to spin some words * Update index.py * Adding type hint of spin_words function * Update and rename python_codewars_disemvowel/index.py to strings/reverse_long_words.py Co-authored-by: Christian Clauss --- strings/reverse_long_words.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 strings/reverse_long_words.py diff --git a/strings/reverse_long_words.py b/strings/reverse_long_words.py new file mode 100644 index 000000000..39ef11513 --- /dev/null +++ b/strings/reverse_long_words.py @@ -0,0 +1,21 @@ +def reverse_long_words(sentence: str) -> str: + """ + Reverse all words that are longer than 4 characters in a sentence. + + >>> reverse_long_words("Hey wollef sroirraw") + 'Hey fellow warriors' + >>> reverse_long_words("nohtyP is nohtyP") + 'Python is Python' + >>> reverse_long_words("1 12 123 1234 54321 654321") + '1 12 123 1234 12345 123456' + """ + return " ".join( + "".join(word[::-1]) if len(word) > 4 else word for word in sentence.split() + ) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + print(reverse_long_words("Hey wollef sroirraw")) From 12e81ea6a2e74691173895418f2129bb4d2752c2 Mon Sep 17 00:00:00 2001 From: "@im_8055" <38890773+Bhargavishnu@users.noreply.github.com> Date: Tue, 26 Oct 2021 10:51:07 +0530 Subject: [PATCH 124/726] Add credit card string validator (#5583) * Add credit card validator *  * Add return type hint * Add test cases for validator function * Add test cases * Feature: Rename file * Update strings/cc_validator.py Co-authored-by: Christian Clauss * Update strings/cc_validator.py Co-authored-by: Christian Clauss * Update strings/cc_validator.py Co-authored-by: Christian Clauss * Review: Fix redundant checks * Review: Refactor * Fix: Update test cases * Refactor * Update credit_card_validator.py Co-authored-by: Christian Clauss --- strings/credit_card_validator.py | 105 +++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 strings/credit_card_validator.py diff --git a/strings/credit_card_validator.py b/strings/credit_card_validator.py new file mode 100644 index 000000000..3b5a1aae6 --- /dev/null +++ b/strings/credit_card_validator.py @@ -0,0 +1,105 @@ +""" +Functions for testing the validity of credit card numbers. + +https://en.wikipedia.org/wiki/Luhn_algorithm +""" + + +def validate_initial_digits(credit_card_number: str) -> bool: + """ + Function to validate initial digits of a given credit card number. + >>> valid = "4111111111111111 41111111111111 34 35 37 412345 523456 634567" + >>> all(validate_initial_digits(cc) for cc in valid.split()) + True + >>> invalid = "32323 36111111111111" + >>> all(validate_initial_digits(cc) is False for cc in invalid.split()) + True + """ + if len(credit_card_number) < 2: + return False + return credit_card_number[0] in "456" or credit_card_number[1] in "457" + + +def luhn_validation(credit_card_number: str) -> bool: + """ + Function to luhn algorithm validation for a given credit card number. + >>> luhn_validation('4111111111111111') + True + >>> luhn_validation('36111111111111') + True + >>> luhn_validation('41111111111111') + False + """ + cc_number = credit_card_number + total = 0 + half_len = len(cc_number) - 2 + for i in range(half_len, -1, -2): + # double the value of every second digit + digit = int(cc_number[i]) + digit *= 2 + # If doubling of a number results in a two digit number + # i.e greater than 9(e.g., 6 × 2 = 12), + # then add the digits of the product (e.g., 12: 1 + 2 = 3, 15: 1 + 5 = 6), + # to get a single digit number. + if digit > 9: + digit %= 10 + digit += 1 + cc_number = cc_number[:i] + str(digit) + cc_number[i + 1 :] + total += digit + + # Sum up the remaining digits + for i in range(len(cc_number) - 1, -1, -2): + total += int(cc_number[i]) + + return total % 10 == 0 + + +def validate_credit_card_number(credit_card_number: str) -> bool: + """ + Function to validate the given credit card number. + >>> validate_credit_card_number('4111111111111111') + 4111111111111111 is a valid credit card number. + True + >>> validate_credit_card_number('helloworld$') + helloworld$ is an invalid credit card number because it has nonnumerical characters. + False + >>> validate_credit_card_number('32323') + 32323 is an invalid credit card number because of its length. + False + >>> validate_credit_card_number('32323323233232332323') + 32323323233232332323 is an invalid credit card number because of its length. + False + >>> validate_credit_card_number('36111111111111') + 36111111111111 is an invalid credit card number because of its first two digits. + False + >>> validate_credit_card_number('41111111111111') + 41111111111111 is an invalid credit card number because it fails the Lhun check. + False + """ + error_message = f"{credit_card_number} is an invalid credit card number because" + if not credit_card_number.isdigit(): + print(f"{error_message} it has nonnumerical characters.") + return False + + if not 13 <= len(credit_card_number) <= 16: + print(f"{error_message} of its length.") + return False + + if not validate_initial_digits(credit_card_number): + print(f"{error_message} of its first two digits.") + return False + + if not luhn_validation(credit_card_number): + print(f"{error_message} it fails the Lhun check.") + return False + + print(f"{credit_card_number} is a valid credit card number.") + return True + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + validate_credit_card_number("4111111111111111") + validate_credit_card_number("32323") From 716beb32ed231217c05782be9323ef43f6c1a0ce Mon Sep 17 00:00:00 2001 From: Leoriem-code <73761711+Leoriem-code@users.noreply.github.com> Date: Tue, 26 Oct 2021 09:21:44 +0200 Subject: [PATCH 125/726] Improved prime_numbers.py (#5592) * Improved prime_numbers.py * update prime_numbers.py * Increase the timeit number to 1_000_000 Co-authored-by: Christian Clauss --- maths/prime_numbers.py | 55 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/maths/prime_numbers.py b/maths/prime_numbers.py index 38bebddee..183fbd393 100644 --- a/maths/prime_numbers.py +++ b/maths/prime_numbers.py @@ -58,6 +58,38 @@ def primes(max: int) -> Generator[int, None, None]: yield i +def fast_primes(max: int) -> Generator[int, None, None]: + """ + Return a list of all primes numbers up to max. + >>> list(fast_primes(0)) + [] + >>> list(fast_primes(-1)) + [] + >>> list(fast_primes(-10)) + [] + >>> list(fast_primes(25)) + [2, 3, 5, 7, 11, 13, 17, 19, 23] + >>> list(fast_primes(11)) + [2, 3, 5, 7, 11] + >>> list(fast_primes(33)) + [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31] + >>> list(fast_primes(10000))[-1] + 9973 + """ + numbers: Generator = (i for i in range(1, (max + 1), 2)) + # It's useless to test even numbers as they will not be prime + if max > 2: + yield 2 # Because 2 will not be tested, it's necessary to yield it now + for i in (n for n in numbers if n > 1): + bound = int(math.sqrt(i)) + 1 + for j in range(3, bound, 2): + # As we removed the even numbers, we don't need them now + if (i % j) == 0: + break + else: + yield i + + if __name__ == "__main__": number = int(input("Calculate primes up to:\n>> ").strip()) for ret in primes(number): @@ -66,5 +98,24 @@ if __name__ == "__main__": # Let's benchmark them side-by-side... from timeit import timeit - print(timeit("slow_primes(1_000_000)", setup="from __main__ import slow_primes")) - print(timeit("primes(1_000_000)", setup="from __main__ import primes")) + print( + timeit( + "slow_primes(1_000_000_000_000)", + setup="from __main__ import slow_primes", + number=1_000_000, + ) + ) + print( + timeit( + "primes(1_000_000_000_000)", + setup="from __main__ import primes", + number=1_000_000, + ) + ) + print( + timeit( + "fast_primes(1_000_000_000_000)", + setup="from __main__ import fast_primes", + number=1_000_000, + ) + ) From 8e857e8692bf8e07112dedb7042bdab1ecb1d20e Mon Sep 17 00:00:00 2001 From: Leoriem-code <73761711+Leoriem-code@users.noreply.github.com> Date: Tue, 26 Oct 2021 09:57:49 +0200 Subject: [PATCH 126/726] add implementation of Nagel and Schrekenberg algo (#5584) * add implementation of Nagel and Schrekenberg algo * Update cellular_automata/nasch.py Co-authored-by: Christian Clauss * Update nasch.py * Update and rename nasch.py to nagel_schrekenberg.py * Update cellular_automata/nagel_schrekenberg.py Co-authored-by: Christian Clauss * Update nagel_schrekenberg.py * Update nagel_schrekenberg.py * Update nagel_schrekenberg.py * update nagel_schrekenberg.py * Update nagel_schrekenberg.py Co-authored-by: Christian Clauss --- cellular_automata/nagel_schrekenberg.py | 140 ++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 cellular_automata/nagel_schrekenberg.py diff --git a/cellular_automata/nagel_schrekenberg.py b/cellular_automata/nagel_schrekenberg.py new file mode 100644 index 000000000..be44761ec --- /dev/null +++ b/cellular_automata/nagel_schrekenberg.py @@ -0,0 +1,140 @@ +""" +Simulate the evolution of a highway with only one road that is a loop. +The highway is divided in cells, each cell can have at most one car in it. +The highway is a loop so when a car comes to one end, it will come out on the other. +Each car is represented by its speed (from 0 to 5). + +Some information about speed: + -1 means that the cell on the highway is empty + 0 to 5 are the speed of the cars with 0 being the lowest and 5 the highest + +highway: list[int] Where every position and speed of every car will be stored +probability The probability that a driver will slow down +initial_speed The speed of the cars a the start +frequency How many cells there are between two cars at the start +max_speed The maximum speed a car can go to +number_of_cells How many cell are there in the highway +number_of_update How many times will the position be updated + +More information here: https://en.wikipedia.org/wiki/Nagel%E2%80%93Schreckenberg_model + +Examples for doctest: +>>> simulate(construct_highway(6, 3, 0), 2, 0, 2) +[[0, -1, -1, 0, -1, -1], [-1, 1, -1, -1, 1, -1], [-1, -1, 1, -1, -1, 1]] +>>> simulate(construct_highway(5, 2, -2), 3, 0, 2) +[[0, -1, 0, -1, 0], [0, -1, 0, -1, -1], [0, -1, -1, 1, -1], [-1, 1, -1, 0, -1]] +""" +from random import randint, random + + +def construct_highway( + number_of_cells: int, + frequency: int, + initial_speed: int, + random_frequency: bool = False, + random_speed: bool = False, + max_speed: int = 5, +) -> list: + """ + Build the highway following the parameters given + >>> construct_highway(10, 2, 6) + [[6, -1, 6, -1, 6, -1, 6, -1, 6, -1]] + >>> construct_highway(10, 10, 2) + [[2, -1, -1, -1, -1, -1, -1, -1, -1, -1]] + """ + + highway = [[-1] * number_of_cells] # Create a highway without any car + i = 0 + if initial_speed < 0: + initial_speed = 0 + while i < number_of_cells: + highway[0][i] = ( + randint(0, max_speed) if random_speed else initial_speed + ) # Place the cars + i += ( + randint(1, max_speed * 2) if random_frequency else frequency + ) # Arbitrary number, may need tuning + return highway + + +def get_distance(highway_now: list, car_index: int) -> int: + """ + Get the distance between a car (at index car_index) and the next car + >>> get_distance([6, -1, 6, -1, 6], 2) + 1 + >>> get_distance([2, -1, -1, -1, 3, 1, 0, 1, 3, 2], 0) + 3 + >>> get_distance([-1, -1, -1, -1, 2, -1, -1, -1, 3], -1) + 4 + """ + + distance = 0 + cells = highway_now[car_index + 1 :] + for cell in range(len(cells)): # May need a better name for this + if cells[cell] != -1: # If the cell is not empty then + return distance # we have the distance we wanted + distance += 1 + # Here if the car is near the end of the highway + return distance + get_distance(highway_now, -1) + + +def update(highway_now: list, probability: float, max_speed: int) -> list: + """ + Update the speed of the cars + >>> update([-1, -1, -1, -1, -1, 2, -1, -1, -1, -1, 3], 0.0, 5) + [-1, -1, -1, -1, -1, 3, -1, -1, -1, -1, 4] + >>> update([-1, -1, 2, -1, -1, -1, -1, 3], 0.0, 5) + [-1, -1, 3, -1, -1, -1, -1, 1] + """ + + number_of_cells = len(highway_now) + # Beforce calculations, the highway is empty + next_highway = [-1] * number_of_cells + + for car_index in range(number_of_cells): + if highway_now[car_index] != -1: + # Add 1 to the current speed of the car and cap the speed + next_highway[car_index] = min(highway_now[car_index] + 1, max_speed) + # Number of empty cell before the next car + dn = get_distance(highway_now, car_index) - 1 + # We can't have the car causing an accident + next_highway[car_index] = min(next_highway[car_index], dn) + if random() < probability: + # Randomly, a driver will slow down + next_highway[car_index] = max(next_highway[car_index] - 1, 0) + return next_highway + + +def simulate( + highway: list, number_of_update: int, probability: float, max_speed: int +) -> list: + """ + The main function, it will simulate the evolution of the highway + >>> simulate([[-1, 2, -1, -1, -1, 3]], 2, 0.0, 3) + [[-1, 2, -1, -1, -1, 3], [-1, -1, -1, 2, -1, 0], [1, -1, -1, 0, -1, -1]] + >>> simulate([[-1, 2, -1, 3]], 4, 0.0, 3) + [[-1, 2, -1, 3], [-1, 0, -1, 0], [-1, 0, -1, 0], [-1, 0, -1, 0], [-1, 0, -1, 0]] + """ + + number_of_cells = len(highway[0]) + + for i in range(number_of_update): + next_speeds_calculated = update(highway[i], probability, max_speed) + real_next_speeds = [-1] * number_of_cells + + for car_index in range(number_of_cells): + speed = next_speeds_calculated[car_index] + if speed != -1: + # Change the position based on the speed (with % to create the loop) + index = (car_index + speed) % number_of_cells + # Commit the change of position + real_next_speeds[index] = speed + highway.append(real_next_speeds) + + return highway + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From f93c7d4d80bcad6b4679d09ecefa7cc3874aae54 Mon Sep 17 00:00:00 2001 From: Prakhar Gurunani Date: Tue, 26 Oct 2021 13:35:13 +0530 Subject: [PATCH 127/726] Get user tweets (#5593) * updating DIRECTORY.md * Create get_user_tweets.py * updating DIRECTORY.md * Reformat code with black * Add argument type * Add return type * Add tweepy * Fix isort issues * Fix flake8 issues * WIP: doctest * Doctest setup and format with pre-commit * Remove doctests * Update web_programming/get_user_tweets.py Co-authored-by: Christian Clauss * Update get_user_tweets.py Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss --- DIRECTORY.md | 10 ++++- requirements.txt | 1 + web_programming/get_user_tweets.py | 60 ++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 web_programming/get_user_tweets.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 13a360ab6..e2b2442fd 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -10,6 +10,11 @@ * [Newton Raphson](https://github.com/TheAlgorithms/Python/blob/master/arithmetic_analysis/newton_raphson.py) * [Secant Method](https://github.com/TheAlgorithms/Python/blob/master/arithmetic_analysis/secant_method.py) +## Audio Filters + * [Butterworth Filter](https://github.com/TheAlgorithms/Python/blob/master/audio_filters/butterworth_filter.py) + * [Iir Filter](https://github.com/TheAlgorithms/Python/blob/master/audio_filters/iir_filter.py) + * [Show Response](https://github.com/TheAlgorithms/Python/blob/master/audio_filters/show_response.py) + ## Backtracking * [All Combinations](https://github.com/TheAlgorithms/Python/blob/master/backtracking/all_combinations.py) * [All Permutations](https://github.com/TheAlgorithms/Python/blob/master/backtracking/all_permutations.py) @@ -60,6 +65,7 @@ * [Base64 Encoding](https://github.com/TheAlgorithms/Python/blob/master/ciphers/base64_encoding.py) * [Base85](https://github.com/TheAlgorithms/Python/blob/master/ciphers/base85.py) * [Beaufort Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/beaufort_cipher.py) + * [Bifid](https://github.com/TheAlgorithms/Python/blob/master/ciphers/bifid.py) * [Brute Force Caesar Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/brute_force_caesar_cipher.py) * [Caesar Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/caesar_cipher.py) * [Cryptomath Module](https://github.com/TheAlgorithms/Python/blob/master/ciphers/cryptomath_module.py) @@ -106,8 +112,8 @@ ## Conversions * [Binary To Decimal](https://github.com/TheAlgorithms/Python/blob/master/conversions/binary_to_decimal.py) - * [Binary To Octal](https://github.com/TheAlgorithms/Python/blob/master/conversions/binary_to_octal.py) * [Binary To Hexadecimal](https://github.com/TheAlgorithms/Python/blob/master/conversions/binary_to_hexadecimal.py) + * [Binary To Octal](https://github.com/TheAlgorithms/Python/blob/master/conversions/binary_to_octal.py) * [Decimal To Any](https://github.com/TheAlgorithms/Python/blob/master/conversions/decimal_to_any.py) * [Decimal To Binary](https://github.com/TheAlgorithms/Python/blob/master/conversions/decimal_to_binary.py) * [Decimal To Binary Recursion](https://github.com/TheAlgorithms/Python/blob/master/conversions/decimal_to_binary_recursion.py) @@ -352,6 +358,7 @@ * [Multi Heuristic Astar](https://github.com/TheAlgorithms/Python/blob/master/graphs/multi_heuristic_astar.py) * [Page Rank](https://github.com/TheAlgorithms/Python/blob/master/graphs/page_rank.py) * [Prim](https://github.com/TheAlgorithms/Python/blob/master/graphs/prim.py) + * [Random Graph Generator](https://github.com/TheAlgorithms/Python/blob/master/graphs/random_graph_generator.py) * [Scc Kosaraju](https://github.com/TheAlgorithms/Python/blob/master/graphs/scc_kosaraju.py) * [Strongly Connected Components](https://github.com/TheAlgorithms/Python/blob/master/graphs/strongly_connected_components.py) * [Tarjans Scc](https://github.com/TheAlgorithms/Python/blob/master/graphs/tarjans_scc.py) @@ -978,6 +985,7 @@ * [Fetch Jobs](https://github.com/TheAlgorithms/Python/blob/master/web_programming/fetch_jobs.py) * [Get Imdb Top 250 Movies Csv](https://github.com/TheAlgorithms/Python/blob/master/web_programming/get_imdb_top_250_movies_csv.py) * [Get Imdbtop](https://github.com/TheAlgorithms/Python/blob/master/web_programming/get_imdbtop.py) + * [Get User Tweets](https://github.com/TheAlgorithms/Python/blob/master/web_programming/get_user_tweets.py) * [Giphy](https://github.com/TheAlgorithms/Python/blob/master/web_programming/giphy.py) * [Instagram Crawler](https://github.com/TheAlgorithms/Python/blob/master/web_programming/instagram_crawler.py) * [Instagram Pic](https://github.com/TheAlgorithms/Python/blob/master/web_programming/instagram_pic.py) diff --git a/requirements.txt b/requirements.txt index 4867de26f..7c2672ae2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,5 +14,6 @@ sklearn statsmodels sympy tensorflow +tweepy types-requests xgboost diff --git a/web_programming/get_user_tweets.py b/web_programming/get_user_tweets.py new file mode 100644 index 000000000..0f70201dc --- /dev/null +++ b/web_programming/get_user_tweets.py @@ -0,0 +1,60 @@ +import csv + +import tweepy + +# Twitter API credentials +consumer_key = "" +consumer_secret = "" +access_key = "" +access_secret = "" + + +def get_all_tweets(screen_name: str) -> None: + + # authorize twitter, initialize tweepy + auth = tweepy.OAuthHandler(consumer_key, consumer_secret) + auth.set_access_token(access_key, access_secret) + api = tweepy.API(auth) + + # initialize a list to hold all the tweepy Tweets + alltweets = [] + + # make initial request for most recent tweets (200 is the maximum allowed count) + new_tweets = api.user_timeline(screen_name=screen_name, count=200) + + # save most recent tweets + alltweets.extend(new_tweets) + + # save the id of the oldest tweet less one + oldest = alltweets[-1].id - 1 + + # keep grabbing tweets until there are no tweets left to grab + while len(new_tweets) > 0: + print(f"getting tweets before {oldest}") + + # all subsiquent requests use the max_id param to prevent duplicates + new_tweets = api.user_timeline( + screen_name=screen_name, count=200, max_id=oldest + ) + + # save most recent tweets + alltweets.extend(new_tweets) + + # update the id of the oldest tweet less one + oldest = alltweets[-1].id - 1 + + print(f"...{len(alltweets)} tweets downloaded so far") + + # transform the tweepy tweets into a 2D array that will populate the csv + outtweets = [[tweet.id_str, tweet.created_at, tweet.text] for tweet in alltweets] + + # write the csv + with open(f"new_{screen_name}_tweets.csv", "w") as f: + writer = csv.writer(f) + writer.writerow(["id", "created_at", "text"]) + writer.writerows(outtweets) + + +if __name__ == "__main__": + # pass in the username of the account you want to download + get_all_tweets("FirePing32") From 2606f1bbe58dfc370ce1f35d3d9c51396e791fa6 Mon Sep 17 00:00:00 2001 From: Andrew Grangaard Date: Tue, 26 Oct 2021 02:50:36 -0700 Subject: [PATCH 128/726] [mypy-fix] Type fixes for graham_scan (#5589) * [mypy] Fixes type annotations in other/graham_scan #4052 + Prefer tuple to list for point x,y pairs * NOP: fixes typo in comment --- other/graham_scan.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/other/graham_scan.py b/other/graham_scan.py index 67c5cd8ab..91bb6812f 100644 --- a/other/graham_scan.py +++ b/other/graham_scan.py @@ -14,7 +14,7 @@ from math import atan2, degrees from sys import maxsize -def graham_scan(points: list[list[int, int]]) -> list[list[int, int]]: +def graham_scan(points: list[tuple[int, int]]) -> list[tuple[int, int]]: """Pure implementation of graham scan algorithm in Python :param points: The unique points on coordinates. @@ -57,7 +57,7 @@ def graham_scan(points: list[list[int, int]]) -> list[list[int, int]]: # remove the lowest and the most left point from points for preparing for sort points.pop(minidx) - def angle_comparer(point: list[int, int], minx: int, miny: int) -> float: + def angle_comparer(point: tuple[int, int], minx: int, miny: int) -> float: """Return the angle toward to point from (minx, miny) :param point: The target point @@ -66,13 +66,13 @@ def graham_scan(points: list[list[int, int]]) -> list[list[int, int]]: :return: the angle Examples: - >>> angle_comparer([1,1], 0, 0) + >>> angle_comparer((1,1), 0, 0) 45.0 - >>> angle_comparer([100,1], 10, 10) + >>> angle_comparer((100,1), 10, 10) -5.710593137499642 - >>> angle_comparer([5,5], 2, 3) + >>> angle_comparer((5,5), 2, 3) 33.690067525979785 """ # sort the points accorgind to the angle from the lowest and the most left point @@ -83,7 +83,7 @@ def graham_scan(points: list[list[int, int]]) -> list[list[int, int]]: sorted_points = sorted(points, key=lambda point: angle_comparer(point, minx, miny)) # This insert actually costs complexity, - # and you should insteadly add (minx, miny) into stack later. + # and you should instead add (minx, miny) into stack later. # I'm using insert just for easy understanding. sorted_points.insert(0, (minx, miny)) @@ -95,7 +95,7 @@ def graham_scan(points: list[list[int, int]]) -> list[list[int, int]]: right = 3 def check_direction( - starting: list[int, int], via: list[int, int], target: list[int, int] + starting: tuple[int, int], via: tuple[int, int], target: tuple[int, int] ) -> Direction: """Return the direction toward to the line from via to target from starting @@ -105,13 +105,13 @@ def graham_scan(points: list[list[int, int]]) -> list[list[int, int]]: :return: the Direction Examples: - >>> check_direction([1,1], [2,2], [3,3]) + >>> check_direction((1,1), (2,2), (3,3)) Direction.straight - >>> check_direction([60,1], [-50,199], [30,2]) + >>> check_direction((60,1), (-50,199), (30,2)) Direction.left - >>> check_direction([0,0], [5,5], [10,0]) + >>> check_direction((0,0), (5,5), (10,0)) Direction.right """ x0, y0 = starting @@ -132,12 +132,12 @@ def graham_scan(points: list[list[int, int]]) -> list[list[int, int]]: # If they are same, it means they are on a same line of convex hull. if target_angle > via_angle: return Direction.left - if target_angle == via_angle: + elif target_angle == via_angle: return Direction.straight - if target_angle < via_angle: + else: return Direction.right - stack = deque() + stack: deque[tuple[int, int]] = deque() stack.append(sorted_points[0]) stack.append(sorted_points[1]) stack.append(sorted_points[2]) From de07245c170f2007cef415fa4114be870078988e Mon Sep 17 00:00:00 2001 From: Andrew Grangaard Date: Tue, 26 Oct 2021 03:10:37 -0700 Subject: [PATCH 129/726] [mypy] Adds type annotations in other/activity_selection #4052 (#5590) --- other/activity_selection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/other/activity_selection.py b/other/activity_selection.py index c03956cce..d809bf90a 100644 --- a/other/activity_selection.py +++ b/other/activity_selection.py @@ -10,7 +10,7 @@ single person, one at a time""" # finish[] --> An array that contains finish time of all activities -def printMaxActivities(start, finish): +def printMaxActivities(start: list[int], finish: list[int]) -> None: """ >>> start = [1, 3, 0, 5, 8, 5] >>> finish = [2, 4, 6, 7, 9, 9] From e49d8e3af427353c18fe5f1afb0927e3e8d6461c Mon Sep 17 00:00:00 2001 From: Erwin Junge Date: Tue, 26 Oct 2021 12:29:27 +0200 Subject: [PATCH 130/726] [mypy] annotate `compression` (#5570) --- compression/burrows_wheeler.py | 12 +++++- compression/huffman.py | 48 ++++++++++++----------- compression/lempel_ziv.py | 4 +- compression/peak_signal_to_noise_ratio.py | 4 +- 4 files changed, 40 insertions(+), 28 deletions(-) diff --git a/compression/burrows_wheeler.py b/compression/burrows_wheeler.py index 7d705af74..4ad99a642 100644 --- a/compression/burrows_wheeler.py +++ b/compression/burrows_wheeler.py @@ -12,6 +12,13 @@ of text compression algorithms, costing only some extra computation. """ from __future__ import annotations +from typing import TypedDict + + +class BWTTransformDict(TypedDict): + bwt_string: str + idx_original_string: int + def all_rotations(s: str) -> list[str]: """ @@ -43,7 +50,7 @@ def all_rotations(s: str) -> list[str]: return [s[i:] + s[:i] for i in range(len(s))] -def bwt_transform(s: str) -> dict: +def bwt_transform(s: str) -> BWTTransformDict: """ :param s: The string that will be used at bwt algorithm :return: the string composed of the last char of each row of the ordered @@ -75,10 +82,11 @@ def bwt_transform(s: str) -> dict: rotations = all_rotations(s) rotations.sort() # sort the list of rotations in alphabetically order # make a string composed of the last char of each rotation - return { + response: BWTTransformDict = { "bwt_string": "".join([word[-1] for word in rotations]), "idx_original_string": rotations.index(s), } + return response def reverse_bwt(bwt_string: str, idx_original_string: int) -> str: diff --git a/compression/huffman.py b/compression/huffman.py index 8f37a53ce..d5d78b753 100644 --- a/compression/huffman.py +++ b/compression/huffman.py @@ -1,29 +1,31 @@ +from __future__ import annotations + import sys class Letter: - def __init__(self, letter, freq): - self.letter = letter - self.freq = freq - self.bitstring = {} + def __init__(self, letter: str, freq: int): + self.letter: str = letter + self.freq: int = freq + self.bitstring: dict[str, str] = {} - def __repr__(self): + def __repr__(self) -> str: return f"{self.letter}:{self.freq}" class TreeNode: - def __init__(self, freq, left, right): - self.freq = freq - self.left = left - self.right = right + def __init__(self, freq: int, left: Letter | TreeNode, right: Letter | TreeNode): + self.freq: int = freq + self.left: Letter | TreeNode = left + self.right: Letter | TreeNode = right -def parse_file(file_path): +def parse_file(file_path: str) -> list[Letter]: """ Read the file and build a dict of all letters and their frequencies, then convert the dict into a list of Letters. """ - chars = {} + chars: dict[str, int] = {} with open(file_path) as f: while True: c = f.read(1) @@ -33,22 +35,23 @@ def parse_file(file_path): return sorted((Letter(c, f) for c, f in chars.items()), key=lambda l: l.freq) -def build_tree(letters): +def build_tree(letters: list[Letter]) -> Letter | TreeNode: """ Run through the list of Letters and build the min heap for the Huffman Tree. """ - while len(letters) > 1: - left = letters.pop(0) - right = letters.pop(0) + response: list[Letter | TreeNode] = letters # type: ignore + while len(response) > 1: + left = response.pop(0) + right = response.pop(0) total_freq = left.freq + right.freq node = TreeNode(total_freq, left, right) - letters.append(node) - letters.sort(key=lambda l: l.freq) - return letters[0] + response.append(node) + response.sort(key=lambda l: l.freq) + return response[0] -def traverse_tree(root, bitstring): +def traverse_tree(root: Letter | TreeNode, bitstring: str) -> list[Letter]: """ Recursively traverse the Huffman Tree to set each Letter's bitstring dictionary, and return the list of Letters @@ -56,13 +59,14 @@ def traverse_tree(root, bitstring): if type(root) is Letter: root.bitstring[root.letter] = bitstring return [root] + treenode: TreeNode = root # type: ignore letters = [] - letters += traverse_tree(root.left, bitstring + "0") - letters += traverse_tree(root.right, bitstring + "1") + letters += traverse_tree(treenode.left, bitstring + "0") + letters += traverse_tree(treenode.right, bitstring + "1") return letters -def huffman(file_path): +def huffman(file_path: str) -> None: """ Parse the file, build the tree, then run through the file again, using the letters dictionary to find and print out the diff --git a/compression/lempel_ziv.py b/compression/lempel_ziv.py index 6743dc42d..ea6f33944 100644 --- a/compression/lempel_ziv.py +++ b/compression/lempel_ziv.py @@ -26,7 +26,7 @@ def read_file_binary(file_path: str) -> str: def add_key_to_lexicon( - lexicon: dict, curr_string: str, index: int, last_match_id: str + lexicon: dict[str, str], curr_string: str, index: int, last_match_id: str ) -> None: """ Adds new strings (curr_string + "0", curr_string + "1") to the lexicon @@ -110,7 +110,7 @@ def write_file_binary(file_path: str, to_write: str) -> None: sys.exit() -def compress(source_path, destination_path: str) -> None: +def compress(source_path: str, destination_path: str) -> None: """ Reads source file, compresses it and writes the compressed result in destination file diff --git a/compression/peak_signal_to_noise_ratio.py b/compression/peak_signal_to_noise_ratio.py index 6c6c4c38a..dded2a712 100644 --- a/compression/peak_signal_to_noise_ratio.py +++ b/compression/peak_signal_to_noise_ratio.py @@ -12,7 +12,7 @@ import cv2 import numpy as np -def psnr(original, contrast): +def psnr(original: float, contrast: float) -> float: mse = np.mean((original - contrast) ** 2) if mse == 0: return 100 @@ -21,7 +21,7 @@ def psnr(original, contrast): return PSNR -def main(): +def main() -> None: dir_path = os.path.dirname(os.path.realpath(__file__)) # Loading images (original image and compressed image) original = cv2.imread(os.path.join(dir_path, "image_data/original_image.png")) From 700398ec063687b661e9be865f5c32d3c822fca1 Mon Sep 17 00:00:00 2001 From: Erwin Junge Date: Tue, 26 Oct 2021 12:35:21 +0200 Subject: [PATCH 131/726] [mypy] annotate `ciphers` (#5569) * [mypy] annotate `ciphers` * Update ciphers/polybius.py * Update polybius.py Co-authored-by: Christian Clauss --- ciphers/decrypt_caesar_with_chi_squared.py | 11 +++++++---- ciphers/polybius.py | 3 +-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ciphers/decrypt_caesar_with_chi_squared.py b/ciphers/decrypt_caesar_with_chi_squared.py index 89477914a..beac851b6 100644 --- a/ciphers/decrypt_caesar_with_chi_squared.py +++ b/ciphers/decrypt_caesar_with_chi_squared.py @@ -221,10 +221,13 @@ def decrypt_caesar_with_chi_squared( # Get the most likely cipher by finding the cipher with the smallest chi squared # statistic - most_likely_cipher: int = min( # type: ignore - chi_squared_statistic_values, # type: ignore - key=chi_squared_statistic_values.get, # type: ignore - ) # type: ignore + def chi_squared_statistic_values_sorting_key(key: int) -> tuple[float, str]: + return chi_squared_statistic_values[key] + + most_likely_cipher: int = min( + chi_squared_statistic_values, + key=chi_squared_statistic_values_sorting_key, + ) # Get all the data from the most likely cipher (key, decoded message) ( diff --git a/ciphers/polybius.py b/ciphers/polybius.py index 9e1dc4cbb..2a45f02a3 100644 --- a/ciphers/polybius.py +++ b/ciphers/polybius.py @@ -45,8 +45,7 @@ class PolybiusCipher: >>> PolybiusCipher().numbers_to_letter(1, 1) == "a" True """ - letter = self.SQUARE[index1 - 1, index2 - 1] - return letter + return self.SQUARE[index1 - 1, index2 - 1] def encode(self, message: str) -> str: """ From 366a0f18397427b61979ea27f7497718962834d8 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 26 Oct 2021 14:32:34 +0200 Subject: [PATCH 132/726] Fix validate_initial_digits of credit_card_validator.py (#5600) * Fix validate_initial_digits of credit_card_validator.py @Bhargavishnu I think that I broke the logic of validate_initial_digits which should require that credit_card_number[0] is 3 before checking that credit_card_number[1] is 4, 5, or 7. Please verify the new changes and the new test cases to make sure that this is correct. Thanks! * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 2 ++ strings/credit_card_validator.py | 6 ++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index e2b2442fd..f765b29b6 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -944,6 +944,7 @@ * [Capitalize](https://github.com/TheAlgorithms/Python/blob/master/strings/capitalize.py) * [Check Anagrams](https://github.com/TheAlgorithms/Python/blob/master/strings/check_anagrams.py) * [Check Pangram](https://github.com/TheAlgorithms/Python/blob/master/strings/check_pangram.py) + * [Credit Card Validator](https://github.com/TheAlgorithms/Python/blob/master/strings/credit_card_validator.py) * [Detecting English Programmatically](https://github.com/TheAlgorithms/Python/blob/master/strings/detecting_english_programmatically.py) * [Frequency Finder](https://github.com/TheAlgorithms/Python/blob/master/strings/frequency_finder.py) * [Indian Phone Validator](https://github.com/TheAlgorithms/Python/blob/master/strings/indian_phone_validator.py) @@ -961,6 +962,7 @@ * [Rabin Karp](https://github.com/TheAlgorithms/Python/blob/master/strings/rabin_karp.py) * [Remove Duplicate](https://github.com/TheAlgorithms/Python/blob/master/strings/remove_duplicate.py) * [Reverse Letters](https://github.com/TheAlgorithms/Python/blob/master/strings/reverse_letters.py) + * [Reverse Long Words](https://github.com/TheAlgorithms/Python/blob/master/strings/reverse_long_words.py) * [Reverse Words](https://github.com/TheAlgorithms/Python/blob/master/strings/reverse_words.py) * [Split](https://github.com/TheAlgorithms/Python/blob/master/strings/split.py) * [Upper](https://github.com/TheAlgorithms/Python/blob/master/strings/upper.py) diff --git a/strings/credit_card_validator.py b/strings/credit_card_validator.py index 3b5a1aae6..3a08c4117 100644 --- a/strings/credit_card_validator.py +++ b/strings/credit_card_validator.py @@ -11,13 +11,11 @@ def validate_initial_digits(credit_card_number: str) -> bool: >>> valid = "4111111111111111 41111111111111 34 35 37 412345 523456 634567" >>> all(validate_initial_digits(cc) for cc in valid.split()) True - >>> invalid = "32323 36111111111111" + >>> invalid = "14 25 76 32323 36111111111111" >>> all(validate_initial_digits(cc) is False for cc in invalid.split()) True """ - if len(credit_card_number) < 2: - return False - return credit_card_number[0] in "456" or credit_card_number[1] in "457" + return credit_card_number.startswith(("34", "35", "37", "4", "5", "6")) def luhn_validation(credit_card_number: str) -> bool: From 827b8f04a4f8090f0a8b42f7685a6b510996e5a3 Mon Sep 17 00:00:00 2001 From: Prakhar Gurunani Date: Tue, 26 Oct 2021 18:43:23 +0530 Subject: [PATCH 133/726] Get top 10 HN posts (#5604) * updating DIRECTORY.md * updating DIRECTORY.md * Create get_top_hn_posts.py * updating DIRECTORY.md * Add return type and desc * Add texttable * Update web_programming/get_top_hn_posts.py Co-authored-by: Christian Clauss * Update web_programming/get_top_hn_posts.py Co-authored-by: Christian Clauss * Get top 10 posts * Update get_top_hn_posts.py * Don't use texttable * Setup doctest * Fix pre-commit issues * Remove print statement * Add hackernews_top_stories_as_markdown() Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss --- DIRECTORY.md | 2 ++ requirements.txt | 1 + web_programming/get_top_hn_posts.py | 26 ++++++++++++++++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 web_programming/get_top_hn_posts.py diff --git a/DIRECTORY.md b/DIRECTORY.md index f765b29b6..67f2113ea 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -53,6 +53,7 @@ ## Cellular Automata * [Conways Game Of Life](https://github.com/TheAlgorithms/Python/blob/master/cellular_automata/conways_game_of_life.py) * [Game Of Life](https://github.com/TheAlgorithms/Python/blob/master/cellular_automata/game_of_life.py) + * [Nagel Schrekenberg](https://github.com/TheAlgorithms/Python/blob/master/cellular_automata/nagel_schrekenberg.py) * [One Dimensional](https://github.com/TheAlgorithms/Python/blob/master/cellular_automata/one_dimensional.py) ## Ciphers @@ -987,6 +988,7 @@ * [Fetch Jobs](https://github.com/TheAlgorithms/Python/blob/master/web_programming/fetch_jobs.py) * [Get Imdb Top 250 Movies Csv](https://github.com/TheAlgorithms/Python/blob/master/web_programming/get_imdb_top_250_movies_csv.py) * [Get Imdbtop](https://github.com/TheAlgorithms/Python/blob/master/web_programming/get_imdbtop.py) + * [Get Top Hn Posts](https://github.com/TheAlgorithms/Python/blob/master/web_programming/get_top_hn_posts.py) * [Get User Tweets](https://github.com/TheAlgorithms/Python/blob/master/web_programming/get_user_tweets.py) * [Giphy](https://github.com/TheAlgorithms/Python/blob/master/web_programming/giphy.py) * [Instagram Crawler](https://github.com/TheAlgorithms/Python/blob/master/web_programming/instagram_crawler.py) diff --git a/requirements.txt b/requirements.txt index 7c2672ae2..c28238a07 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,6 +14,7 @@ sklearn statsmodels sympy tensorflow +texttable tweepy types-requests xgboost diff --git a/web_programming/get_top_hn_posts.py b/web_programming/get_top_hn_posts.py new file mode 100644 index 000000000..fbb7c051a --- /dev/null +++ b/web_programming/get_top_hn_posts.py @@ -0,0 +1,26 @@ +from __future__ import annotations + +import requests + + +def get_hackernews_story(story_id: str) -> dict: + url = f"https://hacker-news.firebaseio.com/v0/item/{story_id}.json?print=pretty" + return requests.get(url).json() + + +def hackernews_top_stories(max_stories: int = 10) -> list[dict]: + """ + Get the top max_stories posts from HackerNews - https://news.ycombinator.com/ + """ + url = "https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty" + story_ids = requests.get(url).json()[:max_stories] + return [get_hackernews_story(story_id) for story_id in story_ids] + + +def hackernews_top_stories_as_markdown(max_stories: int = 10) -> str: + stories = hackernews_top_stories(max_stories) + return "\n".join("* [{title}]({url})".format(**story) for story in stories) + + +if __name__ == "__main__": + print(hackernews_top_stories_as_markdown()) From 6fcefc04535357776124806f0fac40c005b35d1a Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj Date: Tue, 26 Oct 2021 18:53:38 +0530 Subject: [PATCH 134/726] Add decode function to base16.py (#5575) * Add decode function * Update base16.py * Update base16.py * Update base16.py * Made the line shorter * Made another line shorter --- ciphers/base16.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/ciphers/base16.py b/ciphers/base16.py index f27ea4628..1ef60868d 100644 --- a/ciphers/base16.py +++ b/ciphers/base16.py @@ -4,6 +4,7 @@ import base64 def encode_to_b16(inp: str) -> bytes: """ Encodes a given utf-8 string into base-16. + >>> encode_to_b16('Hello World!') b'48656C6C6F20576F726C6421' >>> encode_to_b16('HELLO WORLD!') @@ -11,9 +12,23 @@ def encode_to_b16(inp: str) -> bytes: >>> encode_to_b16('') b'' """ - encoded = inp.encode("utf-8") # encoded the input (we need a bytes like object) - b16encoded = base64.b16encode(encoded) # b16encoded the encoded string - return b16encoded + # encode the input into a bytes-like object and then encode b16encode that + return base64.b16encode(inp.encode("utf-8")) + + +def decode_from_b16(b16encoded: bytes) -> str: + """ + Decodes from base-16 to a utf-8 string. + + >>> decode_from_b16(b'48656C6C6F20576F726C6421') + 'Hello World!' + >>> decode_from_b16(b'48454C4C4F20574F524C4421') + 'HELLO WORLD!' + >>> decode_from_b16(b'') + '' + """ + # b16decode the input into bytes and decode that into a human readable string + return base64.b16decode(b16encoded).decode("utf-8") if __name__ == "__main__": From 23f43afee5f7ee3a2bc60ad2997644c54b23bba7 Mon Sep 17 00:00:00 2001 From: Sabari Ganesh <64348740+SabariGanesh-K@users.noreply.github.com> Date: Tue, 26 Oct 2021 21:27:59 +0530 Subject: [PATCH 135/726] Added volume conversions (#5607) * Added volume conversions This is a file which has relevant function which helps in conversion between volume units. Available Units:- Cubic metre,Litre,KiloLitre,Gallon,Cubic yard,Cubic foot,cup The file is also written in a way that , adding a new unit can easily be done by modifying tuple available in the source code * Formatted file The file was formatted to follow the syntax formatting rules of the repo * Formatted file further --- conversions/volume_conversions.py | 79 +++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 conversions/volume_conversions.py diff --git a/conversions/volume_conversions.py b/conversions/volume_conversions.py new file mode 100644 index 000000000..de2290196 --- /dev/null +++ b/conversions/volume_conversions.py @@ -0,0 +1,79 @@ +""" +Conversion of volume units. +Available Units:- Cubic metre,Litre,KiloLitre,Gallon,Cubic yard,Cubic foot,cup +USAGE : +-> Import this file into their respective project. +-> Use the function length_conversion() for conversion of volume units. +-> Parameters : + -> value : The number of from units you want to convert + -> from_type : From which type you want to convert + -> to_type : To which type you want to convert +REFERENCES : +-> Wikipedia reference: https://en.wikipedia.org/wiki/Cubic_metre +-> Wikipedia reference: https://en.wikipedia.org/wiki/Litre +-> Wikipedia reference: https://en.wiktionary.org/wiki/kilolitre +-> Wikipedia reference: https://en.wikipedia.org/wiki/Gallon +-> Wikipedia reference: https://en.wikipedia.org/wiki/Cubic_yard +-> Wikipedia reference: https://en.wikipedia.org/wiki/Cubic_foot +-> Wikipedia reference: https://en.wikipedia.org/wiki/Cup_(unit) +""" + +from collections import namedtuple + +from_to = namedtuple("from_to", "from_ to") + +METRIC_CONVERSION = { + "cubicmeter": from_to(1, 1), + "litre": from_to(0.001, 1000), + "kilolitre": from_to(1, 1), + "gallon": from_to(0.00454, 264.172), + "cubicyard": from_to(0.76455, 1.30795), + "cubicfoot": from_to(0.028, 35.3147), + "cup": from_to(0.000236588, 4226.75), +} + + +def volume_conversion(value: float, from_type: str, to_type: str) -> float: + """ + Conversion between volume units. + >>> volume_conversion(4, "cubicmeter", "litre") + 4000 + >>> volume_conversion(1, "litre", "gallon") + 0.264172 + >>> volume_conversion(1, "kilolitre", "cubicmeter") + 1 + >>> volume_conversion(3, "gallon", "cubicyard") + 0.017814279 + >>> volume_conversion(2, "cubicyard", "litre") + 1529.1 + >>> volume_conversion(4, "cubicfoot", "cup") + 473.396 + >>> volume_conversion(1, "cup", "kilolitre") + 0.000236588 + >>> volume_conversion(4, "wrongUnit", "litre") + Traceback (most recent call last): + File "/usr/lib/python3.8/doctest.py", line 1336, in __run + exec(compile(example.source, filename, "single", + File "", line 1, in + volume_conversion(4, "wrongUnit", "litre") + File "", line 62, in volume_conversion + ValueError: Invalid 'from_type' value: 'wrongUnit' Supported values are: + cubicmeter, litre, kilolitre, gallon, cubicyard, cubicfoot, cup + """ + if from_type not in METRIC_CONVERSION: + raise ValueError( + f"Invalid 'from_type' value: {from_type!r} Supported values are:\n" + + ", ".join(METRIC_CONVERSION) + ) + if to_type not in METRIC_CONVERSION: + raise ValueError( + f"Invalid 'to_type' value: {to_type!r}. Supported values are:\n" + + ", ".join(METRIC_CONVERSION) + ) + return value * METRIC_CONVERSION[from_type].from_ * METRIC_CONVERSION[to_type].to + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From c41bb49fc05339b6c9fbfe4c025946602b4bb919 Mon Sep 17 00:00:00 2001 From: Tarcisio Bruni Rangel Date: Tue, 26 Oct 2021 13:19:00 -0300 Subject: [PATCH 136/726] Financials (#5585) * feat: creates math calculations for financials * refactor: make pull request items requirements * refactor: provides type hint for parameters * refactor: applies code review suggestions * refactor: adds more examples tests * refactor: throws ValueError instead of Exception * refactor: fix formatting * refactor: fix formatting * Update interest.py * Update and rename financials/ABOUT.md to financial/ABOUT.md * Rename financials/__init__.py to financial/__init__.py * Rename financials/interest.py to financial/interest.py * https://www.investopedia.com * Update __init__.py * pre-commit: Disable end-of-file-fixer * Revert change to pre-commit * Update __init__.py * __init__.py Co-authored-by: Christian Clauss Co-authored-by: John Law --- financial/ABOUT.md | 4 +++ financial/__init__.py | 0 financial/interest.py | 83 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 financial/ABOUT.md create mode 100644 financial/__init__.py create mode 100644 financial/interest.py diff --git a/financial/ABOUT.md b/financial/ABOUT.md new file mode 100644 index 000000000..f6b0647f8 --- /dev/null +++ b/financial/ABOUT.md @@ -0,0 +1,4 @@ +### Interest + +* Compound Interest: "Compound interest is calculated by multiplying the initial principal amount by one plus the annual interest rate raised to the number of compound periods minus one." [Compound Interest](https://www.investopedia.com/) +* Simple Interest: "Simple interest paid or received over a certain period is a fixed percentage of the principal amount that was borrowed or lent. " [Simple Interest](https://www.investopedia.com/) diff --git a/financial/__init__.py b/financial/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/financial/interest.py b/financial/interest.py new file mode 100644 index 000000000..394da2bc9 --- /dev/null +++ b/financial/interest.py @@ -0,0 +1,83 @@ +# https://www.investopedia.com + +from __future__ import annotations + + +def simple_interest( + principle: float, daily_interest_rate: float, days_between_payments: int +) -> float: + """ + >>> simple_interest(18000.0, 0.06, 3) + 3240.0 + >>> simple_interest(0.5, 0.06, 3) + 0.09 + >>> simple_interest(18000.0, 0.01, 10) + 1800.0 + >>> simple_interest(18000.0, 0.0, 3) + 0.0 + >>> simple_interest(5500.0, 0.01, 100) + 5500.0 + >>> simple_interest(10000.0, -0.06, 3) + Traceback (most recent call last): + ... + ValueError: daily_interest_rate must be >= 0 + >>> simple_interest(-10000.0, 0.06, 3) + Traceback (most recent call last): + ... + ValueError: principle must be > 0 + >>> simple_interest(5500.0, 0.01, -5) + Traceback (most recent call last): + ... + ValueError: days_between_payments must be > 0 + """ + if days_between_payments <= 0: + raise ValueError("days_between_payments must be > 0") + if daily_interest_rate < 0: + raise ValueError("daily_interest_rate must be >= 0") + if principle <= 0: + raise ValueError("principle must be > 0") + return principle * daily_interest_rate * days_between_payments + + +def compound_interest( + principle: float, + nominal_annual_interest_rate_percentage: float, + number_of_compounding_periods: int, +) -> float: + """ + >>> compound_interest(10000.0, 0.05, 3) + 1576.2500000000014 + >>> compound_interest(10000.0, 0.05, 1) + 500.00000000000045 + >>> compound_interest(0.5, 0.05, 3) + 0.07881250000000006 + >>> compound_interest(10000.0, 0.06, -4) + Traceback (most recent call last): + ... + ValueError: number_of_compounding_periods must be > 0 + >>> compound_interest(10000.0, -3.5, 3.0) + Traceback (most recent call last): + ... + ValueError: nominal_annual_interest_rate_percentage must be >= 0 + >>> compound_interest(-5500.0, 0.01, 5) + Traceback (most recent call last): + ... + ValueError: principle must be > 0 + """ + if number_of_compounding_periods <= 0: + raise ValueError("number_of_compounding_periods must be > 0") + if nominal_annual_interest_rate_percentage < 0: + raise ValueError("nominal_annual_interest_rate_percentage must be >= 0") + if principle <= 0: + raise ValueError("principle must be > 0") + + return principle * ( + (1 + nominal_annual_interest_rate_percentage) ** number_of_compounding_periods + - 1 + ) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From cb4dc197238e670d150eaebd8f387670f7a54377 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 26 Oct 2021 18:41:32 +0200 Subject: [PATCH 137/726] Financial: principle -> principal (#5614) * Financial: principle -> principal The originally invested amount of money: `principal` -- https://www.grammarly.com/blog/principle-principal/ * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 4 ++++ financial/interest.py | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 67f2113ea..6fbd5e2cc 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -129,6 +129,7 @@ * [Rgb Hsv Conversion](https://github.com/TheAlgorithms/Python/blob/master/conversions/rgb_hsv_conversion.py) * [Roman Numerals](https://github.com/TheAlgorithms/Python/blob/master/conversions/roman_numerals.py) * [Temperature Conversions](https://github.com/TheAlgorithms/Python/blob/master/conversions/temperature_conversions.py) + * [Volume Conversions](https://github.com/TheAlgorithms/Python/blob/master/conversions/volume_conversions.py) * [Weight Conversion](https://github.com/TheAlgorithms/Python/blob/master/conversions/weight_conversion.py) ## Data Structures @@ -290,6 +291,9 @@ * Tests * [Test Send File](https://github.com/TheAlgorithms/Python/blob/master/file_transfer/tests/test_send_file.py) +## Financial + * [Interest](https://github.com/TheAlgorithms/Python/blob/master/financial/interest.py) + ## Fractals * [Julia Sets](https://github.com/TheAlgorithms/Python/blob/master/fractals/julia_sets.py) * [Koch Snowflake](https://github.com/TheAlgorithms/Python/blob/master/fractals/koch_snowflake.py) diff --git a/financial/interest.py b/financial/interest.py index 394da2bc9..c69c73045 100644 --- a/financial/interest.py +++ b/financial/interest.py @@ -4,7 +4,7 @@ from __future__ import annotations def simple_interest( - principle: float, daily_interest_rate: float, days_between_payments: int + principal: float, daily_interest_rate: float, days_between_payments: int ) -> float: """ >>> simple_interest(18000.0, 0.06, 3) @@ -24,7 +24,7 @@ def simple_interest( >>> simple_interest(-10000.0, 0.06, 3) Traceback (most recent call last): ... - ValueError: principle must be > 0 + ValueError: principal must be > 0 >>> simple_interest(5500.0, 0.01, -5) Traceback (most recent call last): ... @@ -34,13 +34,13 @@ def simple_interest( raise ValueError("days_between_payments must be > 0") if daily_interest_rate < 0: raise ValueError("daily_interest_rate must be >= 0") - if principle <= 0: - raise ValueError("principle must be > 0") - return principle * daily_interest_rate * days_between_payments + if principal <= 0: + raise ValueError("principal must be > 0") + return principal * daily_interest_rate * days_between_payments def compound_interest( - principle: float, + principal: float, nominal_annual_interest_rate_percentage: float, number_of_compounding_periods: int, ) -> float: @@ -62,16 +62,16 @@ def compound_interest( >>> compound_interest(-5500.0, 0.01, 5) Traceback (most recent call last): ... - ValueError: principle must be > 0 + ValueError: principal must be > 0 """ if number_of_compounding_periods <= 0: raise ValueError("number_of_compounding_periods must be > 0") if nominal_annual_interest_rate_percentage < 0: raise ValueError("nominal_annual_interest_rate_percentage must be >= 0") - if principle <= 0: - raise ValueError("principle must be > 0") + if principal <= 0: + raise ValueError("principal must be > 0") - return principle * ( + return principal * ( (1 + nominal_annual_interest_rate_percentage) ** number_of_compounding_periods - 1 ) From 31061aacf2482e7a8521f577b68930716dab21eb Mon Sep 17 00:00:00 2001 From: Connor Bottum Date: Tue, 26 Oct 2021 12:43:46 -0400 Subject: [PATCH 138/726] fix: use `+=` in sorts/recursive_mergesort_array.py (#5019) --- sorts/recursive_mergesort_array.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sorts/recursive_mergesort_array.py b/sorts/recursive_mergesort_array.py index f714d0238..e02c02405 100644 --- a/sorts/recursive_mergesort_array.py +++ b/sorts/recursive_mergesort_array.py @@ -38,23 +38,23 @@ def merge(arr: list[int]) -> list[int]: ): # Runs until the lowers size of the left and right are sorted. if left_array[left_index] < right_array[right_index]: arr[index] = left_array[left_index] - left_index = left_index + 1 + left_index += 1 else: arr[index] = right_array[right_index] - right_index = right_index + 1 - index = index + 1 + right_index += 1 + index += 1 while ( left_index < left_size ): # Adds the left over elements in the left half of the array arr[index] = left_array[left_index] - left_index = left_index + 1 - index = index + 1 + left_index += 1 + index += 1 while ( right_index < right_size ): # Adds the left over elements in the right half of the array arr[index] = right_array[right_index] - right_index = right_index + 1 - index = index + 1 + right_index += 1 + index += 1 return arr From b4036b70f1f51c29d0c94a591e8738ac81d7397a Mon Sep 17 00:00:00 2001 From: Srishtik Bhandarkar <53395406+srishtik2310@users.noreply.github.com> Date: Tue, 26 Oct 2021 22:40:15 +0530 Subject: [PATCH 139/726] Add solution for probelm_686 of project_euler (#5480) * Added solution for probelm_686 of project_euler * Changed documentation and formatting. * Added ref link to optimization logic * Update project_euler/problem_686/sol1.py Co-authored-by: John Law Co-authored-by: John Law --- project_euler/problem_686/__init__.py | 0 project_euler/problem_686/sol1.py | 160 ++++++++++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 project_euler/problem_686/__init__.py create mode 100644 project_euler/problem_686/sol1.py diff --git a/project_euler/problem_686/__init__.py b/project_euler/problem_686/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_686/sol1.py b/project_euler/problem_686/sol1.py new file mode 100644 index 000000000..3b6bdb655 --- /dev/null +++ b/project_euler/problem_686/sol1.py @@ -0,0 +1,160 @@ +""" +Project Euler Problem 686: https://projecteuler.net/problem=686 + +2^7 = 128 is the first power of two whose leading digits are "12". +The next power of two whose leading digits are "12" is 2^80. + +Define p(L,n) to be the nth-smallest value of j such that +the base 10 representation of 2^j begins with the digits of L. + +So p(12, 1) = 7 and p(12, 2) = 80. + +You are given that p(123, 45) = 12710. + +Find p(123, 678910). +""" + +import math + + +def log_difference(number: int) -> float: + """ + This function returns the decimal value of a number multiplied with log(2) + Since the problem is on powers of two, finding the powers of two with + large exponents is time consuming. Hence we use log to reduce compute time. + + We can find out that the first power of 2 with starting digits 123 is 90. + Computing 2^90 is time consuming. + Hence we find log(2^90) = 90*log(2) = 27.092699609758302 + But we require only the decimal part to determine whether the power starts with 123. + SO we just return the decimal part of the log product. + Therefore we return 0.092699609758302 + + >>> log_difference(90) + 0.092699609758302 + >>> log_difference(379) + 0.090368356648852 + + """ + + log_number = math.log(2, 10) * number + difference = round((log_number - int(log_number)), 15) + + return difference + + +def solution(number: int = 678910) -> int: + """ + This function calculates the power of two which is nth (n = number) + smallest value of power of 2 + such that the starting digits of the 2^power is 123. + + For example the powers of 2 for which starting digits is 123 are: + 90, 379, 575, 864, 1060, 1545, 1741, 2030, 2226, 2515 and so on. + 90 is the first power of 2 whose starting digits are 123, + 379 is second power of 2 whose starting digits are 123, + and so on. + + So if number = 10, then solution returns 2515 as we observe from above series. + + Wwe will define a lowerbound and upperbound. + lowerbound = log(1.23), upperbound = log(1.24) + because we need to find the powers that yield 123 as starting digits. + + log(1.23) = 0.08990511143939792, log(1,24) = 0.09342168516223506. + We use 1.23 and not 12.3 or 123, because log(1.23) yields only decimal value + which is less than 1. + log(12.3) will be same decimal vale but 1 added to it + which is log(12.3) = 1.093421685162235. + We observe that decimal value remains same no matter 1.23 or 12.3 + Since we use the function log_difference(), + which returns the value that is only decimal part, using 1.23 is logical. + + If we see, 90*log(2) = 27.092699609758302, + decimal part = 0.092699609758302, which is inside the range of lowerbound + and upperbound. + + If we compute the difference between all the powers which lead to 123 + starting digits is as follows: + + 379 - 90 = 289 + 575 - 379 = 196 + 864 - 575 = 289 + 1060 - 864 = 196 + + We see a pattern here. The difference is either 196 or 289 = 196 + 93. + + Hence to optimize the algorithm we will increment by 196 or 93 depending upon the + log_difference() value. + + Lets take for example 90. + Since 90 is the first power leading to staring digits as 123, + we will increment iterator by 196. + Because the difference between any two powers leading to 123 + as staring digits is greater than or equal to 196. + After incrementing by 196 we get 286. + + log_difference(286) = 0.09457875989861 which is greater than upperbound. + The next power is 379, and we need to add 93 to get there. + The iterator will now become 379, + which is the next power leading to 123 as starting digits. + + Lets take 1060. We increment by 196, we get 1256. + log_difference(1256) = 0.09367455396034, + Which is greater than upperbound hence we increment by 93. Now iterator is 1349. + log_difference(1349) = 0.08946415071057 which is less than lowerbound. + The next power is 1545 and we need to add 196 to get 1545. + + Conditions are as follows: + + 1) If we find a power, whose log_difference() is in the range of + lower and upperbound, we will increment by 196. + which implies that the power is a number which will lead to 123 as starting digits. + 2) If we find a power, whose log_difference() is greater than or equal upperbound, + we will increment by 93. + 3) if log_difference() < lowerbound, we increment by 196. + + Reference to the above logic: + https://math.stackexchange.com/questions/4093970/powers-of-2-starting-with-123-does-a-pattern-exist + + >>> solution(1000) + 284168 + + >>> solution(56000) + 15924915 + + >>> solution(678910) + 193060223 + + """ + + power_iterator = 90 + position = 0 + + lower_limit = math.log(1.23, 10) + upper_limit = math.log(1.24, 10) + previous_power = 0 + + while position < number: + difference = log_difference(power_iterator) + + if difference >= upper_limit: + power_iterator += 93 + + elif difference < lower_limit: + power_iterator += 196 + + else: + previous_power = power_iterator + power_iterator += 196 + position += 1 + + return previous_power + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + + print(f"{solution() = }") From 582f57f41fb9d36ae8fe4d49c98775877b9013b7 Mon Sep 17 00:00:00 2001 From: Sabari Ganesh <64348740+SabariGanesh-K@users.noreply.github.com> Date: Tue, 26 Oct 2021 23:25:41 +0530 Subject: [PATCH 140/726] Added physical pressure units (#5613) * Added physical pressure units This uses tuple pair which stores units required to be converted to respective other units as mentioned. Available Units:- Pascal,Bar,Kilopascal,Megapascal,psi(pound per square inch),inHg(in mercury column),torr,atm * Formatted file File was formatted as per repo rules * Reformatted file :) * Added more reference * More reference added --- conversions/pressure_conversions.py | 85 +++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 conversions/pressure_conversions.py diff --git a/conversions/pressure_conversions.py b/conversions/pressure_conversions.py new file mode 100644 index 000000000..2018080b9 --- /dev/null +++ b/conversions/pressure_conversions.py @@ -0,0 +1,85 @@ +""" +Conversion of pressure units. +Available Units:- Pascal,Bar,Kilopascal,Megapascal,psi(pound per square inch), +inHg(in mercury column),torr,atm +USAGE : +-> Import this file into their respective project. +-> Use the function pressure_conversion() for conversion of pressure units. +-> Parameters : + -> value : The number of from units you want to convert + -> from_type : From which type you want to convert + -> to_type : To which type you want to convert +REFERENCES : +-> Wikipedia reference: https://en.wikipedia.org/wiki/Pascal_(unit) +-> Wikipedia reference: https://en.wikipedia.org/wiki/Pound_per_square_inch +-> Wikipedia reference: https://en.wikipedia.org/wiki/Inch_of_mercury +-> Wikipedia reference: https://en.wikipedia.org/wiki/Torr +-> https://en.wikipedia.org/wiki/Standard_atmosphere_(unit) +-> https://msestudent.com/what-are-the-units-of-pressure/ +-> https://www.unitconverters.net/pressure-converter.html +""" + +from collections import namedtuple + +from_to = namedtuple("from_to", "from_ to") + +PRESSURE_CONVERSION = { + "atm": from_to(1, 1), + "pascal": from_to(0.0000098, 101325), + "bar": from_to(0.986923, 1.01325), + "kilopascal": from_to(0.00986923, 101.325), + "megapascal": from_to(9.86923, 0.101325), + "psi": from_to(0.068046, 14.6959), + "inHg": from_to(0.0334211, 29.9213), + "torr": from_to(0.00131579, 760), +} + + +def pressure_conversion(value: float, from_type: str, to_type: str) -> float: + """ + Conversion between pressure units. + >>> pressure_conversion(4, "atm", "pascal") + 405300 + >>> pressure_conversion(1, "pascal", "psi") + 0.00014401981999999998 + >>> pressure_conversion(1, "bar", "atm") + 0.986923 + >>> pressure_conversion(3, "kilopascal", "bar") + 0.029999991892499998 + >>> pressure_conversion(2, "megapascal", "psi") + 290.074434314 + >>> pressure_conversion(4, "psi", "torr") + 206.85984 + >>> pressure_conversion(1, "inHg", "atm") + 0.0334211 + >>> pressure_conversion(1, "torr", "psi") + 0.019336718261000002 + >>> pressure_conversion(4, "wrongUnit", "atm") + Traceback (most recent call last): + File "/usr/lib/python3.8/doctest.py", line 1336, in __run + exec(compile(example.source, filename, "single", + File "", line 1, in + pressure_conversion(4, "wrongUnit", "atm") + File "", line 67, in pressure_conversion + ValueError: Invalid 'from_type' value: 'wrongUnit' Supported values are: + atm, pascal, bar, kilopascal, megapascal, psi, inHg, torr + """ + if from_type not in PRESSURE_CONVERSION: + raise ValueError( + f"Invalid 'from_type' value: {from_type!r} Supported values are:\n" + + ", ".join(PRESSURE_CONVERSION) + ) + if to_type not in PRESSURE_CONVERSION: + raise ValueError( + f"Invalid 'to_type' value: {to_type!r}. Supported values are:\n" + + ", ".join(PRESSURE_CONVERSION) + ) + return ( + value * PRESSURE_CONVERSION[from_type].from_ * PRESSURE_CONVERSION[to_type].to + ) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From c0ed031b3fcf47736f98dfd89e2588dbffceadde Mon Sep 17 00:00:00 2001 From: Edward Nuno Date: Tue, 26 Oct 2021 11:33:08 -0700 Subject: [PATCH 141/726] Fix type annotations for stack.py (#5566) --- data_structures/stacks/balanced_parentheses.py | 2 +- .../stacks/dijkstras_two_stack_algorithm.py | 4 ++-- .../stacks/infix_to_postfix_conversion.py | 2 +- data_structures/stacks/stack.py | 18 +++++++++++------- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/data_structures/stacks/balanced_parentheses.py b/data_structures/stacks/balanced_parentheses.py index 674f7ea43..3c036c220 100644 --- a/data_structures/stacks/balanced_parentheses.py +++ b/data_structures/stacks/balanced_parentheses.py @@ -14,7 +14,7 @@ def balanced_parentheses(parentheses: str) -> bool: >>> balanced_parentheses("") True """ - stack = Stack() + stack: Stack[str] = Stack() bracket_pairs = {"(": ")", "[": "]", "{": "}"} for bracket in parentheses: if bracket in bracket_pairs: diff --git a/data_structures/stacks/dijkstras_two_stack_algorithm.py b/data_structures/stacks/dijkstras_two_stack_algorithm.py index 8b4668f9f..ba2ca92c7 100644 --- a/data_structures/stacks/dijkstras_two_stack_algorithm.py +++ b/data_structures/stacks/dijkstras_two_stack_algorithm.py @@ -51,8 +51,8 @@ def dijkstras_two_stack_algorithm(equation: str) -> int: """ operators = {"*": op.mul, "/": op.truediv, "+": op.add, "-": op.sub} - operand_stack = Stack() - operator_stack = Stack() + operand_stack: Stack[int] = Stack() + operator_stack: Stack[str] = Stack() for i in equation: if i.isdigit(): diff --git a/data_structures/stacks/infix_to_postfix_conversion.py b/data_structures/stacks/infix_to_postfix_conversion.py index dedba8479..b812d108e 100644 --- a/data_structures/stacks/infix_to_postfix_conversion.py +++ b/data_structures/stacks/infix_to_postfix_conversion.py @@ -38,7 +38,7 @@ def infix_to_postfix(expression_str: str) -> str: """ if not balanced_parentheses(expression_str): raise ValueError("Mismatched parentheses") - stack = Stack() + stack: Stack[str] = Stack() postfix = [] for char in expression_str: if char.isalpha() or char.isdigit(): diff --git a/data_structures/stacks/stack.py b/data_structures/stacks/stack.py index 4bc032f72..d1c73df43 100644 --- a/data_structures/stacks/stack.py +++ b/data_structures/stacks/stack.py @@ -1,5 +1,9 @@ from __future__ import annotations +from typing import Generic, TypeVar + +T = TypeVar("T") + class StackOverflowError(BaseException): pass @@ -9,7 +13,7 @@ class StackUnderflowError(BaseException): pass -class Stack: +class Stack(Generic[T]): """A stack is an abstract data type that serves as a collection of elements with two principal operations: push() and pop(). push() adds an element to the top of the stack, and pop() removes an element from the top @@ -19,7 +23,7 @@ class Stack: """ def __init__(self, limit: int = 10): - self.stack: list[int] = [] + self.stack: list[T] = [] self.limit = limit def __bool__(self) -> bool: @@ -28,13 +32,13 @@ class Stack: def __str__(self) -> str: return str(self.stack) - def push(self, data): + def push(self, data: T) -> None: """Push an element to the top of the stack.""" if len(self.stack) >= self.limit: raise StackOverflowError self.stack.append(data) - def pop(self): + def pop(self) -> T: """ Pop an element off of the top of the stack. @@ -47,7 +51,7 @@ class Stack: raise StackUnderflowError return self.stack.pop() - def peek(self): + def peek(self) -> T: """ Peek at the top-most element of the stack. @@ -71,7 +75,7 @@ class Stack: """Return the size of the stack.""" return len(self.stack) - def __contains__(self, item) -> bool: + def __contains__(self, item: T) -> bool: """Check if item is in stack""" return item in self.stack @@ -80,7 +84,7 @@ def test_stack() -> None: """ >>> test_stack() """ - stack = Stack(10) + stack: Stack[int] = Stack(10) assert bool(stack) is False assert stack.is_empty() is True assert stack.is_full() is False From 9a03919052276bfe83f90a7ba2fe258d20a104e9 Mon Sep 17 00:00:00 2001 From: Edward Nuno Date: Tue, 26 Oct 2021 12:12:46 -0700 Subject: [PATCH 142/726] [mypy] Fix type annotations for stack_using_dll.py (#5577) * Fix mypy annotations for stack_using_dll.py * Replace Optional with inline union type --- data_structures/stacks/stack_using_dll.py | 40 ++++++++++++++--------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/data_structures/stacks/stack_using_dll.py b/data_structures/stacks/stack_using_dll.py index 75e0cd206..a129665f2 100644 --- a/data_structures/stacks/stack_using_dll.py +++ b/data_structures/stacks/stack_using_dll.py @@ -1,15 +1,21 @@ # A complete working Python program to demonstrate all # stack operations using a doubly linked list +from __future__ import annotations -class Node: - def __init__(self, data): +from typing import Generic, TypeVar + +T = TypeVar("T") + + +class Node(Generic[T]): + def __init__(self, data: T): self.data = data # Assign data - self.next = None # Initialize next as null - self.prev = None # Initialize prev as null + self.next: Node[T] | None = None # Initialize next as null + self.prev: Node[T] | None = None # Initialize prev as null -class Stack: +class Stack(Generic[T]): """ >>> stack = Stack() >>> stack.is_empty() @@ -35,10 +41,10 @@ class Stack: 2->1->0-> """ - def __init__(self): - self.head = None + def __init__(self) -> None: + self.head: Node[T] | None = None - def push(self, data): + def push(self, data: T) -> None: """add a Node to the stack""" if self.head is None: self.head = Node(data) @@ -49,21 +55,23 @@ class Stack: new_node.prev = None self.head = new_node - def pop(self): + def pop(self) -> T | None: """pop the top element off the stack""" if self.head is None: return None else: + assert self.head is not None temp = self.head.data self.head = self.head.next - self.head.prev = None + if self.head is not None: + self.head.prev = None return temp - def top(self): + def top(self) -> T | None: """return the top element of the stack""" - return self.head.data + return self.head.data if self.head is not None else None - def __len__(self): + def __len__(self) -> int: temp = self.head count = 0 while temp is not None: @@ -71,10 +79,10 @@ class Stack: temp = temp.next return count - def is_empty(self): + def is_empty(self) -> bool: return self.head is None - def print_stack(self): + def print_stack(self) -> None: print("stack elements are:") temp = self.head while temp is not None: @@ -86,7 +94,7 @@ class Stack: if __name__ == "__main__": # Start with the empty stack - stack = Stack() + stack: Stack[int] = Stack() # Insert 4 at the beginning. So stack becomes 4->None print("Stack operations using Doubly LinkedList") From 4eb5c12727d7590d17a5cbefe34c6a255f69e670 Mon Sep 17 00:00:00 2001 From: Matteo Messmer <40521259+matteomessmer@users.noreply.github.com> Date: Wed, 27 Oct 2021 00:28:26 +0200 Subject: [PATCH 143/726] Sphere intersection and spherical cap volumes (#5579) * sphere intersection + spherical cap volume formulas * reformatted * Update volume.py Co-authored-by: Christian Clauss --- maths/volume.py | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/maths/volume.py b/maths/volume.py index 51b2b9fc0..fd24aa9ee 100644 --- a/maths/volume.py +++ b/maths/volume.py @@ -20,6 +20,56 @@ def vol_cube(side_length: int | float) -> float: return pow(side_length, 3) +def vol_spherical_cap(height: float, radius: float) -> float: + """ + Calculate the Volume of the spherical cap. + :return 1/3 pi * height ^ 2 * (3 * radius - height) + + >>> vol_spherical_cap(1, 2) + 5.235987755982988 + """ + return 1 / 3 * pi * pow(height, 2) * (3 * radius - height) + + +def vol_spheres_intersect( + radius_1: float, radius_2: float, centers_distance: float +) -> float: + """ + Calculate the volume of the intersection of two spheres. + + The intersection is composed by two spherical caps and therefore its volume is the + sum of the volumes of the spherical caps. First it calculates the heights (h1, h2) + of the the spherical caps, then the two volumes and it returns the sum. + The height formulas are + h1 = (radius_1 - radius_2 + centers_distance) + * (radius_1 + radius_2 - centers_distance) + / (2 * centers_distance) + h2 = (radius_2 - radius_1 + centers_distance) + * (radius_2 + radius_1 - centers_distance) + / (2 * centers_distance) + if centers_distance is 0 then it returns the volume of the smallers sphere + :return vol_spherical_cap(h1, radius_2) + vol_spherical_cap(h2, radius_1) + + >>> vol_spheres_intersect(2, 2, 1) + 21.205750411731103 + """ + if centers_distance == 0: + return vol_sphere(min(radius_1, radius_2)) + + h1 = ( + (radius_1 - radius_2 + centers_distance) + * (radius_1 + radius_2 - centers_distance) + / (2 * centers_distance) + ) + h2 = ( + (radius_2 - radius_1 + centers_distance) + * (radius_2 + radius_1 - centers_distance) + / (2 * centers_distance) + ) + + return vol_spherical_cap(h1, radius_2) + vol_spherical_cap(h2, radius_1) + + def vol_cuboid(width: float, height: float, length: float) -> float: """ Calculate the Volume of a Cuboid. @@ -127,6 +177,8 @@ def main(): print("Pyramid: " + str(vol_pyramid(2, 2))) # ~= 1.33 print("Sphere: " + str(vol_sphere(2))) # ~= 33.5 print("Circular Cylinder: " + str(vol_circular_cylinder(2, 2))) # ~= 25.1 + print("Spherical cap: " + str(vol_spherical_cap(1, 2))) # ~= 5.24 + print("Spheres intersetion: " + str(vol_spheres_intersect(2, 2, 1))) # ~= 21.21 if __name__ == "__main__": From 8285913e81fb8f46b90d0e19da233862964c07dc Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Wed, 27 Oct 2021 00:45:33 -0300 Subject: [PATCH 144/726] [mypy] Fix and add type annotations (#5618) --- data_structures/queue/double_ended_queue.py | 72 ++++++--------------- 1 file changed, 18 insertions(+), 54 deletions(-) diff --git a/data_structures/queue/double_ended_queue.py b/data_structures/queue/double_ended_queue.py index 36106d8bc..a4658d997 100644 --- a/data_structures/queue/double_ended_queue.py +++ b/data_structures/queue/double_ended_queue.py @@ -1,6 +1,8 @@ """ Implementation of double ended queue. """ +from __future__ import annotations + from dataclasses import dataclass from typing import Any, Iterable @@ -8,35 +10,23 @@ from typing import Any, Iterable class Deque: """ Deque data structure. - Operations ---------- append(val: Any) -> None - appendleft(val: Any) -> None - extend(iter: Iterable) -> None - extendleft(iter: Iterable) -> None - pop() -> Any - popleft() -> Any - - Observers --------- is_empty() -> bool - - Attributes ---------- _front: _Node front of the deque a.k.a. the first element - _back: _Node back of the element a.k.a. the last element - _len: int the number of nodes """ @@ -51,13 +41,12 @@ class Deque: """ val: Any = None - next: "Deque._Node" = None - prev: "Deque._Node" = None + next: Deque._Node | None = None + prev: Deque._Node | None = None class _Iterator: """ Helper class for iteration. Will be used to implement iteration. - Attributes ---------- _cur: _Node @@ -66,10 +55,10 @@ class Deque: __slots__ = ["_cur"] - def __init__(self, cur: "Deque._Node") -> None: + def __init__(self, cur: Deque._Node | None) -> None: self._cur = cur - def __iter__(self) -> "Deque._Iterator": + def __iter__(self) -> Deque._Iterator: """ >>> our_deque = Deque([1, 2, 3]) >>> iterator = iter(our_deque) @@ -95,9 +84,10 @@ class Deque: return val - def __init__(self, iterable: Iterable = None) -> None: - self._front = self._back = None - self._len = 0 + def __init__(self, iterable: Iterable[Any] | None = None) -> None: + self._front: Any = None + self._back: Any = None + self._len: int = 0 if iterable is not None: # append every value to the deque @@ -108,7 +98,6 @@ class Deque: """ Adds val to the end of the deque. Time complexity: O(1) - >>> our_deque_1 = Deque([1, 2, 3]) >>> our_deque_1.append(4) >>> our_deque_1 @@ -117,7 +106,6 @@ class Deque: >>> our_deque_2.append('c') >>> our_deque_2 ['a', 'b', 'c'] - >>> from collections import deque >>> deque_collections_1 = deque([1, 2, 3]) >>> deque_collections_1.append(4) @@ -127,7 +115,6 @@ class Deque: >>> deque_collections_2.append('c') >>> deque_collections_2 deque(['a', 'b', 'c']) - >>> list(our_deque_1) == list(deque_collections_1) True >>> list(our_deque_2) == list(deque_collections_2) @@ -153,7 +140,6 @@ class Deque: """ Adds val to the beginning of the deque. Time complexity: O(1) - >>> our_deque_1 = Deque([2, 3]) >>> our_deque_1.appendleft(1) >>> our_deque_1 @@ -162,7 +148,6 @@ class Deque: >>> our_deque_2.appendleft('a') >>> our_deque_2 ['a', 'b', 'c'] - >>> from collections import deque >>> deque_collections_1 = deque([2, 3]) >>> deque_collections_1.appendleft(1) @@ -172,7 +157,6 @@ class Deque: >>> deque_collections_2.appendleft('a') >>> deque_collections_2 deque(['a', 'b', 'c']) - >>> list(our_deque_1) == list(deque_collections_1) True >>> list(our_deque_2) == list(deque_collections_2) @@ -194,11 +178,10 @@ class Deque: # make sure there were no errors assert not self.is_empty(), "Error on appending value." - def extend(self, iter: Iterable) -> None: + def extend(self, iter: Iterable[Any]) -> None: """ Appends every value of iter to the end of the deque. Time complexity: O(n) - >>> our_deque_1 = Deque([1, 2, 3]) >>> our_deque_1.extend([4, 5]) >>> our_deque_1 @@ -207,7 +190,6 @@ class Deque: >>> our_deque_2.extend('cd') >>> our_deque_2 ['a', 'b', 'c', 'd'] - >>> from collections import deque >>> deque_collections_1 = deque([1, 2, 3]) >>> deque_collections_1.extend([4, 5]) @@ -217,7 +199,6 @@ class Deque: >>> deque_collections_2.extend('cd') >>> deque_collections_2 deque(['a', 'b', 'c', 'd']) - >>> list(our_deque_1) == list(deque_collections_1) True >>> list(our_deque_2) == list(deque_collections_2) @@ -226,11 +207,10 @@ class Deque: for val in iter: self.append(val) - def extendleft(self, iter: Iterable) -> None: + def extendleft(self, iter: Iterable[Any]) -> None: """ Appends every value of iter to the beginning of the deque. Time complexity: O(n) - >>> our_deque_1 = Deque([1, 2, 3]) >>> our_deque_1.extendleft([0, -1]) >>> our_deque_1 @@ -239,7 +219,6 @@ class Deque: >>> our_deque_2.extendleft('ba') >>> our_deque_2 ['a', 'b', 'c', 'd'] - >>> from collections import deque >>> deque_collections_1 = deque([1, 2, 3]) >>> deque_collections_1.extendleft([0, -1]) @@ -249,7 +228,6 @@ class Deque: >>> deque_collections_2.extendleft('ba') >>> deque_collections_2 deque(['a', 'b', 'c', 'd']) - >>> list(our_deque_1) == list(deque_collections_1) True >>> list(our_deque_2) == list(deque_collections_2) @@ -262,16 +240,13 @@ class Deque: """ Removes the last element of the deque and returns it. Time complexity: O(1) - @returns topop.val: the value of the node to pop. - >>> our_deque = Deque([1, 2, 3, 15182]) >>> our_popped = our_deque.pop() >>> our_popped 15182 >>> our_deque [1, 2, 3] - >>> from collections import deque >>> deque_collections = deque([1, 2, 3, 15182]) >>> collections_popped = deque_collections.pop() @@ -279,7 +254,6 @@ class Deque: 15182 >>> deque_collections deque([1, 2, 3]) - >>> list(our_deque) == list(deque_collections) True >>> our_popped == collections_popped @@ -302,16 +276,13 @@ class Deque: """ Removes the first element of the deque and returns it. Time complexity: O(1) - @returns topop.val: the value of the node to pop. - >>> our_deque = Deque([15182, 1, 2, 3]) >>> our_popped = our_deque.popleft() >>> our_popped 15182 >>> our_deque [1, 2, 3] - >>> from collections import deque >>> deque_collections = deque([15182, 1, 2, 3]) >>> collections_popped = deque_collections.popleft() @@ -319,7 +290,6 @@ class Deque: 15182 >>> deque_collections deque([1, 2, 3]) - >>> list(our_deque) == list(deque_collections) True >>> our_popped == collections_popped @@ -340,14 +310,12 @@ class Deque: """ Checks if the deque is empty. Time complexity: O(1) - >>> our_deque = Deque([1, 2, 3]) >>> our_deque.is_empty() False >>> our_empty_deque = Deque() >>> our_empty_deque.is_empty() True - >>> from collections import deque >>> empty_deque_collections = deque() >>> list(our_empty_deque) == list(empty_deque_collections) @@ -359,14 +327,12 @@ class Deque: """ Implements len() function. Returns the length of the deque. Time complexity: O(1) - >>> our_deque = Deque([1, 2, 3]) >>> len(our_deque) 3 >>> our_empty_deque = Deque() >>> len(our_empty_deque) 0 - >>> from collections import deque >>> deque_collections = deque([1, 2, 3]) >>> len(deque_collections) @@ -379,11 +345,10 @@ class Deque: """ return self._len - def __eq__(self, other: "Deque") -> bool: + def __eq__(self, other: object) -> bool: """ Implements "==" operator. Returns if *self* is equal to *other*. Time complexity: O(n) - >>> our_deque_1 = Deque([1, 2, 3]) >>> our_deque_2 = Deque([1, 2, 3]) >>> our_deque_1 == our_deque_2 @@ -391,7 +356,6 @@ class Deque: >>> our_deque_3 = Deque([1, 2]) >>> our_deque_1 == our_deque_3 False - >>> from collections import deque >>> deque_collections_1 = deque([1, 2, 3]) >>> deque_collections_2 = deque([1, 2, 3]) @@ -400,12 +364,15 @@ class Deque: >>> deque_collections_3 = deque([1, 2]) >>> deque_collections_1 == deque_collections_3 False - >>> (our_deque_1 == our_deque_2) == (deque_collections_1 == deque_collections_2) True >>> (our_deque_1 == our_deque_3) == (deque_collections_1 == deque_collections_3) True """ + + if not isinstance(other, Deque): + return NotImplemented + me = self._front oth = other._front @@ -422,18 +389,16 @@ class Deque: return True - def __iter__(self) -> "_Iterator": + def __iter__(self) -> Deque._Iterator: """ Implements iteration. Time complexity: O(1) - >>> our_deque = Deque([1, 2, 3]) >>> for v in our_deque: ... print(v) 1 2 3 - >>> from collections import deque >>> deque_collections = deque([1, 2, 3]) >>> for v in deque_collections: @@ -449,7 +414,6 @@ class Deque: Implements representation of the deque. Represents it as a list, with its values between '[' and ']'. Time complexity: O(n) - >>> our_deque = Deque([1, 2, 3]) >>> our_deque [1, 2, 3] From fe5c711ce68cb1d410d13d8c8a02ee7bfd49b1d3 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Wed, 27 Oct 2021 03:48:43 +0000 Subject: [PATCH 145/726] Rewrite parts of Vector and Matrix (#5362) * Rewrite parts of Vector and Matrix methods * Refactor determinant method and add unit tests Refactor determinant method to create separate minor and cofactor methods. Add respective unit tests for new methods. Rename methods using snake case to follow Python naming conventions. * Reorganize Vector and Matrix methods * Update linear_algebra/README.md Co-authored-by: John Law * Fix punctuation and wording * Apply suggestions from code review Co-authored-by: John Law Co-authored-by: John Law --- knapsack/README.md | 2 +- linear_algebra/README.md | 44 +-- linear_algebra/src/lib.py | 372 ++++++++++++---------- linear_algebra/src/test_linear_algebra.py | 96 ++++-- 4 files changed, 292 insertions(+), 222 deletions(-) diff --git a/knapsack/README.md b/knapsack/README.md index 6041c1e48..f31e5f591 100644 --- a/knapsack/README.md +++ b/knapsack/README.md @@ -17,7 +17,7 @@ The knapsack problem has been studied for more than a century, with early works ## Documentation This module uses docstrings to enable the use of Python's in-built `help(...)` function. -For instance, try `help(Vector)`, `help(unitBasisVector)`, and `help(CLASSNAME.METHODNAME)`. +For instance, try `help(Vector)`, `help(unit_basis_vector)`, and `help(CLASSNAME.METHODNAME)`. --- diff --git a/linear_algebra/README.md b/linear_algebra/README.md index dc6085090..35b50b5e0 100644 --- a/linear_algebra/README.md +++ b/linear_algebra/README.md @@ -10,56 +10,56 @@ This module contains classes and functions for doing linear algebra. - - This class represents a vector of arbitrary size and related operations. - **Overview about the methods:** + **Overview of the methods:** - - constructor(components : list) : init the vector - - set(components : list) : changes the vector components. + - constructor(components) : init the vector + - set(components) : changes the vector components. - \_\_str\_\_() : toString method - - component(i : int): gets the i-th component (start by 0) + - component(i): gets the i-th component (0-indexed) - \_\_len\_\_() : gets the size / length of the vector (number of components) - - euclidLength() : returns the eulidean length of the vector. + - euclidean_length() : returns the eulidean length of the vector - operator + : vector addition - operator - : vector subtraction - operator * : scalar multiplication and dot product - - copy() : copies this vector and returns it. - - changeComponent(pos,value) : changes the specified component. + - copy() : copies this vector and returns it + - change_component(pos,value) : changes the specified component -- function zeroVector(dimension) +- function zero_vector(dimension) - returns a zero vector of 'dimension' -- function unitBasisVector(dimension,pos) - - returns a unit basis vector with a One at index 'pos' (indexing at 0) -- function axpy(scalar,vector1,vector2) +- function unit_basis_vector(dimension, pos) + - returns a unit basis vector with a one at index 'pos' (0-indexed) +- function axpy(scalar, vector1, vector2) - computes the axpy operation -- function randomVector(N,a,b) - - returns a random vector of size N, with random integer components between 'a' and 'b'. +- function random_vector(N, a, b) + - returns a random vector of size N, with random integer components between 'a' and 'b' inclusive ### class Matrix - - This class represents a matrix of arbitrary size and operations on it. - **Overview about the methods:** + **Overview of the methods:** - \_\_str\_\_() : returns a string representation - operator * : implements the matrix vector multiplication implements the matrix-scalar multiplication. - - changeComponent(x,y,value) : changes the specified component. - - component(x,y) : returns the specified component. + - change_component(x, y, value) : changes the specified component. + - component(x, y) : returns the specified component. - width() : returns the width of the matrix - height() : returns the height of the matrix - - determinate() : returns the determinate of the matrix if it is square + - determinant() : returns the determinant of the matrix if it is square - operator + : implements the matrix-addition. - - operator - _ implements the matrix-subtraction + - operator - : implements the matrix-subtraction -- function squareZeroMatrix(N) +- function square_zero_matrix(N) - returns a square zero-matrix of dimension NxN -- function randomMatrix(W,H,a,b) - - returns a random matrix WxH with integer components between 'a' and 'b' +- function random_matrix(W, H, a, b) + - returns a random matrix WxH with integer components between 'a' and 'b' inclusive --- ## Documentation This module uses docstrings to enable the use of Python's in-built `help(...)` function. -For instance, try `help(Vector)`, `help(unitBasisVector)`, and `help(CLASSNAME.METHODNAME)`. +For instance, try `help(Vector)`, `help(unit_basis_vector)`, and `help(CLASSNAME.METHODNAME)`. --- diff --git a/linear_algebra/src/lib.py b/linear_algebra/src/lib.py index 6a18df5e1..dad0a8c0a 100644 --- a/linear_algebra/src/lib.py +++ b/linear_algebra/src/lib.py @@ -10,13 +10,13 @@ with linear algebra in python. Overview: - class Vector -- function zeroVector(dimension) -- function unitBasisVector(dimension,pos) -- function axpy(scalar,vector1,vector2) -- function randomVector(N,a,b) +- function zero_vector(dimension) +- function unit_basis_vector(dimension, pos) +- function axpy(scalar, vector1, vector2) +- function random_vector(N, a, b) - class Matrix -- function squareZeroMatrix(N) -- function randomMatrix(W,H,a,b) +- function square_zero_matrix(N) +- function random_matrix(W, H, a, b) """ from __future__ import annotations @@ -30,20 +30,23 @@ class Vector: This class represents a vector of arbitrary size. You need to give the vector components. - Overview about the methods: + Overview of the methods: - constructor(components : list) : init the vector - set(components : list) : changes the vector components. - __str__() : toString method - component(i : int): gets the i-th component (start by 0) - __len__() : gets the size of the vector (number of components) - euclidLength() : returns the euclidean length of the vector. - operator + : vector addition - operator - : vector subtraction - operator * : scalar multiplication and dot product - copy() : copies this vector and returns it. - changeComponent(pos,value) : changes the specified component. - TODO: compare-operator + __init__(components: Collection[float] | None): init the vector + __len__(): gets the size of the vector (number of components) + __str__(): returns a string representation + __add__(other: Vector): vector addition + __sub__(other: Vector): vector subtraction + __mul__(other: float): scalar multiplication + __mul__(other: Vector): dot product + set(components: Collection[float]): changes the vector components + copy(): copies this vector and returns it + component(i): gets the i-th component (0-indexed) + change_component(pos: int, value: float): changes specified component + euclidean_length(): returns the euclidean length of the vector + magnitude(): returns the magnitude of the vector + angle(other: Vector, deg: bool): returns the angle between two vectors + TODO: compare-operator """ def __init__(self, components: Collection[float] | None = None) -> None: @@ -55,47 +58,17 @@ class Vector: components = [] self.__components = list(components) - def set(self, components: Collection[float]) -> None: - """ - input: new components - changes the components of the vector. - replace the components with newer one. - """ - if len(components) > 0: - self.__components = list(components) - else: - raise Exception("please give any vector") - - def __str__(self) -> str: - """ - returns a string representation of the vector - """ - return "(" + ",".join(map(str, self.__components)) + ")" - - def component(self, i: int) -> float: - """ - input: index (start at 0) - output: the i-th component of the vector. - """ - if type(i) is int and -len(self.__components) <= i < len(self.__components): - return self.__components[i] - else: - raise Exception("index out of range") - def __len__(self) -> int: """ returns the size of the vector """ return len(self.__components) - def euclidLength(self) -> float: + def __str__(self) -> str: """ - returns the euclidean length of the vector + returns a string representation of the vector """ - summe: float = 0 - for c in self.__components: - summe += c ** 2 - return math.sqrt(summe) + return "(" + ",".join(map(str, self.__components)) + ")" def __add__(self, other: Vector) -> Vector: """ @@ -139,15 +112,57 @@ class Vector: if isinstance(other, float) or isinstance(other, int): ans = [c * other for c in self.__components] return Vector(ans) - elif isinstance(other, Vector) and (len(self) == len(other)): + elif isinstance(other, Vector) and len(self) == len(other): size = len(self) - summe: float = 0 - for i in range(size): - summe += self.__components[i] * other.component(i) - return summe + prods = [self.__components[i] * other.component(i) for i in range(size)] + return sum(prods) else: # error case raise Exception("invalid operand!") + def set(self, components: Collection[float]) -> None: + """ + input: new components + changes the components of the vector. + replaces the components with newer one. + """ + if len(components) > 0: + self.__components = list(components) + else: + raise Exception("please give any vector") + + def copy(self) -> Vector: + """ + copies this vector and returns it. + """ + return Vector(self.__components) + + def component(self, i: int) -> float: + """ + input: index (0-indexed) + output: the i-th component of the vector. + """ + if type(i) is int and -len(self.__components) <= i < len(self.__components): + return self.__components[i] + else: + raise Exception("index out of range") + + def change_component(self, pos: int, value: float) -> None: + """ + input: an index (pos) and a value + changes the specified component (pos) with the + 'value' + """ + # precondition + assert -len(self.__components) <= pos < len(self.__components) + self.__components[pos] = value + + def euclidean_length(self) -> float: + """ + returns the euclidean length of the vector + """ + squares = [c ** 2 for c in self.__components] + return math.sqrt(sum(squares)) + def magnitude(self) -> float: """ Magnitude of a Vector @@ -156,7 +171,8 @@ class Vector: 5.385164807134504 """ - return sum([i ** 2 for i in self.__components]) ** (1 / 2) + squares = [c ** 2 for c in self.__components] + return math.sqrt(sum(squares)) def angle(self, other: Vector, deg: bool = False) -> float: """ @@ -178,24 +194,8 @@ class Vector: else: return math.acos(num / den) - def copy(self) -> Vector: - """ - copies this vector and returns it. - """ - return Vector(self.__components) - def changeComponent(self, pos: int, value: float) -> None: - """ - input: an index (pos) and a value - changes the specified component (pos) with the - 'value' - """ - # precondition - assert -len(self.__components) <= pos < len(self.__components) - self.__components[pos] = value - - -def zeroVector(dimension: int) -> Vector: +def zero_vector(dimension: int) -> Vector: """ returns a zero-vector of size 'dimension' """ @@ -204,7 +204,7 @@ def zeroVector(dimension: int) -> Vector: return Vector([0] * dimension) -def unitBasisVector(dimension: int, pos: int) -> Vector: +def unit_basis_vector(dimension: int, pos: int) -> Vector: """ returns a unit basis vector with a One at index 'pos' (indexing at 0) @@ -225,13 +225,13 @@ def axpy(scalar: float, x: Vector, y: Vector) -> Vector: # precondition assert ( isinstance(x, Vector) - and (isinstance(y, Vector)) + and isinstance(y, Vector) and (isinstance(scalar, int) or isinstance(scalar, float)) ) return x * scalar + y -def randomVector(N: int, a: int, b: int) -> Vector: +def random_vector(n: int, a: int, b: int) -> Vector: """ input: size (N) of the vector. random range (a,b) @@ -239,26 +239,30 @@ def randomVector(N: int, a: int, b: int) -> Vector: random integer components between 'a' and 'b'. """ random.seed(None) - ans = [random.randint(a, b) for _ in range(N)] + ans = [random.randint(a, b) for _ in range(n)] return Vector(ans) class Matrix: """ class: Matrix - This class represents a arbitrary matrix. + This class represents an arbitrary matrix. - Overview about the methods: + Overview of the methods: - __str__() : returns a string representation - operator * : implements the matrix vector multiplication - implements the matrix-scalar multiplication. - changeComponent(x,y,value) : changes the specified component. - component(x,y) : returns the specified component. - width() : returns the width of the matrix - height() : returns the height of the matrix - operator + : implements the matrix-addition. - operator - _ implements the matrix-subtraction + __init__(): + __str__(): returns a string representation + __add__(other: Matrix): matrix addition + __sub__(other: Matrix): matrix subtraction + __mul__(other: float): scalar multiplication + __mul__(other: Vector): vector multiplication + height() : returns height + width() : returns width + component(x: int, y: int): returns specified component + change_component(x: int, y: int, value: float): changes specified component + minor(x: int, y: int): returns minor along (x, y) + cofactor(x: int, y: int): returns cofactor along (x, y) + determinant() : returns determinant """ def __init__(self, matrix: list[list[float]], w: int, h: int) -> None: @@ -285,62 +289,37 @@ class Matrix: ans += str(self.__matrix[i][j]) + "|\n" return ans - def changeComponent(self, x: int, y: int, value: float) -> None: + def __add__(self, other: Matrix) -> Matrix: """ - changes the x-y component of this matrix + implements the matrix-addition. """ - if 0 <= x < self.__height and 0 <= y < self.__width: - self.__matrix[x][y] = value + if self.__width == other.width() and self.__height == other.height(): + matrix = [] + for i in range(self.__height): + row = [ + self.__matrix[i][j] + other.component(i, j) + for j in range(self.__width) + ] + matrix.append(row) + return Matrix(matrix, self.__width, self.__height) else: - raise Exception("changeComponent: indices out of bounds") + raise Exception("matrix must have the same dimension!") - def component(self, x: int, y: int) -> float: + def __sub__(self, other: Matrix) -> Matrix: """ - returns the specified (x,y) component + implements the matrix-subtraction. """ - if 0 <= x < self.__height and 0 <= y < self.__width: - return self.__matrix[x][y] + if self.__width == other.width() and self.__height == other.height(): + matrix = [] + for i in range(self.__height): + row = [ + self.__matrix[i][j] - other.component(i, j) + for j in range(self.__width) + ] + matrix.append(row) + return Matrix(matrix, self.__width, self.__height) else: - raise Exception("changeComponent: indices out of bounds") - - def width(self) -> int: - """ - getter for the width - """ - return self.__width - - def height(self) -> int: - """ - getter for the height - """ - return self.__height - - def determinate(self) -> float: - """ - returns the determinate of an nxn matrix using Laplace expansion - """ - if self.__height == self.__width and self.__width >= 2: - total = 0 - if self.__width > 2: - for x in range(0, self.__width): - for y in range(0, self.__height): - total += ( - self.__matrix[x][y] - * (-1) ** (x + y) - * Matrix( - self.__matrix[0:x] + self.__matrix[x + 1 :], - self.__width - 1, - self.__height - 1, - ).determinate() - ) - else: - return ( - self.__matrix[0][0] * self.__matrix[1][1] - - self.__matrix[0][1] * self.__matrix[1][0] - ) - return total - else: - raise Exception("matrix is not square") + raise Exception("matrices must have the same dimension!") @overload def __mul__(self, other: float) -> Matrix: @@ -355,20 +334,20 @@ class Matrix: implements the matrix-vector multiplication. implements the matrix-scalar multiplication """ - if isinstance(other, Vector): # vector-matrix + if isinstance(other, Vector): # matrix-vector if len(other) == self.__width: - ans = zeroVector(self.__height) + ans = zero_vector(self.__height) for i in range(self.__height): - summe: float = 0 - for j in range(self.__width): - summe += other.component(j) * self.__matrix[i][j] - ans.changeComponent(i, summe) - summe = 0 + prods = [ + self.__matrix[i][j] * other.component(j) + for j in range(self.__width) + ] + ans.change_component(i, sum(prods)) return ans else: raise Exception( "vector must have the same size as the " - + "number of columns of the matrix!" + "number of columns of the matrix!" ) elif isinstance(other, int) or isinstance(other, float): # matrix-scalar matrix = [ @@ -377,52 +356,95 @@ class Matrix: ] return Matrix(matrix, self.__width, self.__height) - def __add__(self, other: Matrix) -> Matrix: + def height(self) -> int: """ - implements the matrix-addition. + getter for the height """ - if self.__width == other.width() and self.__height == other.height(): - matrix = [] - for i in range(self.__height): - row = [] - for j in range(self.__width): - row.append(self.__matrix[i][j] + other.component(i, j)) - matrix.append(row) - return Matrix(matrix, self.__width, self.__height) + return self.__height + + def width(self) -> int: + """ + getter for the width + """ + return self.__width + + def component(self, x: int, y: int) -> float: + """ + returns the specified (x,y) component + """ + if 0 <= x < self.__height and 0 <= y < self.__width: + return self.__matrix[x][y] else: - raise Exception("matrix must have the same dimension!") + raise Exception("change_component: indices out of bounds") - def __sub__(self, other: Matrix) -> Matrix: + def change_component(self, x: int, y: int, value: float) -> None: """ - implements the matrix-subtraction. + changes the x-y component of this matrix """ - if self.__width == other.width() and self.__height == other.height(): - matrix = [] - for i in range(self.__height): - row = [] - for j in range(self.__width): - row.append(self.__matrix[i][j] - other.component(i, j)) - matrix.append(row) - return Matrix(matrix, self.__width, self.__height) + if 0 <= x < self.__height and 0 <= y < self.__width: + self.__matrix[x][y] = value else: - raise Exception("matrix must have the same dimension!") + raise Exception("change_component: indices out of bounds") + + def minor(self, x: int, y: int) -> float: + """ + returns the minor along (x, y) + """ + if self.__height != self.__width: + raise Exception("Matrix is not square") + minor = self.__matrix[:x] + self.__matrix[x + 1 :] + for i in range(len(minor)): + minor[i] = minor[i][:y] + minor[i][y + 1 :] + return Matrix(minor, self.__width - 1, self.__height - 1).determinant() + + def cofactor(self, x: int, y: int) -> float: + """ + returns the cofactor (signed minor) along (x, y) + """ + if self.__height != self.__width: + raise Exception("Matrix is not square") + if 0 <= x < self.__height and 0 <= y < self.__width: + return (-1) ** (x + y) * self.minor(x, y) + else: + raise Exception("Indices out of bounds") + + def determinant(self) -> float: + """ + returns the determinant of an nxn matrix using Laplace expansion + """ + if self.__height != self.__width: + raise Exception("Matrix is not square") + if self.__height < 1: + raise Exception("Matrix has no element") + elif self.__height == 1: + return self.__matrix[0][0] + elif self.__height == 2: + return ( + self.__matrix[0][0] * self.__matrix[1][1] + - self.__matrix[0][1] * self.__matrix[1][0] + ) + else: + cofactor_prods = [ + self.__matrix[0][y] * self.cofactor(0, y) for y in range(self.__width) + ] + return sum(cofactor_prods) -def squareZeroMatrix(N: int) -> Matrix: +def square_zero_matrix(n: int) -> Matrix: """ returns a square zero-matrix of dimension NxN """ - ans: list[list[float]] = [[0] * N for _ in range(N)] - return Matrix(ans, N, N) + ans: list[list[float]] = [[0] * n for _ in range(n)] + return Matrix(ans, n, n) -def randomMatrix(W: int, H: int, a: int, b: int) -> Matrix: +def random_matrix(width: int, height: int, a: int, b: int) -> Matrix: """ returns a random matrix WxH with integer components between 'a' and 'b' """ random.seed(None) matrix: list[list[float]] = [ - [random.randint(a, b) for _ in range(W)] for _ in range(H) + [random.randint(a, b) for _ in range(width)] for _ in range(height) ] - return Matrix(matrix, W, H) + return Matrix(matrix, width, height) diff --git a/linear_algebra/src/test_linear_algebra.py b/linear_algebra/src/test_linear_algebra.py index 0954a2d93..de7041a17 100644 --- a/linear_algebra/src/test_linear_algebra.py +++ b/linear_algebra/src/test_linear_algebra.py @@ -8,13 +8,20 @@ This file contains the test-suite for the linear algebra library. """ import unittest -from .lib import Matrix, Vector, axpy, squareZeroMatrix, unitBasisVector, zeroVector +from .lib import ( + Matrix, + Vector, + axpy, + square_zero_matrix, + unit_basis_vector, + zero_vector, +) class Test(unittest.TestCase): def test_component(self) -> None: """ - test for method component + test for method component() """ x = Vector([1, 2, 3]) self.assertEqual(x.component(0), 1) @@ -23,24 +30,24 @@ class Test(unittest.TestCase): def test_str(self) -> None: """ - test for toString() method + test for method toString() """ x = Vector([0, 0, 0, 0, 0, 1]) self.assertEqual(str(x), "(0,0,0,0,0,1)") def test_size(self) -> None: """ - test for size()-method + test for method size() """ x = Vector([1, 2, 3, 4]) self.assertEqual(len(x), 4) def test_euclidLength(self) -> None: """ - test for the eulidean length + test for method euclidean_length() """ x = Vector([1, 2]) - self.assertAlmostEqual(x.euclidLength(), 2.236, 3) + self.assertAlmostEqual(x.euclidean_length(), 2.236, 3) def test_add(self) -> None: """ @@ -67,26 +74,26 @@ class Test(unittest.TestCase): test for * operator """ x = Vector([1, 2, 3]) - a = Vector([2, -1, 4]) # for test of dot-product + a = Vector([2, -1, 4]) # for test of dot product b = Vector([1, -2, -1]) self.assertEqual(str(x * 3.0), "(3.0,6.0,9.0)") self.assertEqual((a * b), 0) def test_zeroVector(self) -> None: """ - test for the global function zeroVector(...) + test for global function zero_vector() """ - self.assertTrue(str(zeroVector(10)).count("0") == 10) + self.assertTrue(str(zero_vector(10)).count("0") == 10) def test_unitBasisVector(self) -> None: """ - test for the global function unitBasisVector(...) + test for global function unit_basis_vector() """ - self.assertEqual(str(unitBasisVector(3, 1)), "(0,1,0)") + self.assertEqual(str(unit_basis_vector(3, 1)), "(0,1,0)") def test_axpy(self) -> None: """ - test for the global function axpy(...) (operation) + test for global function axpy() (operation) """ x = Vector([1, 2, 3]) y = Vector([1, 0, 1]) @@ -94,7 +101,7 @@ class Test(unittest.TestCase): def test_copy(self) -> None: """ - test for the copy()-method + test for method copy() """ x = Vector([1, 0, 0, 0, 0, 0]) y = x.copy() @@ -102,53 +109,94 @@ class Test(unittest.TestCase): def test_changeComponent(self) -> None: """ - test for the changeComponent(...)-method + test for method change_component() """ x = Vector([1, 0, 0]) - x.changeComponent(0, 0) - x.changeComponent(1, 1) + x.change_component(0, 0) + x.change_component(1, 1) self.assertEqual(str(x), "(0,1,0)") def test_str_matrix(self) -> None: + """ + test for Matrix method str() + """ A = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) self.assertEqual("|1,2,3|\n|2,4,5|\n|6,7,8|\n", str(A)) - def test_determinate(self) -> None: + def test_minor(self) -> None: """ - test for determinate() + test for Matrix method minor() """ - A = Matrix([[1, 1, 4, 5], [3, 3, 3, 2], [5, 1, 9, 0], [9, 7, 7, 9]], 4, 4) - self.assertEqual(-376, A.determinate()) + A = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) + minors = [[-3, -14, -10], [-5, -10, -5], [-2, -1, 0]] + for x in range(A.height()): + for y in range(A.width()): + self.assertEqual(minors[x][y], A.minor(x, y)) + + def test_cofactor(self) -> None: + """ + test for Matrix method cofactor() + """ + A = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) + cofactors = [[-3, 14, -10], [5, -10, 5], [-2, 1, 0]] + for x in range(A.height()): + for y in range(A.width()): + self.assertEqual(cofactors[x][y], A.cofactor(x, y)) + + def test_determinant(self) -> None: + """ + test for Matrix method determinant() + """ + A = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) + self.assertEqual(-5, A.determinant()) def test__mul__matrix(self) -> None: + """ + test for Matrix * operator + """ A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]], 3, 3) x = Vector([1, 2, 3]) self.assertEqual("(14,32,50)", str(A * x)) self.assertEqual("|2,4,6|\n|8,10,12|\n|14,16,18|\n", str(A * 2)) - def test_changeComponent_matrix(self) -> None: + def test_change_component_matrix(self) -> None: + """ + test for Matrix method change_component() + """ A = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) - A.changeComponent(0, 2, 5) + A.change_component(0, 2, 5) self.assertEqual("|1,2,5|\n|2,4,5|\n|6,7,8|\n", str(A)) def test_component_matrix(self) -> None: + """ + test for Matrix method component() + """ A = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) self.assertEqual(7, A.component(2, 1), 0.01) def test__add__matrix(self) -> None: + """ + test for Matrix + operator + """ A = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) B = Matrix([[1, 2, 7], [2, 4, 5], [6, 7, 10]], 3, 3) self.assertEqual("|2,4,10|\n|4,8,10|\n|12,14,18|\n", str(A + B)) def test__sub__matrix(self) -> None: + """ + test for Matrix - operator + """ A = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) B = Matrix([[1, 2, 7], [2, 4, 5], [6, 7, 10]], 3, 3) self.assertEqual("|0,0,-4|\n|0,0,0|\n|0,0,-2|\n", str(A - B)) def test_squareZeroMatrix(self) -> None: + """ + test for global function square_zero_matrix() + """ self.assertEqual( - "|0,0,0,0,0|\n|0,0,0,0,0|\n|0,0,0,0,0|\n|0,0,0,0,0|" + "\n|0,0,0,0,0|\n", - str(squareZeroMatrix(5)), + "|0,0,0,0,0|\n|0,0,0,0,0|\n|0,0,0,0,0|\n|0,0,0,0,0|\n|0,0,0,0,0|\n", + str(square_zero_matrix(5)), ) From ce9a139b56735ee05fc21679b6a8e35940c7ca77 Mon Sep 17 00:00:00 2001 From: harshitkap00r <76745800+harshitkap00r@users.noreply.github.com> Date: Wed, 27 Oct 2021 09:55:48 +0530 Subject: [PATCH 146/726] Update binary_search.py (#4856) Take less time to calculate --- searches/binary_search.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/searches/binary_search.py b/searches/binary_search.py index 0966cd8de..88fee4715 100644 --- a/searches/binary_search.py +++ b/searches/binary_search.py @@ -51,7 +51,7 @@ def bisect_left( hi = len(sorted_collection) while lo < hi: - mid = (lo + hi) // 2 + mid = lo + (hi - lo) // 2 if sorted_collection[mid] < item: lo = mid + 1 else: @@ -96,7 +96,7 @@ def bisect_right( hi = len(sorted_collection) while lo < hi: - mid = (lo + hi) // 2 + mid = lo + (hi - lo) // 2 if sorted_collection[mid] <= item: lo = mid + 1 else: From 329feb492843129a285e8ec11b9d0c07c28579ba Mon Sep 17 00:00:00 2001 From: Prakhar Gurunani Date: Wed, 27 Oct 2021 14:49:04 +0530 Subject: [PATCH 147/726] Add Project Euler Problem 078 solution 01 (#5565) * Create sol1.py * updating DIRECTORY.md * Create __init__.py * Add docstring * Reformat with black * Fix flake8 issues * Add EOL * Fix formatting issues * Add docstring * Add func return type * Change return type * Remove test print statement * Reformat code * Fix return types * Break loop * Update doctest sol * Update project_euler/problem_078/sol1.py Co-authored-by: John Law * Added doctest and changed return type * Add int() * Fix flake8 issues * Use argument instead of fixed constant * Update sol1.py * fix sol1.py Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: John Law --- DIRECTORY.md | 2 + project_euler/problem_078/__init__.py | 0 project_euler/problem_078/sol1.py | 55 +++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 project_euler/problem_078/__init__.py create mode 100644 project_euler/problem_078/sol1.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 6fbd5e2cc..c94fb78d6 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -788,6 +788,8 @@ * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_076/sol1.py) * Problem 077 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_077/sol1.py) + * Problem 078 + * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_078/sol1.py) * Problem 080 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_080/sol1.py) * Problem 081 diff --git a/project_euler/problem_078/__init__.py b/project_euler/problem_078/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_078/sol1.py b/project_euler/problem_078/sol1.py new file mode 100644 index 000000000..f92cf0f40 --- /dev/null +++ b/project_euler/problem_078/sol1.py @@ -0,0 +1,55 @@ +""" +Problem 78 +Url: https://projecteuler.net/problem=78 +Statement: +Let p(n) represent the number of different ways in which n coins +can be separated into piles. For example, five coins can be separated +into piles in exactly seven different ways, so p(5)=7. + + OOOOO + OOOO O + OOO OO + OOO O O + OO OO O + OO O O O + O O O O O +Find the least value of n for which p(n) is divisible by one million. +""" + +import itertools + + +def solution(number: int = 1000000) -> int: + """ + >>> solution() + 55374 + """ + partitions = [1] + + for i in itertools.count(len(partitions)): + item = 0 + for j in itertools.count(1): + sign = -1 if j % 2 == 0 else +1 + index = (j * j * 3 - j) // 2 + if index > i: + break + item += partitions[i - index] * sign + index += j + if index > i: + break + item += partitions[i - index] * sign + item %= number + + if item == 0: + return i + partitions.append(item) + + return 0 + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + + print(f"{solution() = }") From 615c428903602bf40d2e15dec44be914409fe804 Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj Date: Wed, 27 Oct 2021 22:00:03 +0530 Subject: [PATCH 148/726] Add doctest for exception (#5629) * Add doctest for exception * Spelling correction --- maths/area.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/maths/area.py b/maths/area.py index 13c05af5f..7b39312cf 100644 --- a/maths/area.py +++ b/maths/area.py @@ -203,6 +203,18 @@ def area_triangle_three_sides(side1: float, side2: float, side3: float) -> float Traceback (most recent call last): ... ValueError: area_triangle_three_sides() only accepts non-negative values + >>> area_triangle_three_sides(2, 4, 7) + Traceback (most recent call last): + ... + ValueError: Given three sides do not form a triangle + >>> area_triangle_three_sides(2, 7, 4) + Traceback (most recent call last): + ... + ValueError: Given three sides do not form a triangle + >>> area_triangle_three_sides(7, 2, 4) + Traceback (most recent call last): + ... + ValueError: Given three sides do not form a triangle """ if side1 < 0 or side2 < 0 or side3 < 0: raise ValueError("area_triangle_three_sides() only accepts non-negative values") From 6b6762bde9e242c21bae147c0e0d56bd072ece96 Mon Sep 17 00:00:00 2001 From: "@im_8055" <38890773+Bhargavishnu@users.noreply.github.com> Date: Wed, 27 Oct 2021 22:48:21 +0530 Subject: [PATCH 149/726] Fix pull request template (#5633) The existing template uses * to apply bold font weight. As we already have the ### to markdown the text as heading, its redundant to have the *s. --- .github/pull_request_template.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 103ecf7c2..4d2265968 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,4 +1,4 @@ -### **Describe your change:** +### Describe your change: @@ -6,7 +6,7 @@ * [ ] Fix a bug or typo in an existing algorithm? * [ ] Documentation change? -### **Checklist:** +### Checklist: * [ ] I have read [CONTRIBUTING.md](https://github.com/TheAlgorithms/Python/blob/master/CONTRIBUTING.md). * [ ] This pull request is all my own work -- I have not plagiarized. * [ ] I know that pull requests will not be merged if they fail the automated tests. From bf6db32ec2fb04b6477722f0809c5efef0cad813 Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Thu, 28 Oct 2021 11:05:31 -0300 Subject: [PATCH 150/726] [mypy] Fix type annotations for binary tree traversals in data structures (#5556) * [mypy] Fix type annotations for binary tree traversals in data structures * Change variable name and update level_order_1 to use a deque Using a deque instead of a list here, because since we are removing from the beginning of the list, the deque will be more efficient. * remove duplicate function * Update data_structures/binary_tree/binary_tree_traversals.py Co-authored-by: John Law * fix function name at line 137 * Update data_structures/binary_tree/binary_tree_traversals.py Co-authored-by: John Law * Update data_structures/binary_tree/binary_tree_traversals.py Co-authored-by: John Law * Remove type alias and use the new syntax * Update data_structures/binary_tree/binary_tree_traversals.py Co-authored-by: John Law * Remove prints inside functions and return lists Co-authored-by: John Law --- .../binary_tree/binary_tree_traversals.py | 158 ++++++++++-------- 1 file changed, 92 insertions(+), 66 deletions(-) diff --git a/data_structures/binary_tree/binary_tree_traversals.py b/data_structures/binary_tree/binary_tree_traversals.py index de9e9d60d..9a6239391 100644 --- a/data_structures/binary_tree/binary_tree_traversals.py +++ b/data_structures/binary_tree/binary_tree_traversals.py @@ -1,7 +1,9 @@ # https://en.wikipedia.org/wiki/Tree_traversal from __future__ import annotations +from collections import deque from dataclasses import dataclass +from typing import Any, Sequence @dataclass @@ -11,11 +13,11 @@ class Node: right: Node | None = None -def make_tree() -> Node: +def make_tree() -> Node | None: return Node(1, Node(2, Node(4), Node(5)), Node(3)) -def preorder(root: Node): +def preorder(root: Node | None) -> list[int]: """ Pre-order traversal visits root node, left subtree, right subtree. >>> preorder(make_tree()) @@ -24,7 +26,7 @@ def preorder(root: Node): return [root.data] + preorder(root.left) + preorder(root.right) if root else [] -def postorder(root: Node): +def postorder(root: Node | None) -> list[int]: """ Post-order traversal visits left subtree, right subtree, root node. >>> postorder(make_tree()) @@ -33,7 +35,7 @@ def postorder(root: Node): return postorder(root.left) + postorder(root.right) + [root.data] if root else [] -def inorder(root: Node): +def inorder(root: Node | None) -> list[int]: """ In-order traversal visits left subtree, root node, right subtree. >>> inorder(make_tree()) @@ -42,7 +44,7 @@ def inorder(root: Node): return inorder(root.left) + [root.data] + inorder(root.right) if root else [] -def height(root: Node): +def height(root: Node | None) -> int: """ Recursive function for calculating the height of the binary tree. >>> height(None) @@ -53,80 +55,99 @@ def height(root: Node): return (max(height(root.left), height(root.right)) + 1) if root else 0 -def level_order_1(root: Node): +def level_order(root: Node | None) -> Sequence[Node | None]: """ - Print whole binary tree in Level Order Traverse. + Returns a list of nodes value from a whole binary tree in Level Order Traverse. Level Order traverse: Visit nodes of the tree level-by-level. """ - if not root: - return - temp = root - que = [temp] - while len(que) > 0: - print(que[0].data, end=" ") - temp = que.pop(0) - if temp.left: - que.append(temp.left) - if temp.right: - que.append(temp.right) - return que + output: list[Any] = [] + + if root is None: + return output + + process_queue = deque([root]) + + while process_queue: + node = process_queue.popleft() + output.append(node.data) + + if node.left: + process_queue.append(node.left) + if node.right: + process_queue.append(node.right) + return output -def level_order_2(root: Node, level: int): +def get_nodes_from_left_to_right( + root: Node | None, level: int +) -> Sequence[Node | None]: """ - Level-wise traversal: Print all nodes present at the given level of the binary tree + Returns a list of nodes value from a particular level: + Left to right direction of the binary tree. """ - if not root: - return root - if level == 1: - print(root.data, end=" ") - elif level > 1: - level_order_2(root.left, level - 1) - level_order_2(root.right, level - 1) + output: list[Any] = [] + + def populate_output(root: Node | None, level: int) -> None: + if not root: + return + if level == 1: + + output.append(root.data) + elif level > 1: + populate_output(root.left, level - 1) + populate_output(root.right, level - 1) + + populate_output(root, level) + return output -def print_left_to_right(root: Node, level: int): +def get_nodes_from_right_to_left( + root: Node | None, level: int +) -> Sequence[Node | None]: """ - Print elements on particular level from left to right direction of the binary tree. + Returns a list of nodes value from a particular level: + Right to left direction of the binary tree. """ - if not root: - return - if level == 1: - print(root.data, end=" ") - elif level > 1: - print_left_to_right(root.left, level - 1) - print_left_to_right(root.right, level - 1) + output: list[Any] = [] + + def populate_output(root: Node | None, level: int) -> None: + if root is None: + return + if level == 1: + output.append(root.data) + elif level > 1: + populate_output(root.right, level - 1) + populate_output(root.left, level - 1) + + populate_output(root, level) + return output -def print_right_to_left(root: Node, level: int): +def zigzag(root: Node | None) -> Sequence[Node | None] | list[Any]: """ - Print elements on particular level from right to left direction of the binary tree. + ZigZag traverse: + Returns a list of nodes value from left to right and right to left, alternatively. """ - if not root: - return - if level == 1: - print(root.data, end=" ") - elif level > 1: - print_right_to_left(root.right, level - 1) - print_right_to_left(root.left, level - 1) + if root is None: + return [] + output: list[Sequence[Node | None]] = [] -def zigzag(root: Node): - """ - ZigZag traverse: Print node left to right and right to left, alternatively. - """ flag = 0 height_tree = height(root) + for h in range(1, height_tree + 1): - if flag == 0: - print_left_to_right(root, h) + if not flag: + output.append(get_nodes_from_left_to_right(root, h)) flag = 1 else: - print_right_to_left(root, h) + output.append(get_nodes_from_right_to_left(root, h)) flag = 0 + return output -def main(): # Main function for testing. + +def main() -> None: # Main function for testing. """ Create binary tree. """ @@ -134,18 +155,23 @@ def main(): # Main function for testing. """ All Traversals of the binary are as follows: """ - print(f" In-order Traversal is {inorder(root)}") - print(f" Pre-order Traversal is {preorder(root)}") - print(f"Post-order Traversal is {postorder(root)}") - print(f"Height of Tree is {height(root)}") - print("Complete Level Order Traversal is : ") - level_order_1(root) - print("\nLevel-wise order Traversal is : ") - for h in range(1, height(root) + 1): - level_order_2(root, h) - print("\nZigZag order Traversal is : ") - zigzag(root) - print() + + print(f"In-order Traversal: {inorder(root)}") + print(f"Pre-order Traversal: {preorder(root)}") + print(f"Post-order Traversal: {postorder(root)}", "\n") + + print(f"Height of Tree: {height(root)}", "\n") + + print("Complete Level Order Traversal: ") + print(level_order(root), "\n") + + print("Level-wise order Traversal: ") + + for level in range(1, height(root) + 1): + print(f"Level {level}:", get_nodes_from_left_to_right(root, level=level)) + + print("\nZigZag order Traversal: ") + print(zigzag(root)) if __name__ == "__main__": From 70368a757e8d37b9f3dd96af4ca535275cb39580 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20A=2E=20Rodr=C3=ADguez?= Date: Thu, 28 Oct 2021 11:43:24 -0300 Subject: [PATCH 151/726] Implement Circular Queue using linked lists. Fixes TheAlgorithms#5361 (#5587) * CircularQueueLinkedList: empty list, trivial implementation TheAlgorithms#5361 * CircularQueueLinkedList: single element list TheAlgorithms#5361 * CircularQueueLinkedList: refactor, no que empty attribute TheAlgorithms#5361 * CircularQueueLinkedList: refactor TheAlgorithms#5361 * CircularQueueLinkedList: changed internal data structure to use double linked list TheAlgorithms#5361 * CircularQueueLinkedList: enqueue test cases added TheAlgorithms#5361 * CircularQueueLinkedList: track full queue TheAlgorithms#5361 * CircularQueueLinkedList: adding functions description TheAlgorithms#5361 * CircularQueueLinkedList: type hints TheAlgorithms#5361 * CircularQueueLinkedList: algorithm explanation TheAlgorithms#5361 * CircularQueueLinkedList: missing type hints TheAlgorithms#5361 * CircularQueueLinkedList: more missing type hints TheAlgorithms#5361 * Update data_structures/queue/circular_queue_linked_list.py Co-authored-by: John Law --- .../queue/circular_queue_linked_list.py | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 data_structures/queue/circular_queue_linked_list.py diff --git a/data_structures/queue/circular_queue_linked_list.py b/data_structures/queue/circular_queue_linked_list.py new file mode 100644 index 000000000..1878403bd --- /dev/null +++ b/data_structures/queue/circular_queue_linked_list.py @@ -0,0 +1,150 @@ +# Implementation of Circular Queue using linked lists +# https://en.wikipedia.org/wiki/Circular_buffer + +from typing import Any + + +class CircularQueueLinkedList: + """ + Circular FIFO list with the given capacity (default queue length : 6) + + >>> cq = CircularQueueLinkedList(2) + >>> cq.enqueue('a') + >>> cq.enqueue('b') + >>> cq.enqueue('c') + Traceback (most recent call last): + ... + Exception: Full Queue + """ + + def __init__(self, initial_capacity: int = 6) -> None: + self.front = None + self.rear = None + self.create_linked_list(initial_capacity) + + def create_linked_list(self, initial_capacity: int) -> None: + current_node = Node() + self.front = current_node + self.rear = current_node + previous_node = current_node + for i in range(1, initial_capacity): + current_node = Node() + previous_node.next = current_node + current_node.prev = previous_node + previous_node = current_node + previous_node.next = self.front + self.front.prev = previous_node + + def is_empty(self) -> bool: + """ + Checks where the queue is empty or not + >>> cq = CircularQueueLinkedList() + >>> cq.is_empty() + True + >>> cq.enqueue('a') + >>> cq.is_empty() + False + >>> cq.dequeue() + 'a' + >>> cq.is_empty() + True + """ + return self.front == self.rear and self.front.data is None + + def first(self) -> Any: + """ + Returns the first element of the queue + >>> cq = CircularQueueLinkedList() + >>> cq.first() + Traceback (most recent call last): + ... + Exception: Empty Queue + >>> cq.enqueue('a') + >>> cq.first() + 'a' + >>> cq.dequeue() + 'a' + >>> cq.first() + Traceback (most recent call last): + ... + Exception: Empty Queue + >>> cq.enqueue('b') + >>> cq.enqueue('c') + >>> cq.first() + 'b' + """ + self.check_can_perform_operation() + return self.front.data + + def enqueue(self, data: Any) -> None: + """ + Saves data at the end of the queue + + >>> cq = CircularQueueLinkedList() + >>> cq.enqueue('a') + >>> cq.enqueue('b') + >>> cq.dequeue() + 'a' + >>> cq.dequeue() + 'b' + >>> cq.dequeue() + Traceback (most recent call last): + ... + Exception: Empty Queue + """ + self.check_is_full() + if self.is_empty(): + self.rear.data = data + else: + self.rear = self.rear.next + self.rear.data = data + + def dequeue(self) -> Any: + """ + Removes and retrieves the first element of the queue + + >>> cq = CircularQueueLinkedList() + >>> cq.dequeue() + Traceback (most recent call last): + ... + Exception: Empty Queue + >>> cq.enqueue('a') + >>> cq.dequeue() + 'a' + >>> cq.dequeue() + Traceback (most recent call last): + ... + Exception: Empty Queue + """ + self.check_can_perform_operation() + if self.front == self.rear: + data = self.front.data + self.front.data = None + return data + + old_front = self.front + self.front = old_front.next + data = old_front.data + old_front.data = None + return data + + def check_can_perform_operation(self) -> None: + if self.is_empty(): + raise Exception("Empty Queue") + + def check_is_full(self) -> None: + if self.rear.next == self.front: + raise Exception("Full Queue") + + +class Node: + def __init__(self) -> None: + self.data = None + self.next = None + self.prev = None + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 477cc3fe597fd931c742700284016b937c778fe1 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 28 Oct 2021 16:45:59 +0200 Subject: [PATCH 152/726] Add pyupgrade to pre-commit (#5638) * Add pyupgrade to pre-commit * Remove unused imports * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .pre-commit-config.yaml | 6 ++++++ DIRECTORY.md | 3 +++ data_structures/binary_tree/merge_two_binary_trees.py | 4 +--- data_structures/linked_list/skip_list.py | 4 ++-- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b666e88aa..e60003051 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,6 +22,12 @@ repos: - id: isort args: - --profile=black + - repo: https://github.com/asottile/pyupgrade + rev: v2.29.0 + hooks: + - id: pyupgrade + args: + - --py39-plus - repo: https://gitlab.com/pycqa/flake8 rev: 3.9.1 hooks: diff --git a/DIRECTORY.md b/DIRECTORY.md index c94fb78d6..2acfff69d 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -126,6 +126,7 @@ * [Molecular Chemistry](https://github.com/TheAlgorithms/Python/blob/master/conversions/molecular_chemistry.py) * [Octal To Decimal](https://github.com/TheAlgorithms/Python/blob/master/conversions/octal_to_decimal.py) * [Prefix Conversions](https://github.com/TheAlgorithms/Python/blob/master/conversions/prefix_conversions.py) + * [Pressure Conversions](https://github.com/TheAlgorithms/Python/blob/master/conversions/pressure_conversions.py) * [Rgb Hsv Conversion](https://github.com/TheAlgorithms/Python/blob/master/conversions/rgb_hsv_conversion.py) * [Roman Numerals](https://github.com/TheAlgorithms/Python/blob/master/conversions/roman_numerals.py) * [Temperature Conversions](https://github.com/TheAlgorithms/Python/blob/master/conversions/temperature_conversions.py) @@ -860,6 +861,8 @@ * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_301/sol1.py) * Problem 551 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_551/sol1.py) + * Problem 686 + * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_686/sol1.py) ## Quantum * [Deutsch Jozsa](https://github.com/TheAlgorithms/Python/blob/master/quantum/deutsch_jozsa.py) diff --git a/data_structures/binary_tree/merge_two_binary_trees.py b/data_structures/binary_tree/merge_two_binary_trees.py index 748726894..3380f8c5f 100644 --- a/data_structures/binary_tree/merge_two_binary_trees.py +++ b/data_structures/binary_tree/merge_two_binary_trees.py @@ -7,8 +7,6 @@ will be used as the node of new tree. """ from __future__ import annotations -from typing import Optional - class Node: """ @@ -21,7 +19,7 @@ class Node: self.right: Node | None = None -def merge_two_binary_trees(tree1: Node | None, tree2: Node | None) -> Optional[Node]: +def merge_two_binary_trees(tree1: Node | None, tree2: Node | None) -> Node | None: """ Returns root node of the merged tree. diff --git a/data_structures/linked_list/skip_list.py b/data_structures/linked_list/skip_list.py index be30592ec..176049120 100644 --- a/data_structures/linked_list/skip_list.py +++ b/data_structures/linked_list/skip_list.py @@ -5,14 +5,14 @@ https://epaperpress.com/sortsearch/download/skiplist.pdf from __future__ import annotations from random import random -from typing import Generic, Optional, TypeVar, Union +from typing import Generic, TypeVar KT = TypeVar("KT") VT = TypeVar("VT") class Node(Generic[KT, VT]): - def __init__(self, key: Union[KT, str] = "root", value: Optional[VT] = None): + def __init__(self, key: KT | str = "root", value: VT | None = None): self.key = key self.value = value self.forward: list[Node[KT, VT]] = [] From 11a15cc5842bb44a81bc8ee56af8f25d92a74287 Mon Sep 17 00:00:00 2001 From: Naveen Namani Date: Thu, 28 Oct 2021 22:57:14 +0530 Subject: [PATCH 153/726] Add solution for Project Euler problem 67 (#5519) * New solution for Euler problem 67 A faster and memory efficient solution based on the template of sol1.py. Modified the solution to be more memory efficient while reading and generating the array and during the solution finding. No conditions and straightforward logic. * added return type hint * Update project_euler/problem_067/sol2.py Preferring comprehensions over map Co-authored-by: Christian Clauss * Update sol2.py Self explanatory variable names * Updated sol2 to problem 067 in directory * Update project_euler/problem_067/sol2.py Co-authored-by: Christian Clauss * Update project_euler/problem_067/sol2.py Co-authored-by: Christian Clauss * Fixed extra line Co-authored-by: Christian Clauss --- DIRECTORY.md | 1 + project_euler/problem_067/sol2.py | 39 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 project_euler/problem_067/sol2.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 2acfff69d..a8986f195 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -771,6 +771,7 @@ * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_065/sol1.py) * Problem 067 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_067/sol1.py) + * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_067/sol2.py) * Problem 069 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_069/sol1.py) * Problem 070 diff --git a/project_euler/problem_067/sol2.py b/project_euler/problem_067/sol2.py new file mode 100644 index 000000000..2e88a5717 --- /dev/null +++ b/project_euler/problem_067/sol2.py @@ -0,0 +1,39 @@ +""" +Problem Statement: +By starting at the top of the triangle below and moving to adjacent numbers on +the row below, the maximum total from top to bottom is 23. +3 +7 4 +2 4 6 +8 5 9 3 +That is, 3 + 7 + 4 + 9 = 23. +Find the maximum total from top to bottom in triangle.txt (right click and +'Save Link/Target As...'), a 15K text file containing a triangle with +one-hundred rows. +""" +import os + + +def solution() -> int: + """ + Finds the maximum total in a triangle as described by the problem statement + above. + >>> solution() + 7273 + """ + script_dir = os.path.dirname(os.path.realpath(__file__)) + triangle_path = os.path.join(script_dir, "triangle.txt") + + with open(triangle_path) as in_file: + triangle = [[int(i) for i in line.split()] for line in in_file] + + while len(triangle) != 1: + last_row = triangle.pop() + curr_row = triangle[-1] + for j in range(len(last_row) - 1): + curr_row[j] += max(last_row[j], last_row[j + 1]) + return triangle[0][0] + + +if __name__ == "__main__": + print(solution()) From 61e1dd27b0db00302cec75fca5365d08e81ab707 Mon Sep 17 00:00:00 2001 From: poloso Date: Thu, 28 Oct 2021 15:31:32 -0500 Subject: [PATCH 154/726] [mypy] Fix type annotation in euler_method.py (#5649) * [mypy] Fix type annotation in euler_method.py In line with issue #4052. * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 1 + maths/euler_method.py | 27 +++++++++++++++++---------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index a8986f195..434cddbfd 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -186,6 +186,7 @@ * [Swap Nodes](https://github.com/TheAlgorithms/Python/blob/master/data_structures/linked_list/swap_nodes.py) * Queue * [Circular Queue](https://github.com/TheAlgorithms/Python/blob/master/data_structures/queue/circular_queue.py) + * [Circular Queue Linked List](https://github.com/TheAlgorithms/Python/blob/master/data_structures/queue/circular_queue_linked_list.py) * [Double Ended Queue](https://github.com/TheAlgorithms/Python/blob/master/data_structures/queue/double_ended_queue.py) * [Linked Queue](https://github.com/TheAlgorithms/Python/blob/master/data_structures/queue/linked_queue.py) * [Priority Queue Using List](https://github.com/TheAlgorithms/Python/blob/master/data_structures/queue/priority_queue_using_list.py) diff --git a/maths/euler_method.py b/maths/euler_method.py index 7c7801986..155ef28d1 100644 --- a/maths/euler_method.py +++ b/maths/euler_method.py @@ -1,18 +1,25 @@ +from typing import Callable + import numpy as np -def explicit_euler(ode_func, y0, x0, step_size, x_end): - """ - Calculate numeric solution at each step to an ODE using Euler's Method +def explicit_euler( + ode_func: Callable, y0: float, x0: float, step_size: float, x_end: float +) -> np.ndarray: + """Calculate numeric solution at each step to an ODE using Euler's Method - https://en.wikipedia.org/wiki/Euler_method + For reference to Euler's method refer to https://en.wikipedia.org/wiki/Euler_method. - Arguments: - ode_func -- The ode as a function of x and y - y0 -- the initial value for y - x0 -- the initial value for x - stepsize -- the increment value for x - x_end -- the end value for x + Args: + ode_func (Callable): The ordinary differential equation + as a function of x and y. + y0 (float): The initial value for y. + x0 (float): The initial value for x. + step_size (float): The increment value for x. + x_end (float): The final value of x to be calculated. + + Returns: + np.ndarray: Solution of y for every step in x. >>> # the exact solution is math.exp(x) >>> def f(x, y): From 0590d736fa61833c8f8591f7aa3bbea88b8274f9 Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Thu, 28 Oct 2021 17:53:02 -0300 Subject: [PATCH 155/726] [mypy] Fix type annotations in `wavelet_tree.py` (#5641) * [mypy] Fix type annotations for wavelet_tree.py * fix a typo --- data_structures/binary_tree/wavelet_tree.py | 22 ++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/data_structures/binary_tree/wavelet_tree.py b/data_structures/binary_tree/wavelet_tree.py index 173a88ab7..8d7145189 100644 --- a/data_structures/binary_tree/wavelet_tree.py +++ b/data_structures/binary_tree/wavelet_tree.py @@ -31,7 +31,7 @@ class Node: return f"min_value: {self.minn}, max_value: {self.maxx}" -def build_tree(arr: list[int]) -> Node: +def build_tree(arr: list[int]) -> Node | None: """ Builds the tree for arr and returns the root of the constructed tree @@ -51,7 +51,10 @@ def build_tree(arr: list[int]) -> Node: then recursively build trees for left_arr and right_arr """ pivot = (root.minn + root.maxx) // 2 - left_arr, right_arr = [], [] + + left_arr: list[int] = [] + right_arr: list[int] = [] + for index, num in enumerate(arr): if num <= pivot: left_arr.append(num) @@ -63,7 +66,7 @@ def build_tree(arr: list[int]) -> Node: return root -def rank_till_index(node: Node, num: int, index: int) -> int: +def rank_till_index(node: Node | None, num: int, index: int) -> int: """ Returns the number of occurrences of num in interval [0, index] in the list @@ -79,7 +82,7 @@ def rank_till_index(node: Node, num: int, index: int) -> int: >>> rank_till_index(root, 0, 9) 1 """ - if index < 0: + if index < 0 or node is None: return 0 # Leaf node cases if node.minn == node.maxx: @@ -93,7 +96,7 @@ def rank_till_index(node: Node, num: int, index: int) -> int: return rank_till_index(node.right, num, index - node.map_left[index]) -def rank(node: Node, num: int, start: int, end: int) -> int: +def rank(node: Node | None, num: int, start: int, end: int) -> int: """ Returns the number of occurrences of num in interval [start, end] in the list @@ -114,7 +117,7 @@ def rank(node: Node, num: int, start: int, end: int) -> int: return rank_till_end - rank_before_start -def quantile(node: Node, index: int, start: int, end: int) -> int: +def quantile(node: Node | None, index: int, start: int, end: int) -> int: """ Returns the index'th smallest element in interval [start, end] in the list index is 0-indexed @@ -129,7 +132,7 @@ def quantile(node: Node, index: int, start: int, end: int) -> int: >>> quantile(root, 4, 2, 5) -1 """ - if index > (end - start) or start > end: + if index > (end - start) or start > end or node is None: return -1 # Leaf node case if node.minn == node.maxx: @@ -155,10 +158,10 @@ def quantile(node: Node, index: int, start: int, end: int) -> int: def range_counting( - node: Node, start: int, end: int, start_num: int, end_num: int + node: Node | None, start: int, end: int, start_num: int, end_num: int ) -> int: """ - Returns the number of elememts in range [start_num, end_num] + Returns the number of elements in range [start_num, end_num] in interval [start, end] in the list >>> root = build_tree(test_array) @@ -175,6 +178,7 @@ def range_counting( """ if ( start > end + or node is None or start_num > end_num or node.minn > end_num or node.maxx < start_num From 5c8a6c824723e248047ed6eddfad1a4305de7696 Mon Sep 17 00:00:00 2001 From: Marcus T Date: Thu, 28 Oct 2021 19:53:39 -0400 Subject: [PATCH 156/726] Add Pollard's Rho algorithm for integer factorization (#5598) --- maths/pollard_rho.py | 148 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 maths/pollard_rho.py diff --git a/maths/pollard_rho.py b/maths/pollard_rho.py new file mode 100644 index 000000000..df020c63f --- /dev/null +++ b/maths/pollard_rho.py @@ -0,0 +1,148 @@ +from math import gcd +from typing import Union + + +def pollard_rho( + num: int, + seed: int = 2, + step: int = 1, + attempts: int = 3, +) -> Union[int, None]: + """ + Use Pollard's Rho algorithm to return a nontrivial factor of ``num``. + The returned factor may be composite and require further factorization. + If the algorithm will return None if it fails to find a factor within + the specified number of attempts or within the specified number of steps. + If ``num`` is prime, this algorithm is guaranteed to return None. + https://en.wikipedia.org/wiki/Pollard%27s_rho_algorithm + + >>> pollard_rho(18446744073709551617) + 274177 + >>> pollard_rho(97546105601219326301) + 9876543191 + >>> pollard_rho(100) + 2 + >>> pollard_rho(17) + >>> pollard_rho(17**3) + 17 + >>> pollard_rho(17**3, attempts=1) + >>> pollard_rho(3*5*7) + 21 + >>> pollard_rho(1) + Traceback (most recent call last): + ... + ValueError: The input value cannot be less than 2 + """ + # A value less than 2 can cause an infinite loop in the algorithm. + if num < 2: + raise ValueError("The input value cannot be less than 2") + + # Because of the relationship between ``f(f(x))`` and ``f(x)``, this + # algorithm struggles to find factors that are divisible by two. + # As a workaround, we specifically check for two and even inputs. + # See: https://math.stackexchange.com/a/2856214/165820 + if num > 2 and num % 2 == 0: + return 2 + + # Pollard's Rho algorithm requires a function that returns pseudorandom + # values between 0 <= X < ``num``. It doesn't need to be random in the + # sense that the output value is cryptographically secure or difficult + # to calculate, it only needs to be random in the sense that all output + # values should be equally likely to appear. + # For this reason, Pollard suggested using ``f(x) = (x**2 - 1) % num`` + # However, the success of Pollard's algorithm isn't guaranteed and is + # determined in part by the initial seed and the chosen random function. + # To make retries easier, we will instead use ``f(x) = (x**2 + C) % num`` + # where ``C`` is a value that we can modify between each attempt. + def rand_fn(value: int, step: int, modulus: int) -> int: + """ + Returns a pseudorandom value modulo ``modulus`` based on the + input ``value`` and attempt-specific ``step`` size. + + >>> rand_fn(0, 0, 0) + Traceback (most recent call last): + ... + ZeroDivisionError: integer division or modulo by zero + >>> rand_fn(1, 2, 3) + 0 + >>> rand_fn(0, 10, 7) + 3 + >>> rand_fn(1234, 1, 17) + 16 + """ + return (pow(value, 2) + step) % modulus + + for attempt in range(attempts): + # These track the position within the cycle detection logic. + tortoise = seed + hare = seed + + while True: + # At each iteration, the tortoise moves one step and the hare moves two. + tortoise = rand_fn(tortoise, step, num) + hare = rand_fn(hare, step, num) + hare = rand_fn(hare, step, num) + + # At some point both the tortoise and the hare will enter a cycle whose + # length ``p`` is a divisor of ``num``. Once in that cycle, at some point + # the tortoise and hare will end up on the same value modulo ``p``. + # We can detect when this happens because the position difference between + # the tortoise and the hare will share a common divisor with ``num``. + divisor = gcd(hare - tortoise, num) + + if divisor == 1: + # No common divisor yet, just keep searching. + continue + else: + # We found a common divisor! + if divisor == num: + # Unfortunately, the divisor is ``num`` itself and is useless. + break + else: + # The divisor is a nontrivial factor of ``num``! + return divisor + + # If we made it here, then this attempt failed. + # We need to pick a new starting seed for the tortoise and hare + # in addition to a new step value for the random function. + # To keep this example implementation deterministic, the + # new values will be generated based on currently available + # values instead of using something like ``random.randint``. + + # We can use the hare's position as the new seed. + # This is actually what Richard Brent's the "optimized" variant does. + seed = hare + + # The new step value for the random function can just be incremented. + # At first the results will be similar to what the old function would + # have produced, but the value will quickly diverge after a bit. + step += 1 + + # We haven't found a divisor within the requested number of attempts. + # We were unlucky or ``num`` itself is actually prime. + return None + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument( + "num", + type=int, + help="The value to find a divisor of", + ) + parser.add_argument( + "--attempts", + type=int, + default=3, + help="The number of attempts before giving up", + ) + args = parser.parse_args() + + divisor = pollard_rho(args.num, attempts=args.attempts) + if divisor is None: + print(f"{args.num} is probably prime") + else: + quotient = args.num // divisor + print(f"{args.num} = {divisor} * {quotient}") From 0fc24e86296c613f5aa24015518a9f187a2cdbb6 Mon Sep 17 00:00:00 2001 From: Andrew Grangaard Date: Thu, 28 Oct 2021 22:21:16 -0700 Subject: [PATCH 157/726] [mypy] Annotates other/scoring_algorithm (#5621) * scoring_algorithm: Moves doctest into function docstring so it will be run * [mypy] annotates other/scoring_algorithm * [mypy] renames temp var to unique value to work around mypy issue in other/scoring_algorithm reusing loop variables with the same name and different types gives this very confusing mypy error response. pyright correctly infers the types without issue. ``` scoring_algorithm.py:58: error: Incompatible types in assignment (expression has type "float", variable has type "List[float]") scoring_algorithm.py:60: error: Unsupported operand types for - ("List[float]" and "float") scoring_algorithm.py:65: error: Incompatible types in assignment (expression has type "float", variable has type "List[float]") scoring_algorithm.py:67: error: Unsupported operand types for - ("List[float]" and "float") Found 4 errors in 1 file (checked 1 source file) ``` * scoring_algorithm: uses enumeration instead of manual indexing on loop var * scoring_algorithm: sometimes we look before we leap. * clean-up: runs `black` to fix formatting --- other/scoring_algorithm.py | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/other/scoring_algorithm.py b/other/scoring_algorithm.py index 77e614e26..cc1744012 100644 --- a/other/scoring_algorithm.py +++ b/other/scoring_algorithm.py @@ -20,39 +20,38 @@ We want the vehicle with the lowest price, lowest mileage but newest registration year. Thus the weights for each column are as follows: [0, 0, 1] - ->>> procentual_proximity([[20, 60, 2012],[23, 90, 2015],[22, 50, 2011]], [0, 0, 1]) -[[20, 60, 2012, 2.0], [23, 90, 2015, 1.0], [22, 50, 2011, 1.3333333333333335]] """ -def procentual_proximity(source_data: list, weights: list) -> list: +def procentual_proximity( + source_data: list[list[float]], weights: list[int] +) -> list[list[float]]: """ weights - int list possible values - 0 / 1 0 if lower values have higher weight in the data set 1 if higher values have higher weight in the data set + + >>> procentual_proximity([[20, 60, 2012],[23, 90, 2015],[22, 50, 2011]], [0, 0, 1]) + [[20, 60, 2012, 2.0], [23, 90, 2015, 1.0], [22, 50, 2011, 1.3333333333333335]] """ # getting data - data_lists = [] - for item in source_data: - for i in range(len(item)): - try: - data_lists[i].append(float(item[i])) - except IndexError: - # generate corresponding number of lists + data_lists: list[list[float]] = [] + for data in source_data: + for i, el in enumerate(data): + if len(data_lists) < i + 1: data_lists.append([]) - data_lists[i].append(float(item[i])) + data_lists[i].append(float(el)) - score_lists = [] + score_lists: list[list[float]] = [] # calculating each score for dlist, weight in zip(data_lists, weights): mind = min(dlist) maxd = max(dlist) - score = [] + score: list[float] = [] # for weight 0 score is 1 - actual score if weight == 0: for item in dlist: @@ -75,7 +74,7 @@ def procentual_proximity(source_data: list, weights: list) -> list: score_lists.append(score) # initialize final scores - final_scores = [0 for i in range(len(score_lists[0]))] + final_scores: list[float] = [0 for i in range(len(score_lists[0]))] # generate final scores for i, slist in enumerate(score_lists): From a281151a2c0140dda718186cf82329168e65cf96 Mon Sep 17 00:00:00 2001 From: Andrew Grangaard Date: Fri, 29 Oct 2021 00:22:57 -0700 Subject: [PATCH 158/726] Delete other/date_to_weekday.py as a how-to-use, not an algorithm (#5591) * [mypy] Fixes typing errors in other/date_to_weekday * [mypy] uses future annotation style for other/date_to_weekly * date_to_weekday: new implementation replaces buggy original * date_to_weekday: add examples from multiple of 100 years * clean-up: runs `black` to fix formatting * Delete date_to_weekday.py Co-authored-by: Christian Clauss --- other/date_to_weekday.py | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 other/date_to_weekday.py diff --git a/other/date_to_weekday.py b/other/date_to_weekday.py deleted file mode 100644 index 9dc68666e..000000000 --- a/other/date_to_weekday.py +++ /dev/null @@ -1,27 +0,0 @@ -from calendar import day_name -from datetime import datetime - - -def date_to_weekday(inp_date: str) -> str: - """ - It returns the day name of the given date string. - :param inp_date: - :return: String - >>> date_to_weekday("7/8/2035") - 'Tuesday' - >>> date_to_weekday("7/8/2021") - 'Saturday' - >>> date_to_weekday("1/1/2021") - 'Friday' - """ - 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" - date_time_obj: datetime.date = datetime.strptime(new_base_date, "%d/%m/%y %H:%M:%S") - out_put_day: int = date_time_obj.weekday() - return day_name[out_put_day] - - -if __name__ == "__main__": - print(date_to_weekday("1/1/2021"), end=" ") From 3a4cc7e31084e15cf2cce24038957c686d41a1b3 Mon Sep 17 00:00:00 2001 From: Shriyans Gandhi <41372639+shri30yans@users.noreply.github.com> Date: Fri, 29 Oct 2021 13:09:32 +0530 Subject: [PATCH 159/726] Hexagonal number sequence (#5640) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Hexagonal number sequence A hexagonal number sequence is a sequence of figurate numbers where the nth hexagonal number hₙ is the number of distinct dots in a pattern of dots consisting of the outlines of regular hexagons with sides up to n dots, when the hexagons are overlaid so that they share one vertex. This program returns the hexagonal number sequence of n length. * Update hexagonalnumbers.py * Update hexagonalnumbers.py * Update hexagonalnumbers.py * Update hexagonalnumbers.py * Update and rename hexagonalnumbers.py to hexagonal_numbers.py * Length must be a positive integer Co-authored-by: Christian Clauss --- maths/series/hexagonal_numbers.py | 42 +++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 maths/series/hexagonal_numbers.py diff --git a/maths/series/hexagonal_numbers.py b/maths/series/hexagonal_numbers.py new file mode 100644 index 000000000..582b1989b --- /dev/null +++ b/maths/series/hexagonal_numbers.py @@ -0,0 +1,42 @@ +""" +A hexagonal number sequence is a sequence of figurate numbers +where the nth hexagonal number hₙ is the number of distinct dots +in a pattern of dots consisting of the outlines of regular +hexagons with sides up to n dots, when the hexagons are overlaid +so that they share one vertex. + + Calculates the hexagonal numbers sequence with a formula + hₙ = n(2n-1) + where: + hₙ --> is nth element of the sequence + n --> is the number of element in the sequence + reference-->"Hexagonal number" Wikipedia + +""" + + +def hexagonal_numbers(length: int) -> list[int]: + """ + :param len: max number of elements + :type len: int + :return: Hexagonal numbers as a list + + Tests: + >>> hexagonal_numbers(10) + [0, 1, 6, 15, 28, 45, 66, 91, 120, 153] + >>> hexagonal_numbers(5) + [0, 1, 6, 15, 28] + >>> hexagonal_numbers(0) + Traceback (most recent call last): + ... + ValueError: Length must be a positive integer. + """ + + if length <= 0 or not isinstance(length, int): + raise ValueError("Length must be a positive integer.") + return [n * (2 * n - 1) for n in range(length)] + + +if __name__ == "__main__": + print(hexagonal_numbers(length=5)) + print(hexagonal_numbers(length=10)) From e6cf13cc03475b3a5e7e3d3bf4723c37c3063dde Mon Sep 17 00:00:00 2001 From: Casper Rysgaard Date: Sat, 30 Oct 2021 13:06:25 +0200 Subject: [PATCH 160/726] Update queue implementation (#5388) * Update queue implementation Popping the first element of a list takes O(n) time. Using a cyclic queue takes O(1) time. * Add queue changes from extra files * Update indentation * Add empty line between imports * Fix lines * Apply suggestions from code review Co-authored-by: John Law Co-authored-by: John Law --- graphs/breadth_first_search.py | 12 +++++++----- graphs/breadth_first_search_2.py | 11 +++++++---- graphs/check_bipartite_graph_bfs.py | 13 ++++++++----- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/graphs/breadth_first_search.py b/graphs/breadth_first_search.py index 7c626429e..9264f57b4 100644 --- a/graphs/breadth_first_search.py +++ b/graphs/breadth_first_search.py @@ -3,6 +3,8 @@ """ Author: OMKAR PATHAK """ from __future__ import annotations +from queue import Queue + class Graph: def __init__(self) -> None: @@ -51,19 +53,19 @@ class Graph: visited = set() # create a first in first out queue to store all the vertices for BFS - queue = [] + queue = Queue() # mark the source node as visited and enqueue it visited.add(start_vertex) - queue.append(start_vertex) + queue.put(start_vertex) - while queue: - vertex = queue.pop(0) + while not queue.empty(): + vertex = queue.get() # loop through all adjacent vertex and enqueue it if not yet visited for adjacent_vertex in self.vertices[vertex]: if adjacent_vertex not in visited: - queue.append(adjacent_vertex) + queue.put(adjacent_vertex) visited.add(adjacent_vertex) return visited diff --git a/graphs/breadth_first_search_2.py b/graphs/breadth_first_search_2.py index a90e963a4..4c8b69faf 100644 --- a/graphs/breadth_first_search_2.py +++ b/graphs/breadth_first_search_2.py @@ -14,6 +14,8 @@ while Q is non-empty: """ from __future__ import annotations +from queue import Queue + G = { "A": ["B", "C"], "B": ["A", "D", "E"], @@ -30,13 +32,14 @@ def breadth_first_search(graph: dict, start: str) -> set[str]: 'ABCDEF' """ explored = {start} - queue = [start] - while queue: - v = queue.pop(0) # queue.popleft() + queue = Queue() + queue.put(start) + while not queue.empty(): + v = queue.get() for w in graph[v]: if w not in explored: explored.add(w) - queue.append(w) + queue.put(w) return explored diff --git a/graphs/check_bipartite_graph_bfs.py b/graphs/check_bipartite_graph_bfs.py index 00b771649..b5203b4c5 100644 --- a/graphs/check_bipartite_graph_bfs.py +++ b/graphs/check_bipartite_graph_bfs.py @@ -6,14 +6,17 @@ # from V to U. In other words, for every edge (u, v), either u belongs to U and v to V, # or u belongs to V and v to U. We can also say that there is no edge that connects # vertices of same set. +from queue import Queue + + def checkBipartite(graph): - queue = [] + queue = Queue() visited = [False] * len(graph) color = [-1] * len(graph) def bfs(): - while queue: - u = queue.pop(0) + while not queue.empty(): + u = queue.get() visited[u] = True for neighbour in graph[u]: @@ -23,7 +26,7 @@ def checkBipartite(graph): if color[neighbour] == -1: color[neighbour] = 1 - color[u] - queue.append(neighbour) + queue.put(neighbour) elif color[neighbour] == color[u]: return False @@ -32,7 +35,7 @@ def checkBipartite(graph): for i in range(len(graph)): if not visited[i]: - queue.append(i) + queue.put(i) color[i] = 0 if bfs() is False: return False From e7565f8bfc276e0d58d609f6c39f39b80b92a4a2 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sat, 30 Oct 2021 22:36:12 +0300 Subject: [PATCH 161/726] Improve Project Euler problem 070 solution 1 (#5166) * Change has_same_digits doctest * Improve has_same_digits function --- project_euler/problem_070/sol1.py | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/project_euler/problem_070/sol1.py b/project_euler/problem_070/sol1.py index e106800d5..d42b017cc 100644 --- a/project_euler/problem_070/sol1.py +++ b/project_euler/problem_070/sol1.py @@ -60,34 +60,16 @@ def has_same_digits(num1: int, num2: int) -> bool: Return True if num1 and num2 have the same frequency of every digit, False otherwise. - digits[] is a frequency table where the index represents the digit from - 0-9, and the element stores the number of appearances. Increment the - respective index every time you see the digit in num1, and decrement if in - num2. At the end, if the numbers have the same digits, every index must - contain 0. - >>> has_same_digits(123456789, 987654321) True - >>> has_same_digits(123, 12) + >>> has_same_digits(123, 23) False >>> has_same_digits(1234566, 123456) False """ - digits = [0] * 10 - - while num1 > 0 and num2 > 0: - digits[num1 % 10] += 1 - digits[num2 % 10] -= 1 - num1 //= 10 - num2 //= 10 - - for digit in digits: - if digit != 0: - return False - - return True + return sorted(str(num1)) == sorted(str(num2)) def solution(max: int = 10000000) -> int: From 678535b5c83302ee25b8a135b977c7e48b8f8668 Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Sat, 30 Oct 2021 16:43:48 -0300 Subject: [PATCH 162/726] [mypy] Fix type annotations in non_recursive_segment_tree (#5652) --- .../binary_tree/non_recursive_segment_tree.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/data_structures/binary_tree/non_recursive_segment_tree.py b/data_structures/binary_tree/non_recursive_segment_tree.py index c914079e0..b04a6e5ca 100644 --- a/data_structures/binary_tree/non_recursive_segment_tree.py +++ b/data_structures/binary_tree/non_recursive_segment_tree.py @@ -37,12 +37,12 @@ https://www.geeksforgeeks.org/segment-tree-efficient-implementation/ """ from __future__ import annotations -from typing import Callable, TypeVar +from typing import Any, Callable, Generic, TypeVar T = TypeVar("T") -class SegmentTree: +class SegmentTree(Generic[T]): def __init__(self, arr: list[T], fnc: Callable[[T, T], T]) -> None: """ Segment Tree constructor, it works just with commutative combiner. @@ -55,8 +55,10 @@ class SegmentTree: ... lambda a, b: (a[0] + b[0], a[1] + b[1])).query(0, 2) (6, 9) """ - self.N = len(arr) - self.st = [None for _ in range(len(arr))] + arr + any_type: Any | T = None + + self.N: int = len(arr) + self.st: list[T] = [any_type for _ in range(self.N)] + arr self.fn = fnc self.build() @@ -83,7 +85,7 @@ class SegmentTree: p = p // 2 self.st[p] = self.fn(self.st[p * 2], self.st[p * 2 + 1]) - def query(self, l: int, r: int) -> T: # noqa: E741 + def query(self, l: int, r: int) -> T | None: # noqa: E741 """ Get range query value in log(N) time :param l: left element index @@ -101,7 +103,8 @@ class SegmentTree: 7 """ l, r = l + self.N, r + self.N # noqa: E741 - res = None + + res: T | None = None while l <= r: # noqa: E741 if l % 2 == 1: res = self.st[l] if res is None else self.fn(res, self.st[l]) @@ -135,7 +138,7 @@ if __name__ == "__main__": max_segment_tree = SegmentTree(test_array, max) sum_segment_tree = SegmentTree(test_array, lambda a, b: a + b) - def test_all_segments(): + def test_all_segments() -> None: """ Test all possible segments """ From 359e0e795e7e0efa4212a3c94fb482e128bc63eb Mon Sep 17 00:00:00 2001 From: Mitheel <81575947+mitheelgajare@users.noreply.github.com> Date: Sun, 31 Oct 2021 01:18:50 +0530 Subject: [PATCH 163/726] Fixed grammatical errors in CONTRIBUTING.md (#5635) --- CONTRIBUTING.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f5c123674..4df60ed3f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -67,7 +67,7 @@ pre-commit run --all-files --show-diff-on-failure We want your work to be readable by others; therefore, we encourage you to note the following: - Please write in Python 3.9+. For instance: `print()` is a function in Python 3 so `print "Hello"` will *not* work but `print("Hello")` will. -- Please focus hard on naming of functions, classes, and variables. Help your reader by using __descriptive names__ that can help you to remove redundant comments. +- Please focus hard on the naming of functions, classes, and variables. Help your reader by using __descriptive names__ that can help you to remove redundant comments. - Single letter variable names are *old school* so please avoid them unless their life only spans a few lines. - Expand acronyms because `gcd()` is hard to understand but `greatest_common_divisor()` is not. - Please follow the [Python Naming Conventions](https://pep8.org/#prescriptive-naming-conventions) so variable_names and function_names should be lower_case, CONSTANTS in UPPERCASE, ClassNames should be CamelCase, etc. @@ -102,7 +102,7 @@ We want your work to be readable by others; therefore, we encourage you to note This is too trivial. Comments are expected to be explanatory. For comments, you can write them above, on or below a line of code, as long as you are consistent within the same piece of code. - We encourage you to put docstrings inside your functions but please pay attention to indentation of docstrings. The following is a good example: + We encourage you to put docstrings inside your functions but please pay attention to the indentation of docstrings. The following is a good example: ```python def sum_ab(a, b): @@ -160,7 +160,7 @@ We want your work to be readable by others; therefore, we encourage you to note - [__List comprehensions and generators__](https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions) are preferred over the use of `lambda`, `map`, `filter`, `reduce` but the important thing is to demonstrate the power of Python in code that is easy to read and maintain. - Avoid importing external libraries for basic algorithms. Only use those libraries for complicated algorithms. -- If you need a third party module that is not in the file __requirements.txt__, please add it to that file as part of your submission. +- If you need a third-party module that is not in the file __requirements.txt__, please add it to that file as part of your submission. #### Other Requirements for Submissions - If you are submitting code in the `project_euler/` directory, please also read [the dedicated Guideline](https://github.com/TheAlgorithms/Python/blob/master/project_euler/README.md) before contributing to our Project Euler library. @@ -172,7 +172,7 @@ We want your work to be readable by others; therefore, we encourage you to note - If you have modified/added documentation work, ensure your language is concise and contains no grammar errors. - Do not update the README.md or DIRECTORY.md file which will be periodically autogenerated by our Travis CI processes. - Add a corresponding explanation to [Algorithms-Explanation](https://github.com/TheAlgorithms/Algorithms-Explanation) (Optional but recommended). -- All submissions will be tested with [__mypy__](http://www.mypy-lang.org) so we encourage to add [__Python type hints__](https://docs.python.org/3/library/typing.html) where it makes sense to do so. +- All submissions will be tested with [__mypy__](http://www.mypy-lang.org) so we encourage you to add [__Python type hints__](https://docs.python.org/3/library/typing.html) where it makes sense to do so. - Most importantly, - __Be consistent in the use of these guidelines when submitting.__ From 21c99d2ae294d08893bd0160cd9aacc2ad3ca556 Mon Sep 17 00:00:00 2001 From: Navpreet Singh Devpuri Date: Sun, 31 Oct 2021 01:34:46 +0530 Subject: [PATCH 164/726] added is_contains_unique_chars() (#5701) * added is_contains_unique_chars() * added is_contains_unique_chars() * added stackoverflow reference --- strings/is_contains_unique_chars.py | 31 +++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 strings/is_contains_unique_chars.py diff --git a/strings/is_contains_unique_chars.py b/strings/is_contains_unique_chars.py new file mode 100644 index 000000000..fdf7a02ff --- /dev/null +++ b/strings/is_contains_unique_chars.py @@ -0,0 +1,31 @@ +def is_contains_unique_chars(input_str: str) -> bool: + """ + Check if all characters in the string is unique or not. + >>> is_contains_unique_chars("I_love.py") + True + >>> is_contains_unique_chars("I don't love Python") + False + + Time complexity: O(n) + Space compexity: O(1) 19320 bytes as we are having 144697 characters in unicode + """ + + # Each bit will represent each unicode character + # For example 65th bit representing 'A' + # https://stackoverflow.com/a/12811293 + bitmap = 0 + for ch in input_str: + ch_unicode = ord(ch) + ch_bit_index_on = pow(2, ch_unicode) + + # If we already turned on bit for current character's unicode + if bitmap >> ch_unicode & 1 == 1: + return False + bitmap |= ch_bit_index_on + return True + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 99983c91ca26e8cf592699dd320e0d58140cfe41 Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Sun, 31 Oct 2021 05:38:24 -0300 Subject: [PATCH 165/726] [mypy] Add/fix type annotations in `data_structures/heap/skew_heap.py` (#5634) * Add abstract base class Comparable * [mypy] Fix type annotations (strict mode) * Fix a typo * Remove Comparable class and set bound to bool --- data_structures/heap/skew_heap.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/data_structures/heap/skew_heap.py b/data_structures/heap/skew_heap.py index b59441389..16ddc5545 100644 --- a/data_structures/heap/skew_heap.py +++ b/data_structures/heap/skew_heap.py @@ -2,9 +2,9 @@ from __future__ import annotations -from typing import Generic, Iterable, Iterator, TypeVar +from typing import Any, Generic, Iterable, Iterator, TypeVar -T = TypeVar("T") +T = TypeVar("T", bound=bool) class SkewNode(Generic[T]): @@ -51,7 +51,7 @@ class SkewHeap(Generic[T]): values. Both operations take O(logN) time where N is the size of the structure. Wiki: https://en.wikipedia.org/wiki/Skew_heap - Visualisation: https://www.cs.usfca.edu/~galles/visualization/SkewHeap.html + Visualization: https://www.cs.usfca.edu/~galles/visualization/SkewHeap.html >>> list(SkewHeap([2, 3, 1, 5, 1, 7])) [1, 1, 2, 3, 5, 7] @@ -70,14 +70,16 @@ class SkewHeap(Generic[T]): """ def __init__(self, data: Iterable[T] | None = ()) -> None: + """ >>> sh = SkewHeap([3, 1, 3, 7]) >>> list(sh) [1, 3, 3, 7] """ self._root: SkewNode[T] | None = None - for item in data: - self.insert(item) + if data: + for item in data: + self.insert(item) def __bool__(self) -> bool: """ @@ -103,7 +105,7 @@ class SkewHeap(Generic[T]): >>> list(sh) [1, 3, 3, 7] """ - result = [] + result: list[Any] = [] while self: result.append(self.pop()) @@ -127,7 +129,7 @@ class SkewHeap(Generic[T]): """ self._root = SkewNode.merge(self._root, SkewNode(value)) - def pop(self) -> T: + def pop(self) -> T | None: """ Pop the smallest value from the heap and return it. @@ -146,7 +148,9 @@ class SkewHeap(Generic[T]): IndexError: Can't get top element for the empty heap. """ result = self.top() - self._root = SkewNode.merge(self._root.left, self._root.right) + self._root = ( + SkewNode.merge(self._root.left, self._root.right) if self._root else None + ) return result @@ -172,7 +176,7 @@ class SkewHeap(Generic[T]): raise IndexError("Can't get top element for the empty heap.") return self._root.value - def clear(self): + def clear(self) -> None: """ Clear the heap. From a94c6214ff33def88d9363de935263e3145fc96a Mon Sep 17 00:00:00 2001 From: "@im_8055" <38890773+Bhargavishnu@users.noreply.github.com> Date: Sun, 31 Oct 2021 16:06:03 +0530 Subject: [PATCH 166/726] Fix spellings (#5710) --- strings/credit_card_validator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/strings/credit_card_validator.py b/strings/credit_card_validator.py index 3a08c4117..78bf45740 100644 --- a/strings/credit_card_validator.py +++ b/strings/credit_card_validator.py @@ -71,7 +71,7 @@ def validate_credit_card_number(credit_card_number: str) -> bool: 36111111111111 is an invalid credit card number because of its first two digits. False >>> validate_credit_card_number('41111111111111') - 41111111111111 is an invalid credit card number because it fails the Lhun check. + 41111111111111 is an invalid credit card number because it fails the Luhn check. False """ error_message = f"{credit_card_number} is an invalid credit card number because" @@ -88,7 +88,7 @@ def validate_credit_card_number(credit_card_number: str) -> bool: return False if not luhn_validation(credit_card_number): - print(f"{error_message} it fails the Lhun check.") + print(f"{error_message} it fails the Luhn check.") return False print(f"{credit_card_number} is a valid credit card number.") From 965b1ff7dfac4806d61e39dfbbdfb6c5c165c0a7 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sun, 31 Oct 2021 13:36:53 +0300 Subject: [PATCH 167/726] Improve Project Euler problem 078 solution 1 (#5708) * Add solution doctests * Improve solution function --- project_euler/problem_078/sol1.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/project_euler/problem_078/sol1.py b/project_euler/problem_078/sol1.py index f92cf0f40..7e5938c4c 100644 --- a/project_euler/problem_078/sol1.py +++ b/project_euler/problem_078/sol1.py @@ -21,6 +21,12 @@ import itertools def solution(number: int = 1000000) -> int: """ + >>> solution(1) + 1 + + >>> solution(9) + 14 + >>> solution() 55374 """ @@ -34,6 +40,7 @@ def solution(number: int = 1000000) -> int: if index > i: break item += partitions[i - index] * sign + item %= number index += j if index > i: break From 568425dfd14f687aaa11c6405e4acf2556ce74f2 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sun, 31 Oct 2021 13:37:46 +0300 Subject: [PATCH 168/726] Improve solution (#5705) --- project_euler/problem_072/sol1.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/project_euler/problem_072/sol1.py b/project_euler/problem_072/sol1.py index 846396ab0..a2a0eeeb3 100644 --- a/project_euler/problem_072/sol1.py +++ b/project_euler/problem_072/sol1.py @@ -18,7 +18,7 @@ Number of numbers between 1 and n that are coprime to n is given by the Euler's function, phi(n). So, the answer is simply the sum of phi(n) for 2 <= n <= 1,000,000 Sum of phi(d), for all d|n = n. This result can be used to find phi(n) using a sieve. -Time: 3.5 sec +Time: 1 sec """ @@ -36,8 +36,9 @@ def solution(limit: int = 1_000_000) -> int: phi = [i - 1 for i in range(limit + 1)] for i in range(2, limit + 1): - for j in range(2 * i, limit + 1, i): - phi[j] -= phi[i] + if phi[i] == i - 1: + for j in range(2 * i, limit + 1, i): + phi[j] -= phi[j] // i return sum(phi[2 : limit + 1]) From f92eac982dee9d4ea97e36cfda0f1fa19213b9f4 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sun, 31 Oct 2021 13:38:28 +0300 Subject: [PATCH 169/726] Improve Project Euler problem 092 solution 1 (#5703) * Fix typos * Improve solution --- project_euler/problem_092/sol1.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/project_euler/problem_092/sol1.py b/project_euler/problem_092/sol1.py index dcda3a486..437a85bad 100644 --- a/project_euler/problem_092/sol1.py +++ b/project_euler/problem_092/sol1.py @@ -12,11 +12,14 @@ How many starting numbers below ten million will arrive at 89? """ +DIGITS_SQUARED = [digit ** 2 for digit in range(10)] + + def next_number(number: int) -> int: """ Returns the next number of the chain by adding the square of each digit - to form a neww number. - For example if number = 12, next_number() will return 1^2 + 2^2 = 5. + to form a new number. + For example, if number = 12, next_number() will return 1^2 + 2^2 = 5. Therefore, 5 is the next number of the chain. >>> next_number(44) 32 @@ -27,12 +30,15 @@ def next_number(number: int) -> int: """ sum_of_digits_squared = 0 while number: - sum_of_digits_squared += (number % 10) ** 2 + sum_of_digits_squared += DIGITS_SQUARED[number % 10] number //= 10 return sum_of_digits_squared +CHAINS = {1: True, 58: False} + + def chain(number: int) -> bool: """ The function generates the chain of numbers until the next number is 1 or 89. @@ -40,7 +46,7 @@ def chain(number: int) -> bool: following chain of numbers: 44 → 32 → 13 → 10 → 1 → 1. Once the next number generated is 1 or 89, the function returns whether - or not the the next number generated by next_number() is 1. + or not the next number generated by next_number() is 1. >>> chain(10) True >>> chain(58) @@ -48,10 +54,13 @@ def chain(number: int) -> bool: >>> chain(1) True """ - while number != 1 and number != 89: - number = next_number(number) + if number in CHAINS: + return CHAINS[number] - return number == 1 + number_chain = chain(next_number(number)) + CHAINS[number] = number_chain + + return number_chain def solution(number: int = 10000000) -> int: From 13fdf21c9c74d9a1d0cc573bb35711b790dc8010 Mon Sep 17 00:00:00 2001 From: SURYAPRATAP SINGH SURYAVANSHI <67123991+suryapratapsinghsuryavanshi@users.noreply.github.com> Date: Sun, 31 Oct 2021 16:10:32 +0530 Subject: [PATCH 170/726] Added alternative_list_arrange method (#4631) --- other/alternative_list_arrange.py | 34 +++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 other/alternative_list_arrange.py diff --git a/other/alternative_list_arrange.py b/other/alternative_list_arrange.py new file mode 100644 index 000000000..84c5dd429 --- /dev/null +++ b/other/alternative_list_arrange.py @@ -0,0 +1,34 @@ +def alternative_list_arrange(first_input_list: list, second_input_list: list) -> list: + """ + The method arranges two lists as one list in alternative forms of the list elements. + :param first_input_list: + :param second_input_list: + :return: List + >>> alternative_list_arrange([1, 2, 3, 4, 5], ["A", "B", "C"]) + [1, 'A', 2, 'B', 3, 'C', 4, 5] + >>> alternative_list_arrange(["A", "B", "C"], [1, 2, 3, 4, 5]) + ['A', 1, 'B', 2, 'C', 3, 4, 5] + >>> alternative_list_arrange(["X", "Y", "Z"], [9, 8, 7, 6]) + ['X', 9, 'Y', 8, 'Z', 7, 6] + >>> alternative_list_arrange([1, 2, 3, 4, 5], []) + [1, 2, 3, 4, 5] + """ + first_input_list_length: int = len(first_input_list) + second_input_list_length: int = len(second_input_list) + abs_length: int = ( + first_input_list_length + if first_input_list_length > second_input_list_length + else second_input_list_length + ) + output_result_list: list = [] + for char_count in range(abs_length): + if char_count < first_input_list_length: + output_result_list.append(first_input_list[char_count]) + if char_count < second_input_list_length: + output_result_list.append(second_input_list[char_count]) + + return output_result_list + + +if __name__ == "__main__": + print(alternative_list_arrange(["A", "B", "C"], [1, 2, 3, 4, 5]), end=" ") From 9ac94c09ebc4d25caf3527350ff61d3ba93431e2 Mon Sep 17 00:00:00 2001 From: Morteza Date: Sun, 31 Oct 2021 03:41:39 -0700 Subject: [PATCH 171/726] Improve checking anagrams in O(n) with dictionary (#4806) --- strings/check_anagrams.py | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/strings/check_anagrams.py b/strings/check_anagrams.py index 62a4441a0..938bf4c2a 100644 --- a/strings/check_anagrams.py +++ b/strings/check_anagrams.py @@ -1,6 +1,7 @@ """ wiki: https://en.wikipedia.org/wiki/Anagram """ +from collections import defaultdict def check_anagrams(first_str: str, second_str: str) -> bool: @@ -16,10 +17,30 @@ def check_anagrams(first_str: str, second_str: str) -> bool: >>> check_anagrams('There', 'Their') False """ - return ( - "".join(sorted(first_str.lower())).strip() - == "".join(sorted(second_str.lower())).strip() - ) + first_str = first_str.lower().strip() + second_str = second_str.lower().strip() + + # Remove whitespace + first_str = first_str.replace(" ", "") + second_str = second_str.replace(" ", "") + + # Strings of different lengths are not anagrams + if len(first_str) != len(second_str): + return False + + # Default values for count should be 0 + count = defaultdict(int) + + # For each character in input strings, + # increment count in the corresponding + for i in range(len(first_str)): + count[first_str[i]] += 1 + count[second_str[i]] -= 1 + + for _count in count.values(): + if _count != 0: + return False + return True if __name__ == "__main__": From f4fd147d0306e5fe3dfdda8ef01ec9068c1c247a Mon Sep 17 00:00:00 2001 From: happiestbee <87628038+happiestbee@users.noreply.github.com> Date: Sun, 31 Oct 2021 06:46:31 -0400 Subject: [PATCH 172/726] Make decrypt_caesar_with_chi_squared work with upper case letters (#5379) * Fixes: #5323 * Fixes: #5323 --- ciphers/decrypt_caesar_with_chi_squared.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/ciphers/decrypt_caesar_with_chi_squared.py b/ciphers/decrypt_caesar_with_chi_squared.py index beac851b6..6c3686020 100644 --- a/ciphers/decrypt_caesar_with_chi_squared.py +++ b/ciphers/decrypt_caesar_with_chi_squared.py @@ -6,7 +6,7 @@ def decrypt_caesar_with_chi_squared( ciphertext: str, cipher_alphabet: list[str] | None = None, frequencies_dict: dict[str, float] | None = None, - case_sensetive: bool = False, + case_sensitive: bool = False, ) -> tuple[int, float, str]: """ Basic Usage @@ -20,7 +20,7 @@ def decrypt_caesar_with_chi_squared( * frequencies_dict (dict): a dictionary of word frequencies where keys are the letters and values are a percentage representation of the frequency as a decimal/float - * case_sensetive (bool): a boolean value: True if the case matters during + * case_sensitive (bool): a boolean value: True if the case matters during decryption, False if it doesn't Returns: @@ -117,6 +117,9 @@ def decrypt_caesar_with_chi_squared( >>> decrypt_caesar_with_chi_squared('crybd cdbsxq') (10, 233.35343938980898, 'short string') + >>> decrypt_caesar_with_chi_squared('Crybd Cdbsxq', case_sensitive=True) + (10, 233.35343938980898, 'Short String') + >>> decrypt_caesar_with_chi_squared(12) Traceback (most recent call last): AttributeError: 'int' object has no attribute 'lower' @@ -158,7 +161,7 @@ def decrypt_caesar_with_chi_squared( # Custom frequencies dictionary frequencies = frequencies_dict - if not case_sensetive: + if not case_sensitive: ciphertext = ciphertext.lower() # Chi squared statistic values @@ -172,10 +175,14 @@ def decrypt_caesar_with_chi_squared( for letter in ciphertext: try: # Try to index the letter in the alphabet - new_key = (alphabet_letters.index(letter) - shift) % len( + new_key = (alphabet_letters.index(letter.lower()) - shift) % len( alphabet_letters ) - decrypted_with_shift += alphabet_letters[new_key] + decrypted_with_shift += ( + alphabet_letters[new_key].upper() + if case_sensitive and letter.isupper() + else alphabet_letters[new_key] + ) except ValueError: # Append the character if it isn't in the alphabet decrypted_with_shift += letter @@ -184,10 +191,11 @@ def decrypt_caesar_with_chi_squared( # Loop through each letter in the decoded message with the shift for letter in decrypted_with_shift: - if case_sensetive: + if case_sensitive: + letter = letter.lower() if letter in frequencies: # Get the amount of times the letter occurs in the message - occurrences = decrypted_with_shift.count(letter) + occurrences = decrypted_with_shift.lower().count(letter) # Get the excepcted amount of times the letter should appear based # on letter frequencies From 0f015fa034646fcacd812b429e47c684b44e5bd3 Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 31 Oct 2021 11:48:10 +0100 Subject: [PATCH 173/726] Added solution for euler problem 493 (#5573) * Added solution for problem 493 * fixed typo * return result as string --- project_euler/problem_493/__init__.py | 0 project_euler/problem_493/sol1.py | 53 +++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 project_euler/problem_493/__init__.py create mode 100644 project_euler/problem_493/sol1.py diff --git a/project_euler/problem_493/__init__.py b/project_euler/problem_493/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_493/sol1.py b/project_euler/problem_493/sol1.py new file mode 100644 index 000000000..c9879a528 --- /dev/null +++ b/project_euler/problem_493/sol1.py @@ -0,0 +1,53 @@ +""" +Project Euler Problem 493: https://projecteuler.net/problem=493 + +70 coloured balls are placed in an urn, 10 for each of the seven rainbow colours. +What is the expected number of distinct colours in 20 randomly picked balls? +Give your answer with nine digits after the decimal point (a.bcdefghij). + +----- + +This combinatorial problem can be solved by decomposing the problem into the +following steps: +1. Calculate the total number of possible picking cominations +[combinations := binom_coeff(70, 20)] +2. Calculate the number of combinations with one colour missing +[missing := binom_coeff(60, 20)] +3. Calculate the probability of one colour missing +[missing_prob := missing / combinations] +4. Calculate the probability of no colour missing +[no_missing_prob := 1 - missing_prob] +5. Calculate the expected number of distinct colours +[expected = 7 * no_missing_prob] + +References: +- https://en.wikipedia.org/wiki/Binomial_coefficient +""" + +import math + +BALLS_PER_COLOUR = 10 +NUM_COLOURS = 7 +NUM_BALLS = BALLS_PER_COLOUR * NUM_COLOURS + + +def solution(num_picks: int = 20) -> str: + """ + Calculates the expected number of distinct colours + + >>> solution(10) + '5.669644129' + + >>> solution(30) + '6.985042712' + """ + total = math.comb(NUM_BALLS, num_picks) + missing_colour = math.comb(NUM_BALLS - BALLS_PER_COLOUR, num_picks) + + result = NUM_COLOURS * (1 - missing_colour / total) + + return f"{result:.9f}" + + +if __name__ == "__main__": + print(solution(20)) From 7488c5070e3f5a29a08f584644666494c420f834 Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Sun, 31 Oct 2021 07:49:34 -0300 Subject: [PATCH 174/726] Fix type annotations in randomized_heap.py (#5704) --- data_structures/heap/randomized_heap.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/data_structures/heap/randomized_heap.py b/data_structures/heap/randomized_heap.py index f584f5cb3..bab4ec1b3 100644 --- a/data_structures/heap/randomized_heap.py +++ b/data_structures/heap/randomized_heap.py @@ -3,9 +3,9 @@ from __future__ import annotations import random -from typing import Generic, Iterable, TypeVar +from typing import Any, Generic, Iterable, TypeVar -T = TypeVar("T") +T = TypeVar("T", bound=bool) class RandomizedHeapNode(Generic[T]): @@ -76,8 +76,10 @@ class RandomizedHeap(Generic[T]): [1, 3, 3, 7] """ self._root: RandomizedHeapNode[T] | None = None - for item in data: - self.insert(item) + + if data: + for item in data: + self.insert(item) def insert(self, value: T) -> None: """ @@ -93,7 +95,7 @@ class RandomizedHeap(Generic[T]): """ self._root = RandomizedHeapNode.merge(self._root, RandomizedHeapNode(value)) - def pop(self) -> T: + def pop(self) -> T | None: """ Pop the smallest value from the heap and return it. @@ -111,7 +113,12 @@ class RandomizedHeap(Generic[T]): ... IndexError: Can't get top element for the empty heap. """ + result = self.top() + + if self._root is None: + return None + self._root = RandomizedHeapNode.merge(self._root.left, self._root.right) return result @@ -138,7 +145,7 @@ class RandomizedHeap(Generic[T]): raise IndexError("Can't get top element for the empty heap.") return self._root.value - def clear(self): + def clear(self) -> None: """ Clear the heap. @@ -151,7 +158,7 @@ class RandomizedHeap(Generic[T]): """ self._root = None - def to_sorted_list(self) -> list[T]: + def to_sorted_list(self) -> list[Any]: """ Returns sorted list containing all the values in the heap. From 508589e3fc3fa93312b131c30c77ecd61460a430 Mon Sep 17 00:00:00 2001 From: Venkatesh Tantravahi <64308188+venkateshtantravahi@users.noreply.github.com> Date: Sun, 31 Oct 2021 16:57:50 +0530 Subject: [PATCH 175/726] Local Weighted Learning (#5615) * Local Weighted Learning Added * Delete LWL directory * Local Weighted Learning Added * local weighted learning added * Delete LWL directory * Delete local_weighted_learning.py * rephrased code added * local weight learning updated * local weight learning updated * Updated dir * updated codespell * import modification * Doctests added * doctests updated * lcl updated * doctests updated * doctest values updated --- .../local_weighted_learning/__init__.py | 0 .../local_weighted_learning.md | 66 +++++++++ .../local_weighted_learning.py | 135 ++++++++++++++++++ 3 files changed, 201 insertions(+) create mode 100644 machine_learning/local_weighted_learning/__init__.py create mode 100644 machine_learning/local_weighted_learning/local_weighted_learning.md create mode 100644 machine_learning/local_weighted_learning/local_weighted_learning.py diff --git a/machine_learning/local_weighted_learning/__init__.py b/machine_learning/local_weighted_learning/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/machine_learning/local_weighted_learning/local_weighted_learning.md b/machine_learning/local_weighted_learning/local_weighted_learning.md new file mode 100644 index 000000000..5c7895e75 --- /dev/null +++ b/machine_learning/local_weighted_learning/local_weighted_learning.md @@ -0,0 +1,66 @@ +# Locally Weighted Linear Regression +It is a non-parametric ML algorithm that does not learn on a fixed set of parameters such as **linear regression**. \ +So, here comes a question of what is *linear regression*? \ +**Linear regression** is a supervised learning algorithm used for computing linear relationships between input (X) and output (Y). \ + +### Terminology Involved + +number_of_features(i) = Number of features involved. \ +number_of_training_examples(m) = Number of training examples. \ +output_sequence(y) = Output Sequence. \ +$\theta$ $^T$ x = predicted point. \ +J($\theta$) = COst function of point. + +The steps involved in ordinary linear regression are: + +Training phase: Compute \theta to minimize the cost. \ +J($\theta$) = $\sum_{i=1}^m$ (($\theta$)$^T$ $x^i$ - $y^i$)$^2$ + +Predict output: for given query point x, \ + return: ($\theta$)$^T$ x + +Linear Regression + +This training phase is possible when data points are linear, but there again comes a question can we predict non-linear relationship between x and y ? as shown below + +Non-linear Data +
+
+So, here comes the role of non-parametric algorithm which doesn't compute predictions based on fixed set of params. Rather parameters $\theta$ are computed individually for each query point/data point x. +
+
+While Computing $\theta$ , a higher "preferance" is given to points in the vicinity of x than points farther from x. + +Cost Function J($\theta$) = $\sum_{i=1}^m$ $w^i$ (($\theta$)$^T$ $x^i$ - $y^i$)$^2$ + +$w^i$ is non-negative weight associated to training point $x^i$. \ +$w^i$ is large fr $x^i$'s lying closer to query point $x_i$. \ +$w^i$ is small for $x^i$'s lying farther to query point $x_i$. + +A Typical weight can be computed using \ + +$w^i$ = $\exp$(-$\frac{(x^i-x)(x^i-x)^T}{2\tau^2}$) + +Where $\tau$ is the bandwidth parameter that controls $w^i$ distance from x. + +Let's look at a example : + +Suppose, we had a query point x=5.0 and training points $x^1$=4.9 and $x^2$=5.0 than we can calculate weights as : + +$w^i$ = $\exp$(-$\frac{(x^i-x)(x^i-x)^T}{2\tau^2}$) with $\tau$=0.5 + +$w^1$ = $\exp$(-$\frac{(4.9-5)^2}{2(0.5)^2}$) = 0.9802 + +$w^2$ = $\exp$(-$\frac{(3-5)^2}{2(0.5)^2}$) = 0.000335 + +So, J($\theta$) = 0.9802*($\theta$ $^T$ $x^1$ - $y^1$) + 0.000335*($\theta$ $^T$ $x^2$ - $y^2$) + +So, here by we can conclude that the weight fall exponentially as the distance between x & $x^i$ increases and So, does the contribution of error in prediction for $x^i$ to the cost. + +Steps involved in LWL are : \ +Compute \theta to minimize the cost. +J($\theta$) = $\sum_{i=1}^m$ $w^i$ (($\theta$)$^T$ $x^i$ - $y^i$)$^2$ \ +Predict Output: for given query point x, \ +return : $\theta$ $^T$ x + +LWL diff --git a/machine_learning/local_weighted_learning/local_weighted_learning.py b/machine_learning/local_weighted_learning/local_weighted_learning.py new file mode 100644 index 000000000..af8694bf8 --- /dev/null +++ b/machine_learning/local_weighted_learning/local_weighted_learning.py @@ -0,0 +1,135 @@ +# Required imports to run this file +import matplotlib.pyplot as plt +import numpy as np + + +# weighted matrix +def weighted_matrix(point: np.mat, training_data_x: np.mat, bandwidth: float) -> np.mat: + """ + Calculate the weight for every point in the + data set. It takes training_point , query_point, and tau + Here Tau is not a fixed value it can be varied depends on output. + tau --> bandwidth + xmat -->Training data + point --> the x where we want to make predictions + >>> weighted_matrix(np.array([1., 1.]),np.mat([[16.99, 10.34], [21.01,23.68], + ... [24.59,25.69]]), 0.6) + matrix([[1.43807972e-207, 0.00000000e+000, 0.00000000e+000], + [0.00000000e+000, 0.00000000e+000, 0.00000000e+000], + [0.00000000e+000, 0.00000000e+000, 0.00000000e+000]]) + """ + # m is the number of training samples + m, n = np.shape(training_data_x) + # Initializing weights as identity matrix + weights = np.mat(np.eye(m)) + # calculating weights for all training examples [x(i)'s] + for j in range(m): + diff = point - training_data_x[j] + weights[j, j] = np.exp(diff * diff.T / (-2.0 * bandwidth ** 2)) + return weights + + +def local_weight( + point: np.mat, training_data_x: np.mat, training_data_y: np.mat, bandwidth: float +) -> np.mat: + """ + Calculate the local weights using the weight_matrix function on training data. + Return the weighted matrix. + >>> local_weight(np.array([1., 1.]),np.mat([[16.99, 10.34], [21.01,23.68], + ... [24.59,25.69]]),np.mat([[1.01, 1.66, 3.5]]), 0.6) + matrix([[0.00873174], + [0.08272556]]) + """ + weight = weighted_matrix(point, training_data_x, bandwidth) + W = (training_data_x.T * (weight * training_data_x)).I * ( + training_data_x.T * weight * training_data_y.T + ) + + return W + + +def local_weight_regression( + training_data_x: np.mat, training_data_y: np.mat, bandwidth: float +) -> np.mat: + """ + Calculate predictions for each data point on axis. + >>> local_weight_regression(np.mat([[16.99, 10.34], [21.01,23.68], + ... [24.59,25.69]]),np.mat([[1.01, 1.66, 3.5]]), 0.6) + array([1.07173261, 1.65970737, 3.50160179]) + """ + m, n = np.shape(training_data_x) + ypred = np.zeros(m) + + for i, item in enumerate(training_data_x): + ypred[i] = item * local_weight( + item, training_data_x, training_data_y, bandwidth + ) + + return ypred + + +def load_data(dataset_name: str, cola_name: str, colb_name: str) -> np.mat: + """ + Function used for loading data from the seaborn splitting into x and y points + >>> pass # this function has no doctest + """ + import seaborn as sns + + data = sns.load_dataset(dataset_name) + col_a = np.array(data[cola_name]) # total_bill + col_b = np.array(data[colb_name]) # tip + + mcol_a = np.mat(col_a) + mcol_b = np.mat(col_b) + + m = np.shape(mcol_b)[1] + one = np.ones((1, m), dtype=int) + + # horizontal stacking + training_data_x = np.hstack((one.T, mcol_a.T)) + + return training_data_x, mcol_b, col_a, col_b + + +def get_preds(training_data_x: np.mat, mcol_b: np.mat, tau: float) -> np.ndarray: + """ + Get predictions with minimum error for each training data + >>> get_preds(np.mat([[16.99, 10.34], [21.01,23.68], + ... [24.59,25.69]]),np.mat([[1.01, 1.66, 3.5]]), 0.6) + array([1.07173261, 1.65970737, 3.50160179]) + """ + ypred = local_weight_regression(training_data_x, mcol_b, tau) + return ypred + + +def plot_preds( + training_data_x: np.mat, + predictions: np.ndarray, + col_x: np.ndarray, + col_y: np.ndarray, + cola_name: str, + colb_name: str, +) -> plt.plot: + """ + This function used to plot predictions and display the graph + >>> pass #this function has no doctest + """ + xsort = training_data_x.copy() + xsort.sort(axis=0) + plt.scatter(col_x, col_y, color="blue") + plt.plot( + xsort[:, 1], + predictions[training_data_x[:, 1].argsort(0)], + color="yellow", + linewidth=5, + ) + plt.title("Local Weighted Regression") + plt.xlabel(cola_name) + plt.ylabel(colb_name) + plt.show() + + +if __name__ == "__main__": + training_data_x, mcol_b, col_a, col_b = load_data("tips", "total_bill", "tip") + predictions = get_preds(training_data_x, mcol_b, 0.5) + plot_preds(training_data_x, predictions, col_a, col_b, "total_bill", "tip") From a64c9f1e7cc9616c54296ca3983123e15ec486f1 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Sun, 31 Oct 2021 14:16:02 +0000 Subject: [PATCH 176/726] Deduplicate euclidean_length method in Vector (#5658) * Rewrite parts of Vector and Matrix methods * Refactor determinant method and add unit tests Refactor determinant method to create separate minor and cofactor methods. Add respective unit tests for new methods. Rename methods using snake case to follow Python naming conventions. * Reorganize Vector and Matrix methods * Update linear_algebra/README.md Co-authored-by: John Law * Fix punctuation and wording * Apply suggestions from code review Co-authored-by: John Law * Deduplicate euclidean length method for Vector * Add more unit tests for Euclidean length method * Fix bug in unit test for euclidean_length * Remove old comments for magnitude method Co-authored-by: John Law --- linear_algebra/src/lib.py | 33 +++++++++++------------ linear_algebra/src/test_linear_algebra.py | 8 +++++- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/linear_algebra/src/lib.py b/linear_algebra/src/lib.py index dad0a8c0a..85dc4b71c 100644 --- a/linear_algebra/src/lib.py +++ b/linear_algebra/src/lib.py @@ -44,7 +44,6 @@ class Vector: component(i): gets the i-th component (0-indexed) change_component(pos: int, value: float): changes specified component euclidean_length(): returns the euclidean length of the vector - magnitude(): returns the magnitude of the vector angle(other: Vector, deg: bool): returns the angle between two vectors TODO: compare-operator """ @@ -159,18 +158,20 @@ class Vector: def euclidean_length(self) -> float: """ returns the euclidean length of the vector - """ - squares = [c ** 2 for c in self.__components] - return math.sqrt(sum(squares)) - def magnitude(self) -> float: - """ - Magnitude of a Vector - - >>> Vector([2, 3, 4]).magnitude() + >>> Vector([2, 3, 4]).euclidean_length() 5.385164807134504 - + >>> Vector([1]).euclidean_length() + 1.0 + >>> Vector([0, -1, -2, -3, 4, 5, 6]).euclidean_length() + 9.539392014169456 + >>> Vector([]).euclidean_length() + Traceback (most recent call last): + ... + Exception: Vector is empty """ + if len(self.__components) == 0: + raise Exception("Vector is empty") squares = [c ** 2 for c in self.__components] return math.sqrt(sum(squares)) @@ -188,7 +189,7 @@ class Vector: Exception: invalid operand! """ num = self * other - den = self.magnitude() * other.magnitude() + den = self.euclidean_length() * other.euclidean_length() if deg: return math.degrees(math.acos(num / den)) else: @@ -267,8 +268,7 @@ class Matrix: def __init__(self, matrix: list[list[float]], w: int, h: int) -> None: """ - simple constructor for initializing - the matrix with components. + simple constructor for initializing the matrix with components. """ self.__matrix = matrix self.__width = w @@ -276,8 +276,7 @@ class Matrix: def __str__(self) -> str: """ - returns a string representation of this - matrix. + returns a string representation of this matrix. """ ans = "" for i in range(self.__height): @@ -291,7 +290,7 @@ class Matrix: def __add__(self, other: Matrix) -> Matrix: """ - implements the matrix-addition. + implements matrix addition. """ if self.__width == other.width() and self.__height == other.height(): matrix = [] @@ -307,7 +306,7 @@ class Matrix: def __sub__(self, other: Matrix) -> Matrix: """ - implements the matrix-subtraction. + implements matrix subtraction. """ if self.__width == other.width() and self.__height == other.height(): matrix = [] diff --git a/linear_algebra/src/test_linear_algebra.py b/linear_algebra/src/test_linear_algebra.py index de7041a17..724ceef25 100644 --- a/linear_algebra/src/test_linear_algebra.py +++ b/linear_algebra/src/test_linear_algebra.py @@ -42,12 +42,18 @@ class Test(unittest.TestCase): x = Vector([1, 2, 3, 4]) self.assertEqual(len(x), 4) - def test_euclidLength(self) -> None: + def test_euclidean_length(self) -> None: """ test for method euclidean_length() """ x = Vector([1, 2]) + y = Vector([1, 2, 3, 4, 5]) + z = Vector([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + w = Vector([1, -1, 1, -1, 2, -3, 4, -5]) self.assertAlmostEqual(x.euclidean_length(), 2.236, 3) + self.assertAlmostEqual(y.euclidean_length(), 7.416, 3) + self.assertEqual(z.euclidean_length(), 0) + self.assertAlmostEqual(w.euclidean_length(), 7.616, 3) def test_add(self) -> None: """ From 868c2fa0a8e1f51ba32e7622990a9259a8740604 Mon Sep 17 00:00:00 2001 From: Maarten Date: Sun, 31 Oct 2021 15:19:44 +0100 Subject: [PATCH 177/726] Rewrite fibonacci.py (#5665) (#5677) * Removed doctest call * Removed 0 and 1 append to `fib_array` * Moved fibonacci sequence logic into `calculate` * Refactored `get` to generate missing numbers * Renamed `fib_array` to `sequence` * Renamed `number` to `index` * Refactored `get` to only return sequence to `index` * Moved main block into function * Added documentation to `get` * Added missing type hints * Fixed doctest error in `get` docstring * Moved calculate logic into get * Reformatted with black * Fixed wrong generation range --- dynamic_programming/fibonacci.py | 91 ++++++++++++++------------------ 1 file changed, 39 insertions(+), 52 deletions(-) diff --git a/dynamic_programming/fibonacci.py b/dynamic_programming/fibonacci.py index cab1358dd..4abc60d4f 100644 --- a/dynamic_programming/fibonacci.py +++ b/dynamic_programming/fibonacci.py @@ -5,61 +5,48 @@ sequence problem. class Fibonacci: - def __init__(self, N=None): - self.fib_array = [] - if N: - N = int(N) - self.fib_array.append(0) - self.fib_array.append(1) - for i in range(2, N + 1): - self.fib_array.append(self.fib_array[i - 1] + self.fib_array[i - 2]) - elif N == 0: - self.fib_array.append(0) - print(self.fib_array) + def __init__(self) -> None: + self.sequence = [0, 1] - def get(self, sequence_no=None): + def get(self, index: int) -> list: """ - >>> Fibonacci(5).get(3) - [0, 1, 1, 2, 3, 5] - [0, 1, 1, 2] - >>> Fibonacci(5).get(6) - [0, 1, 1, 2, 3, 5] - Out of bound. - >>> Fibonacci(5).get(-1) - [0, 1, 1, 2, 3, 5] - [] + Get the Fibonacci number of `index`. If the number does not exist, + calculate all missing numbers leading up to the number of `index`. + + >>> Fibonacci().get(10) + [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] + >>> Fibonacci().get(5) + [0, 1, 1, 2, 3] """ - if sequence_no is not None: - if sequence_no < len(self.fib_array): - return print(self.fib_array[: sequence_no + 1]) - else: - print("Out of bound.") - else: - print("Please specify a value") + difference = index - (len(self.sequence) - 2) + if difference >= 1: + for _ in range(difference): + self.sequence.append(self.sequence[-1] + self.sequence[-2]) + return self.sequence[:index] + + +def main(): + print( + "Fibonacci Series Using Dynamic Programming\n", + "Enter the index of the Fibonacci number you want to calculate ", + "in the prompt below. (To exit enter exit or Ctrl-C)\n", + sep="", + ) + fibonacci = Fibonacci() + + while True: + prompt: str = input(">> ") + if prompt in {"exit", "quit"}: + break + + try: + index: int = int(prompt) + except ValueError: + print("Enter a number or 'exit'") + continue + + print(fibonacci.get(index)) if __name__ == "__main__": - print("\n********* Fibonacci Series Using Dynamic Programming ************\n") - print("\n Enter the upper limit for the fibonacci sequence: ", end="") - try: - N = int(input().strip()) - fib = Fibonacci(N) - print( - "\n********* Enter different values to get the corresponding fibonacci " - "sequence, enter any negative number to exit. ************\n" - ) - while True: - try: - i = int(input("Enter value: ").strip()) - if i < 0: - print("\n********* Good Bye!! ************\n") - break - fib.get(i) - except NameError: - print("\nInvalid input, please try again.") - except NameError: - print("\n********* Invalid input, good bye!! ************\n") - - import doctest - - doctest.testmod() + main() From 94f38dd88c9f644d270a52f9cdd76c2e64e90c7c Mon Sep 17 00:00:00 2001 From: Edward Nuno Date: Sun, 31 Oct 2021 09:03:03 -0700 Subject: [PATCH 178/726] [mypy] Fix type annotations for linked_stack.py (#5576) * Fix type annotations for linked_stack.py * Replace Optional with inline union type * Rename linked_stack to stack_with_singly_linked_list * Rename stack_using_dll to stack_with_doubly_linked_list * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 4 +-- ...ll.py => stack_with_doubly_linked_list.py} | 0 ...ck.py => stack_with_singly_linked_list.py} | 29 ++++++++++--------- 3 files changed, 18 insertions(+), 15 deletions(-) rename data_structures/stacks/{stack_using_dll.py => stack_with_doubly_linked_list.py} (100%) rename data_structures/stacks/{linked_stack.py => stack_with_singly_linked_list.py} (83%) diff --git a/DIRECTORY.md b/DIRECTORY.md index 434cddbfd..140dc632c 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -198,12 +198,12 @@ * [Evaluate Postfix Notations](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/evaluate_postfix_notations.py) * [Infix To Postfix Conversion](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/infix_to_postfix_conversion.py) * [Infix To Prefix Conversion](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/infix_to_prefix_conversion.py) - * [Linked Stack](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/linked_stack.py) * [Next Greater Element](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/next_greater_element.py) * [Postfix Evaluation](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/postfix_evaluation.py) * [Prefix Evaluation](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/prefix_evaluation.py) * [Stack](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/stack.py) - * [Stack Using Dll](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/stack_using_dll.py) + * [Stack With Doubly Linked List](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/stack_with_doubly_linked_list.py) + * [Stack With Singly Linked List](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/stack_with_singly_linked_list.py) * [Stock Span Problem](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/stock_span_problem.py) * Trie * [Trie](https://github.com/TheAlgorithms/Python/blob/master/data_structures/trie/trie.py) diff --git a/data_structures/stacks/stack_using_dll.py b/data_structures/stacks/stack_with_doubly_linked_list.py similarity index 100% rename from data_structures/stacks/stack_using_dll.py rename to data_structures/stacks/stack_with_doubly_linked_list.py diff --git a/data_structures/stacks/linked_stack.py b/data_structures/stacks/stack_with_singly_linked_list.py similarity index 83% rename from data_structures/stacks/linked_stack.py rename to data_structures/stacks/stack_with_singly_linked_list.py index 85b59a940..903ae39db 100644 --- a/data_structures/stacks/linked_stack.py +++ b/data_structures/stacks/stack_with_singly_linked_list.py @@ -1,19 +1,22 @@ """ A Stack using a linked list like structure """ from __future__ import annotations -from typing import Any +from collections.abc import Iterator +from typing import Generic, TypeVar + +T = TypeVar("T") -class Node: - def __init__(self, data): +class Node(Generic[T]): + def __init__(self, data: T): self.data = data - self.next = None + self.next: Node[T] | None = None - def __str__(self): + def __str__(self) -> str: return f"{self.data}" -class LinkedStack: +class LinkedStack(Generic[T]): """ Linked List Stack implementing push (to top), pop (from top) and is_empty @@ -44,15 +47,15 @@ class LinkedStack: """ def __init__(self) -> None: - self.top: Node | None = None + self.top: Node[T] | None = None - def __iter__(self): + def __iter__(self) -> Iterator[T]: node = self.top while node: yield node.data node = node.next - def __str__(self): + def __str__(self) -> str: """ >>> stack = LinkedStack() >>> stack.push("c") @@ -63,7 +66,7 @@ class LinkedStack: """ return "->".join([str(item) for item in self]) - def __len__(self): + def __len__(self) -> int: """ >>> stack = LinkedStack() >>> len(stack) == 0 @@ -87,7 +90,7 @@ class LinkedStack: """ return self.top is None - def push(self, item: Any) -> None: + def push(self, item: T) -> None: """ >>> stack = LinkedStack() >>> stack.push("Python") @@ -101,7 +104,7 @@ class LinkedStack: node.next = self.top self.top = node - def pop(self) -> Any: + def pop(self) -> T: """ >>> stack = LinkedStack() >>> stack.pop() @@ -125,7 +128,7 @@ class LinkedStack: self.top = self.top.next return pop_node.data - def peek(self) -> Any: + def peek(self) -> T: """ >>> stack = LinkedStack() >>> stack.push("Java") From 99cf2cc1c5a83585625a26b6f267ac8f25affdc7 Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj Date: Mon, 1 Nov 2021 03:26:33 +0530 Subject: [PATCH 179/726] Fix build issues due to count (#5725) * Fix build issues due to count * Update check_anagrams.py --- strings/check_anagrams.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/strings/check_anagrams.py b/strings/check_anagrams.py index 938bf4c2a..f652e2294 100644 --- a/strings/check_anagrams.py +++ b/strings/check_anagrams.py @@ -2,6 +2,7 @@ wiki: https://en.wikipedia.org/wiki/Anagram """ from collections import defaultdict +from typing import DefaultDict def check_anagrams(first_str: str, second_str: str) -> bool: @@ -29,7 +30,7 @@ def check_anagrams(first_str: str, second_str: str) -> bool: return False # Default values for count should be 0 - count = defaultdict(int) + count: DefaultDict[str, int] = defaultdict(int) # For each character in input strings, # increment count in the corresponding From 06ab650e0823d7b58d1fc22a6f7cc0cca818f973 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Mon, 1 Nov 2021 06:25:40 +0000 Subject: [PATCH 180/726] Merge maths/fibonacci.py and maths/fibonacci_sequence_recursion.py (#5738) * Rewrite parts of Vector and Matrix methods * Refactor determinant method and add unit tests Refactor determinant method to create separate minor and cofactor methods. Add respective unit tests for new methods. Rename methods using snake case to follow Python naming conventions. * Reorganize Vector and Matrix methods * Update linear_algebra/README.md Co-authored-by: John Law * Fix punctuation and wording * Apply suggestions from code review Co-authored-by: John Law * Deduplicate euclidean length method for Vector * Add more unit tests for Euclidean length method * Fix bug in unit test for euclidean_length * Remove old comments for magnitude method * Rewrite maths/fibonacci.py * Rewrite timer and add unit tests * Fix typos in fib_binet unit tests * Fix typos in fib_binet unit tests * Clean main method * Merge fibonacci.py and fibonacci_sequence_recursion.py * Fix fib_binet unit test Co-authored-by: John Law --- maths/fibonacci.py | 260 +++++++++++++------------- maths/fibonacci_sequence_recursion.py | 22 --- 2 files changed, 130 insertions(+), 152 deletions(-) delete mode 100644 maths/fibonacci_sequence_recursion.py diff --git a/maths/fibonacci.py b/maths/fibonacci.py index e65190354..b009ea9df 100644 --- a/maths/fibonacci.py +++ b/maths/fibonacci.py @@ -1,130 +1,130 @@ -# fibonacci.py -""" -1. Calculates the iterative fibonacci sequence - -2. Calculates the fibonacci sequence with a formula - an = [ Phin - (phi)n ]/Sqrt[5] - reference-->Su, Francis E., et al. "Fibonacci Number Formula." Math Fun Facts. - -""" -import functools -import math -import time -from decimal import Decimal, getcontext - -getcontext().prec = 100 - - -def timer_decorator(func): - @functools.wraps(func) - def timer_wrapper(*args, **kwargs): - start = time.time() - func(*args, **kwargs) - end = time.time() - if int(end - start) > 0: - print(f"Run time for {func.__name__}: {(end - start):0.2f}s") - else: - print(f"Run time for {func.__name__}: {(end - start)*1000:0.2f}ms") - return func(*args, **kwargs) - - return timer_wrapper - - -# define Python user-defined exceptions -class Error(Exception): - """Base class for other exceptions""" - - -class ValueTooLargeError(Error): - """Raised when the input value is too large""" - - -class ValueTooSmallError(Error): - """Raised when the input value is not greater than one""" - - -class ValueLessThanZero(Error): - """Raised when the input value is less than zero""" - - -def _check_number_input(n, min_thresh, max_thresh=None): - """ - :param n: single integer - :type n: int - :param min_thresh: min threshold, single integer - :type min_thresh: int - :param max_thresh: max threshold, single integer - :type max_thresh: int - :return: boolean - """ - try: - if n >= min_thresh and max_thresh is None: - return True - elif min_thresh <= n <= max_thresh: - return True - elif n < 0: - raise ValueLessThanZero - elif n < min_thresh: - raise ValueTooSmallError - elif n > max_thresh: - raise ValueTooLargeError - except ValueLessThanZero: - print("Incorrect Input: number must not be less than 0") - except ValueTooSmallError: - print( - f"Incorrect Input: input number must be > {min_thresh} for the recursive " - "calculation" - ) - except ValueTooLargeError: - print( - f"Incorrect Input: input number must be < {max_thresh} for the recursive " - "calculation" - ) - return False - - -@timer_decorator -def fib_iterative(n): - """ - :param n: calculate Fibonacci to the nth integer - :type n:int - :return: Fibonacci sequence as a list - """ - n = int(n) - if _check_number_input(n, 2): - seq_out = [0, 1] - a, b = 0, 1 - for _ in range(n - len(seq_out)): - a, b = b, a + b - seq_out.append(b) - return seq_out - - -@timer_decorator -def fib_formula(n): - """ - :param n: calculate Fibonacci to the nth integer - :type n:int - :return: Fibonacci sequence as a list - """ - seq_out = [0, 1] - n = int(n) - if _check_number_input(n, 2, 1000000): - sqrt = Decimal(math.sqrt(5)) - phi_1 = Decimal(1 + sqrt) / Decimal(2) - phi_2 = Decimal(1 - sqrt) / Decimal(2) - for i in range(2, n): - temp_out = ((phi_1 ** Decimal(i)) - (phi_2 ** Decimal(i))) * ( - Decimal(sqrt) ** Decimal(-1) - ) - seq_out.append(int(temp_out)) - return seq_out - - -if __name__ == "__main__": - num = 20 - # print(f'{fib_recursive(num)}\n') - # print(f'{fib_iterative(num)}\n') - # print(f'{fib_formula(num)}\n') - fib_iterative(num) - fib_formula(num) +# fibonacci.py +""" +Calculates the Fibonacci sequence using iteration, recursion, and a simplified +form of Binet's formula + +NOTE 1: the iterative and recursive functions are more accurate than the Binet's +formula function because the iterative function doesn't use floats + +NOTE 2: the Binet's formula function is much more limited in the size of inputs +that it can handle due to the size limitations of Python floats +""" + +from math import sqrt +from time import time + + +def time_func(func, *args, **kwargs): + """ + Times the execution of a function with parameters + """ + start = time() + output = func(*args, **kwargs) + end = time() + if int(end - start) > 0: + print(f"{func.__name__} runtime: {(end - start):0.4f} s") + else: + print(f"{func.__name__} runtime: {(end - start) * 1000:0.4f} ms") + return output + + +def fib_iterative(n: int) -> list[int]: + """ + Calculates the first n (0-indexed) Fibonacci numbers using iteration + >>> fib_iterative(0) + [0] + >>> fib_iterative(1) + [0, 1] + >>> fib_iterative(5) + [0, 1, 1, 2, 3, 5] + >>> fib_iterative(10) + [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55] + >>> fib_iterative(-1) + Traceback (most recent call last): + ... + Exception: n is negative + """ + if n < 0: + raise Exception("n is negative") + if n == 0: + return [0] + fib = [0, 1] + for _ in range(n - 1): + fib.append(fib[-1] + fib[-2]) + return fib + + +def fib_recursive(n: int) -> list[int]: + """ + Calculates the first n (0-indexed) Fibonacci numbers using recursion + >>> fib_iterative(0) + [0] + >>> fib_iterative(1) + [0, 1] + >>> fib_iterative(5) + [0, 1, 1, 2, 3, 5] + >>> fib_iterative(10) + [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55] + >>> fib_iterative(-1) + Traceback (most recent call last): + ... + Exception: n is negative + """ + + def fib_recursive_term(i: int) -> int: + """ + Calculates the i-th (0-indexed) Fibonacci number using recursion + """ + if i < 0: + raise Exception("n is negative") + if i < 2: + return i + return fib_recursive_term(i - 1) + fib_recursive_term(i - 2) + + if n < 0: + raise Exception("n is negative") + return [fib_recursive_term(i) for i in range(n + 1)] + + +def fib_binet(n: int) -> list[int]: + """ + Calculates the first n (0-indexed) Fibonacci numbers using a simplified form + of Binet's formula: + https://en.m.wikipedia.org/wiki/Fibonacci_number#Computation_by_rounding + + NOTE 1: this function diverges from fib_iterative at around n = 71, likely + due to compounding floating-point arithmetic errors + + NOTE 2: this function overflows on n >= 1475 because of the size limitations + of Python floats + >>> fib_binet(0) + [0] + >>> fib_binet(1) + [0, 1] + >>> fib_binet(5) + [0, 1, 1, 2, 3, 5] + >>> fib_binet(10) + [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55] + >>> fib_binet(-1) + Traceback (most recent call last): + ... + Exception: n is negative + >>> fib_binet(1475) + Traceback (most recent call last): + ... + Exception: n is too large + """ + if n < 0: + raise Exception("n is negative") + if n >= 1475: + raise Exception("n is too large") + sqrt_5 = sqrt(5) + phi = (1 + sqrt_5) / 2 + return [round(phi ** i / sqrt_5) for i in range(n + 1)] + + +if __name__ == "__main__": + num = 20 + time_func(fib_iterative, num) + time_func(fib_recursive, num) + time_func(fib_binet, num) diff --git a/maths/fibonacci_sequence_recursion.py b/maths/fibonacci_sequence_recursion.py deleted file mode 100644 index 794b9fc0b..000000000 --- a/maths/fibonacci_sequence_recursion.py +++ /dev/null @@ -1,22 +0,0 @@ -# Fibonacci Sequence Using Recursion - - -def recur_fibo(n: int) -> int: - """ - >>> [recur_fibo(i) for i in range(12)] - [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] - """ - return n if n <= 1 else recur_fibo(n - 1) + recur_fibo(n - 2) - - -def main() -> None: - limit = int(input("How many terms to include in fibonacci series: ")) - if limit > 0: - print(f"The first {limit} terms of the fibonacci series are as follows:") - print([recur_fibo(n) for n in range(limit)]) - else: - print("Please enter a positive integer: ") - - -if __name__ == "__main__": - main() From 71ba3a1ad940bb42f773ac483da9d40b234ecb7f Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Mon, 1 Nov 2021 09:27:19 +0300 Subject: [PATCH 181/726] Improve Project Euler problem 012 solution 1 (#5731) * Improve solution * Uncomment code that has been commented due to slow execution affecting Travis * Retest --- project_euler/problem_012/sol1.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/project_euler/problem_012/sol1.py b/project_euler/problem_012/sol1.py index 7e080c4e4..861d026ec 100644 --- a/project_euler/problem_012/sol1.py +++ b/project_euler/problem_012/sol1.py @@ -21,17 +21,20 @@ We can see that 28 is the first triangle number to have over five divisors. What is the value of the first triangle number to have over five hundred divisors? """ -from math import sqrt def count_divisors(n): - nDivisors = 0 - for i in range(1, int(sqrt(n)) + 1): - if n % i == 0: - nDivisors += 2 - # check if n is perfect square - if n ** 0.5 == int(n ** 0.5): - nDivisors -= 1 + nDivisors = 1 + i = 2 + while i * i <= n: + multiplicity = 0 + while n % i == 0: + n //= i + multiplicity += 1 + nDivisors *= multiplicity + 1 + i += 1 + if n > 1: + nDivisors *= 2 return nDivisors @@ -39,9 +42,8 @@ def solution(): """Returns the value of the first triangle number to have over five hundred divisors. - # The code below has been commented due to slow execution affecting Travis. - # >>> solution() - # 76576500 + >>> solution() + 76576500 """ tNum = 1 i = 1 From 68ca61ecb75be579f13c6783c2071cc3b063d21b Mon Sep 17 00:00:00 2001 From: Kelly Costa Date: Mon, 1 Nov 2021 10:36:18 -0300 Subject: [PATCH 182/726] Add search book via ISBN using openlibrary.org API (#5736) * Add search book via ISBN using openlibrary.org API * FIX: parameters type hints and isbn sizes * Add doctests * Update search_books_by_isbn.py Co-authored-by: Christian Clauss --- web_programming/search_books_by_isbn.py | 76 +++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 web_programming/search_books_by_isbn.py diff --git a/web_programming/search_books_by_isbn.py b/web_programming/search_books_by_isbn.py new file mode 100644 index 000000000..fcb8b0428 --- /dev/null +++ b/web_programming/search_books_by_isbn.py @@ -0,0 +1,76 @@ +""" +Get book and author data from https://openlibrary.org + +ISBN: https://en.wikipedia.org/wiki/International_Standard_Book_Number +""" +from json import JSONDecodeError # Workaround for requests.exceptions.JSONDecodeError + +import requests + + +def get_openlibrary_data(olid: str = "isbn/0140328726") -> dict: + """ + Given an 'isbn/0140328726', return book data from Open Library as a Python dict. + Given an '/authors/OL34184A', return authors data as a Python dict. + This code must work for olids with or without a leading slash ('/'). + + # Comment out doctests if they take too long or have results that may change + # >>> get_openlibrary_data(olid='isbn/0140328726') # doctest: +ELLIPSIS + {'publishers': ['Puffin'], 'number_of_pages': 96, 'isbn_10': ['0140328726'], ... + # >>> get_openlibrary_data(olid='/authors/OL7353617A') # doctest: +ELLIPSIS + {'name': 'Adrian Brisku', 'created': {'type': '/type/datetime', ... + >>> pass # Placate https://github.com/apps/algorithms-keeper + """ + new_olid = olid.strip().strip("/") # Remove leading/trailing whitespace & slashes + if new_olid.count("/") != 1: + raise ValueError(f"{olid} is not a valid Open Library olid") + return requests.get(f"https://openlibrary.org/{new_olid}.json").json() + + +def summerize_book(ol_book_data: dict) -> dict: + """ + Given Open Library book data, return a summary as a Python dict. + + >>> pass # Placate TheAlgorithms @ + """ + desired_keys = { + "title": "Title", + "publish_date": "Publish date", + "authors": "Authors", + "number_of_pages": "Number of pages:", + "first_sentence": "First sentence", + "isbn_10": "ISBN (10)", + "isbn_13": "ISBN (13)", + } + data = {better_key: ol_book_data[key] for key, better_key in desired_keys.items()} + data["Authors"] = [ + get_openlibrary_data(author["key"])["name"] for author in data["Authors"] + ] + data["First sentence"] = data["First sentence"]["value"] + for key, value in data.items(): + if isinstance(value, list): + data[key] = ", ".join(value) + return data + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + + while True: + isbn = input("\nEnter the ISBN code to search (or 'quit' to stop): ").strip() + if isbn.lower() in ("", "q", "quit", "exit", "stop"): + break + + if len(isbn) not in (10, 13) or not isbn.isdigit(): + print(f"Sorry, {isbn} is not a valid ISBN. Please, input a valid ISBN.") + continue + + print(f"\nSearching Open Library for ISBN: {isbn}...\n") + + try: + book_summary = summerize_book(get_openlibrary_data(f"isbn/{isbn}")) + print("\n".join(f"{key}: {value}" for key, value in book_summary.items())) + except JSONDecodeError: # Workaround for requests.exceptions.RequestException: + print(f"Sorry, there are no results for ISBN: {isbn}.") From 84cca2119c5f493823cc65a3796fe37e4a9c643d Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Mon, 1 Nov 2021 17:06:35 +0000 Subject: [PATCH 183/726] Rewrite maths/fibonacci.py (#5734) * Rewrite parts of Vector and Matrix methods * Refactor determinant method and add unit tests Refactor determinant method to create separate minor and cofactor methods. Add respective unit tests for new methods. Rename methods using snake case to follow Python naming conventions. * Reorganize Vector and Matrix methods * Update linear_algebra/README.md Co-authored-by: John Law * Fix punctuation and wording * Apply suggestions from code review Co-authored-by: John Law * Deduplicate euclidean length method for Vector * Add more unit tests for Euclidean length method * Fix bug in unit test for euclidean_length * Remove old comments for magnitude method * Rewrite maths/fibonacci.py * Rewrite timer and add unit tests * Fix typos in fib_binet unit tests * Fix typos in fib_binet unit tests * Clean main method Co-authored-by: John Law --- maths/fibonacci.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maths/fibonacci.py b/maths/fibonacci.py index b009ea9df..9b193b74a 100644 --- a/maths/fibonacci.py +++ b/maths/fibonacci.py @@ -95,8 +95,8 @@ def fib_binet(n: int) -> list[int]: NOTE 1: this function diverges from fib_iterative at around n = 71, likely due to compounding floating-point arithmetic errors - NOTE 2: this function overflows on n >= 1475 because of the size limitations - of Python floats + NOTE 2: this function doesn't accept n >= 1475 because it overflows + thereafter due to the size limitations of Python floats >>> fib_binet(0) [0] >>> fib_binet(1) From 74f496712628e5bc77ae9e11572d4207066214ba Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 1 Nov 2021 18:07:47 +0100 Subject: [PATCH 184/726] Fix comment (#5742) * Fix comment * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 11 +++++++++-- web_programming/search_books_by_isbn.py | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 140dc632c..e70c0aab6 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -420,6 +420,8 @@ * [Knn Sklearn](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/knn_sklearn.py) * [Linear Discriminant Analysis](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/linear_discriminant_analysis.py) * [Linear Regression](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/linear_regression.py) + * Local Weighted Learning + * [Local Weighted Learning](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/local_weighted_learning/local_weighted_learning.py) * [Logistic Regression](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/logistic_regression.py) * Lstm * [Lstm Prediction](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/lstm/lstm_prediction.py) @@ -476,7 +478,6 @@ * [Factors](https://github.com/TheAlgorithms/Python/blob/master/maths/factors.py) * [Fermat Little Theorem](https://github.com/TheAlgorithms/Python/blob/master/maths/fermat_little_theorem.py) * [Fibonacci](https://github.com/TheAlgorithms/Python/blob/master/maths/fibonacci.py) - * [Fibonacci Sequence Recursion](https://github.com/TheAlgorithms/Python/blob/master/maths/fibonacci_sequence_recursion.py) * [Find Max](https://github.com/TheAlgorithms/Python/blob/master/maths/find_max.py) * [Find Max Recursion](https://github.com/TheAlgorithms/Python/blob/master/maths/find_max_recursion.py) * [Find Min](https://github.com/TheAlgorithms/Python/blob/master/maths/find_min.py) @@ -517,6 +518,7 @@ * [Perfect Number](https://github.com/TheAlgorithms/Python/blob/master/maths/perfect_number.py) * [Perfect Square](https://github.com/TheAlgorithms/Python/blob/master/maths/perfect_square.py) * [Pi Monte Carlo Estimation](https://github.com/TheAlgorithms/Python/blob/master/maths/pi_monte_carlo_estimation.py) + * [Pollard Rho](https://github.com/TheAlgorithms/Python/blob/master/maths/pollard_rho.py) * [Polynomial Evaluation](https://github.com/TheAlgorithms/Python/blob/master/maths/polynomial_evaluation.py) * [Power Using Recursion](https://github.com/TheAlgorithms/Python/blob/master/maths/power_using_recursion.py) * [Prime Check](https://github.com/TheAlgorithms/Python/blob/master/maths/prime_check.py) @@ -539,6 +541,7 @@ * [Geometric Series](https://github.com/TheAlgorithms/Python/blob/master/maths/series/geometric_series.py) * [Harmonic](https://github.com/TheAlgorithms/Python/blob/master/maths/series/harmonic.py) * [Harmonic Series](https://github.com/TheAlgorithms/Python/blob/master/maths/series/harmonic_series.py) + * [Hexagonal Numbers](https://github.com/TheAlgorithms/Python/blob/master/maths/series/hexagonal_numbers.py) * [P Series](https://github.com/TheAlgorithms/Python/blob/master/maths/series/p_series.py) * [Sieve Of Eratosthenes](https://github.com/TheAlgorithms/Python/blob/master/maths/sieve_of_eratosthenes.py) * [Sigmoid](https://github.com/TheAlgorithms/Python/blob/master/maths/sigmoid.py) @@ -583,8 +586,8 @@ ## Other * [Activity Selection](https://github.com/TheAlgorithms/Python/blob/master/other/activity_selection.py) + * [Alternative List Arrange](https://github.com/TheAlgorithms/Python/blob/master/other/alternative_list_arrange.py) * [Check Strong Password](https://github.com/TheAlgorithms/Python/blob/master/other/check_strong_password.py) - * [Date To Weekday](https://github.com/TheAlgorithms/Python/blob/master/other/date_to_weekday.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) @@ -861,6 +864,8 @@ * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_234/sol1.py) * Problem 301 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_301/sol1.py) + * Problem 493 + * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_493/sol1.py) * Problem 551 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_551/sol1.py) * Problem 686 @@ -960,6 +965,7 @@ * [Detecting English Programmatically](https://github.com/TheAlgorithms/Python/blob/master/strings/detecting_english_programmatically.py) * [Frequency Finder](https://github.com/TheAlgorithms/Python/blob/master/strings/frequency_finder.py) * [Indian Phone Validator](https://github.com/TheAlgorithms/Python/blob/master/strings/indian_phone_validator.py) + * [Is Contains Unique Chars](https://github.com/TheAlgorithms/Python/blob/master/strings/is_contains_unique_chars.py) * [Is Palindrome](https://github.com/TheAlgorithms/Python/blob/master/strings/is_palindrome.py) * [Jaro Winkler](https://github.com/TheAlgorithms/Python/blob/master/strings/jaro_winkler.py) * [Join](https://github.com/TheAlgorithms/Python/blob/master/strings/join.py) @@ -1008,6 +1014,7 @@ * [Nasa Data](https://github.com/TheAlgorithms/Python/blob/master/web_programming/nasa_data.py) * [Random Anime Character](https://github.com/TheAlgorithms/Python/blob/master/web_programming/random_anime_character.py) * [Recaptcha Verification](https://github.com/TheAlgorithms/Python/blob/master/web_programming/recaptcha_verification.py) + * [Search Books By Isbn](https://github.com/TheAlgorithms/Python/blob/master/web_programming/search_books_by_isbn.py) * [Slack Message](https://github.com/TheAlgorithms/Python/blob/master/web_programming/slack_message.py) * [Test Fetch Github Info](https://github.com/TheAlgorithms/Python/blob/master/web_programming/test_fetch_github_info.py) * [World Covid19 Stats](https://github.com/TheAlgorithms/Python/blob/master/web_programming/world_covid19_stats.py) diff --git a/web_programming/search_books_by_isbn.py b/web_programming/search_books_by_isbn.py index fcb8b0428..a55110f3f 100644 --- a/web_programming/search_books_by_isbn.py +++ b/web_programming/search_books_by_isbn.py @@ -31,7 +31,7 @@ def summerize_book(ol_book_data: dict) -> dict: """ Given Open Library book data, return a summary as a Python dict. - >>> pass # Placate TheAlgorithms @ + >>> pass # Placate https://github.com/apps/algorithms-keeper """ desired_keys = { "title": "Title", From dc6e77338c9cac607e58c06b178a232643f3e87d Mon Sep 17 00:00:00 2001 From: Brian Evans <53117772+mrbrianevans@users.noreply.github.com> Date: Mon, 1 Nov 2021 23:09:40 +0000 Subject: [PATCH 185/726] Add stone unit of measuring weight (#5730) * Add stone unit of measuring weight And some tests in the docs using an external calculator. Not yet tested if they pass. * Fix rounding descrepencies in doctests to pass tests --- conversions/weight_conversion.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/conversions/weight_conversion.py b/conversions/weight_conversion.py index c344416be..18c403731 100644 --- a/conversions/weight_conversion.py +++ b/conversions/weight_conversion.py @@ -3,7 +3,7 @@ Conversion of weight units. __author__ = "Anubhav Solanki" __license__ = "MIT" -__version__ = "1.0.0" +__version__ = "1.1.0" __maintainer__ = "Anubhav Solanki" __email__ = "anubhavsolanki0@gmail.com" @@ -27,6 +27,7 @@ REFERENCES : -> Wikipedia reference: https://en.wikipedia.org/wiki/Ounce -> Wikipedia reference: https://en.wikipedia.org/wiki/Fineness#Karat -> Wikipedia reference: https://en.wikipedia.org/wiki/Dalton_(unit) +-> Wikipedia reference: https://en.wikipedia.org/wiki/Stone_(unit) """ KILOGRAM_CHART: dict[str, float] = { @@ -37,6 +38,7 @@ KILOGRAM_CHART: dict[str, float] = { "long-ton": 0.0009842073, "short-ton": 0.0011023122, "pound": 2.2046244202, + "stone": 0.1574731728, "ounce": 35.273990723, "carrat": 5000, "atomic-mass-unit": 6.022136652e26, @@ -50,6 +52,7 @@ WEIGHT_TYPE_CHART: dict[str, float] = { "long-ton": 1016.04608, "short-ton": 907.184, "pound": 0.453592, + "stone": 6.35029, "ounce": 0.0283495, "carrat": 0.0002, "atomic-mass-unit": 1.660540199e-27, @@ -67,6 +70,7 @@ def weight_conversion(from_type: str, to_type: str, value: float) -> float: "long-ton" : 0.0009842073, "short-ton" : 0.0011023122, "pound" : 2.2046244202, + "stone": 0.1574731728, "ounce" : 35.273990723, "carrat" : 5000, "atomic-mass-unit" : 6.022136652E+26 @@ -85,6 +89,8 @@ def weight_conversion(from_type: str, to_type: str, value: float) -> float: 0.0011023122 >>> weight_conversion("kilogram","pound",4) 8.8184976808 + >>> weight_conversion("kilogram","stone",5) + 0.7873658640000001 >>> weight_conversion("kilogram","ounce",4) 141.095962892 >>> weight_conversion("kilogram","carrat",3) @@ -105,6 +111,8 @@ def weight_conversion(from_type: str, to_type: str, value: float) -> float: 3.3069366000000003e-06 >>> weight_conversion("gram","pound",3) 0.0066138732606 + >>> weight_conversion("gram","stone",4) + 0.0006298926912000001 >>> weight_conversion("gram","ounce",1) 0.035273990723 >>> weight_conversion("gram","carrat",2) @@ -211,6 +219,24 @@ def weight_conversion(from_type: str, to_type: str, value: float) -> float: 2267.96 >>> weight_conversion("pound","atomic-mass-unit",4) 1.0926372033015936e+27 + >>> weight_conversion("stone","kilogram",5) + 31.751450000000002 + >>> weight_conversion("stone","gram",2) + 12700.58 + >>> weight_conversion("stone","milligram",3) + 19050870.0 + >>> weight_conversion("stone","metric-ton",3) + 0.01905087 + >>> weight_conversion("stone","long-ton",3) + 0.018750005325351003 + >>> weight_conversion("stone","short-ton",3) + 0.021000006421614002 + >>> weight_conversion("stone","pound",2) + 28.00000881870372 + >>> weight_conversion("stone","ounce",1) + 224.00007054835967 + >>> weight_conversion("stone","carrat",2) + 63502.9 >>> weight_conversion("ounce","kilogram",3) 0.0850485 >>> weight_conversion("ounce","gram",3) From 5910c3aa78e6fa53ef425ab9efa43348cc421e6c Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj Date: Tue, 2 Nov 2021 14:50:55 +0530 Subject: [PATCH 186/726] Typo (#5750) --- web_programming/search_books_by_isbn.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web_programming/search_books_by_isbn.py b/web_programming/search_books_by_isbn.py index a55110f3f..22a31dcb1 100644 --- a/web_programming/search_books_by_isbn.py +++ b/web_programming/search_books_by_isbn.py @@ -27,7 +27,7 @@ def get_openlibrary_data(olid: str = "isbn/0140328726") -> dict: return requests.get(f"https://openlibrary.org/{new_olid}.json").json() -def summerize_book(ol_book_data: dict) -> dict: +def summarize_book(ol_book_data: dict) -> dict: """ Given Open Library book data, return a summary as a Python dict. @@ -70,7 +70,7 @@ if __name__ == "__main__": print(f"\nSearching Open Library for ISBN: {isbn}...\n") try: - book_summary = summerize_book(get_openlibrary_data(f"isbn/{isbn}")) + book_summary = summarize_book(get_openlibrary_data(f"isbn/{isbn}")) print("\n".join(f"{key}: {value}" for key, value in book_summary.items())) except JSONDecodeError: # Workaround for requests.exceptions.RequestException: print(f"Sorry, there are no results for ISBN: {isbn}.") From 424c2008473b00a8d3f31a9ad043526d95c31e69 Mon Sep 17 00:00:00 2001 From: Mozartus <32893711+Mozartuss@users.noreply.github.com> Date: Tue, 2 Nov 2021 11:06:39 +0100 Subject: [PATCH 187/726] Add gabor filter (#5289) * add gabor_filter.py * Update gabor_filter.py * update gabor_filter.py * add doctest * change import order * Update digital_image_processing/filters/gabor_filter.py Co-authored-by: John Law * Update gabor_filter.py * fix gabor filter calculation Co-authored-by: John Law --- .../filters/gabor_filter.py | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 digital_image_processing/filters/gabor_filter.py diff --git a/digital_image_processing/filters/gabor_filter.py b/digital_image_processing/filters/gabor_filter.py new file mode 100644 index 000000000..90aa049c2 --- /dev/null +++ b/digital_image_processing/filters/gabor_filter.py @@ -0,0 +1,85 @@ +# Implementation of the Gaborfilter +# https://en.wikipedia.org/wiki/Gabor_filter +import numpy as np +from cv2 import COLOR_BGR2GRAY, CV_8UC3, cvtColor, filter2D, imread, imshow, waitKey + + +def gabor_filter_kernel( + ksize: int, sigma: int, theta: int, lambd: int, gamma: int, psi: int +) -> np.ndarray: + """ + :param ksize: The kernelsize of the convolutional filter (ksize x ksize) + :param sigma: standard deviation of the gaussian bell curve + :param theta: The orientation of the normal to the parallel stripes + of Gabor function. + :param lambd: Wavelength of the sinusoidal component. + :param gamma: The spatial aspect ratio and specifies the ellipticity + of the support of Gabor function. + :param psi: The phase offset of the sinusoidal function. + + >>> gabor_filter_kernel(3, 8, 0, 10, 0, 0).tolist() + [[0.8027212023735046, 1.0, 0.8027212023735046], [0.8027212023735046, 1.0, \ +0.8027212023735046], [0.8027212023735046, 1.0, 0.8027212023735046]] + + """ + + # prepare kernel + # the kernel size have to be odd + if (ksize % 2) == 0: + ksize = ksize + 1 + gabor = np.zeros((ksize, ksize), dtype=np.float32) + + # each value + for y in range(ksize): + for x in range(ksize): + # distance from center + px = x - ksize // 2 + py = y - ksize // 2 + + # degree to radiant + _theta = theta / 180 * np.pi + cos_theta = np.cos(_theta) + sin_theta = np.sin(_theta) + + # get kernel x + _x = cos_theta * px + sin_theta * py + + # get kernel y + _y = -sin_theta * px + cos_theta * py + + # fill kernel + gabor[y, x] = np.exp( + -(_x ** 2 + gamma ** 2 * _y ** 2) / (2 * sigma ** 2) + ) * np.cos(2 * np.pi * _x / lambd + psi) + + return gabor + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + # read original image + img = imread("../image_data/lena.jpg") + # turn image in gray scale value + gray = cvtColor(img, COLOR_BGR2GRAY) + + # Apply multiple Kernel to detect edges + out = np.zeros(gray.shape[:2]) + for theta in [0, 30, 60, 90, 120, 150]: + """ + ksize = 10 + sigma = 8 + lambd = 10 + gamma = 0 + psi = 0 + """ + kernel_10 = gabor_filter_kernel(10, 8, theta, 10, 0, 0) + out += filter2D(gray, CV_8UC3, kernel_10) + out = out / out.max() * 255 + out = out.astype(np.uint8) + + imshow("Original", gray) + imshow("Gabor filter with 20x20 mask and 6 directions", out) + + waitKey(0) From 3c8fec1316aade09134255dd101060b4ec036241 Mon Sep 17 00:00:00 2001 From: Matthew Wisdom Date: Tue, 2 Nov 2021 03:07:36 -0700 Subject: [PATCH 188/726] Add Neville's algorithm for polynomial interpolation (#5447) * Added nevilles algorithm for polynomial interpolation * Added type hinting for neville_interpolate function arguments. * Added more descriptive names * Update nevilles_method.py * Fixed some linting issues * Fixed type hinting error * Fixed nevilles_method.py * Add ellipsis for doctest spanning multiple lines * Update nevilles_method.py Co-authored-by: John Law --- maths/nevilles_method.py | 56 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 maths/nevilles_method.py diff --git a/maths/nevilles_method.py b/maths/nevilles_method.py new file mode 100644 index 000000000..5583e4269 --- /dev/null +++ b/maths/nevilles_method.py @@ -0,0 +1,56 @@ +""" + Python program to show how to interpolate and evaluate a polynomial + using Neville's method. + Neville’s method evaluates a polynomial that passes through a + given set of x and y points for a particular x value (x0) using the + Newton polynomial form. + Reference: + https://rpubs.com/aaronsc32/nevilles-method-polynomial-interpolation +""" + + +def neville_interpolate(x_points: list, y_points: list, x0: int) -> list: + """ + Interpolate and evaluate a polynomial using Neville's method. + Arguments: + x_points, y_points: Iterables of x and corresponding y points through + which the polynomial passes. + x0: The value of x to evaluate the polynomial for. + Return Value: A list of the approximated value and the Neville iterations + table respectively. + >>> import pprint + >>> neville_interpolate((1,2,3,4,6), (6,7,8,9,11), 5)[0] + 10.0 + >>> pprint.pprint(neville_interpolate((1,2,3,4,6), (6,7,8,9,11), 99)[1]) + [[0, 6, 0, 0, 0], + [0, 7, 0, 0, 0], + [0, 8, 104.0, 0, 0], + [0, 9, 104.0, 104.0, 0], + [0, 11, 104.0, 104.0, 104.0]] + >>> neville_interpolate((1,2,3,4,6), (6,7,8,9,11), 99)[0] + 104.0 + >>> neville_interpolate((1,2,3,4,6), (6,7,8,9,11), '') + Traceback (most recent call last): + File "", line 1, in + ... + TypeError: unsupported operand type(s) for -: 'str' and 'int' + """ + n = len(x_points) + q = [[0] * n for i in range(n)] + for i in range(n): + q[i][1] = y_points[i] + + for i in range(2, n): + for j in range(i, n): + q[j][i] = ( + (x0 - x_points[j - i + 1]) * q[j][i - 1] + - (x0 - x_points[j]) * q[j - 1][i - 1] + ) / (x_points[j] - x_points[j - i + 1]) + + return [q[n - 1][n - 1], q] + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 24731b078c0e30d0f9bdd4ed96749f33574860c6 Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Tue, 2 Nov 2021 07:09:46 -0300 Subject: [PATCH 189/726] [mypy] fix type annotations in `data_structures/queue/circular_queue_linked_list.py` (#5749) * [mypy] fix type annotations in circular_queue_linked_list * Remove 10 blank lines Co-authored-by: Christian Clauss --- .../queue/circular_queue_linked_list.py | 37 ++++++++++++------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/data_structures/queue/circular_queue_linked_list.py b/data_structures/queue/circular_queue_linked_list.py index 1878403bd..e8c2b8bff 100644 --- a/data_structures/queue/circular_queue_linked_list.py +++ b/data_structures/queue/circular_queue_linked_list.py @@ -1,6 +1,8 @@ # Implementation of Circular Queue using linked lists # https://en.wikipedia.org/wiki/Circular_buffer +from __future__ import annotations + from typing import Any @@ -18,8 +20,8 @@ class CircularQueueLinkedList: """ def __init__(self, initial_capacity: int = 6) -> None: - self.front = None - self.rear = None + self.front: Node | None = None + self.rear: Node | None = None self.create_linked_list(initial_capacity) def create_linked_list(self, initial_capacity: int) -> None: @@ -27,7 +29,7 @@ class CircularQueueLinkedList: self.front = current_node self.rear = current_node previous_node = current_node - for i in range(1, initial_capacity): + for _ in range(1, initial_capacity): current_node = Node() previous_node.next = current_node current_node.prev = previous_node @@ -49,9 +51,14 @@ class CircularQueueLinkedList: >>> cq.is_empty() True """ - return self.front == self.rear and self.front.data is None - def first(self) -> Any: + return ( + self.front == self.rear + and self.front is not None + and self.front.data is None + ) + + def first(self) -> Any | None: """ Returns the first element of the queue >>> cq = CircularQueueLinkedList() @@ -74,7 +81,7 @@ class CircularQueueLinkedList: 'b' """ self.check_can_perform_operation() - return self.front.data + return self.front.data if self.front else None def enqueue(self, data: Any) -> None: """ @@ -92,11 +99,13 @@ class CircularQueueLinkedList: ... Exception: Empty Queue """ + if self.rear is None: + return + self.check_is_full() - if self.is_empty(): - self.rear.data = data - else: + if not self.is_empty(): self.rear = self.rear.next + if self.rear: self.rear.data = data def dequeue(self) -> Any: @@ -117,6 +126,8 @@ class CircularQueueLinkedList: Exception: Empty Queue """ self.check_can_perform_operation() + if self.rear is None or self.front is None: + return if self.front == self.rear: data = self.front.data self.front.data = None @@ -133,15 +144,15 @@ class CircularQueueLinkedList: raise Exception("Empty Queue") def check_is_full(self) -> None: - if self.rear.next == self.front: + if self.rear and self.rear.next == self.front: raise Exception("Full Queue") class Node: def __init__(self) -> None: - self.data = None - self.next = None - self.prev = None + self.data: Any | None = None + self.next: Node | None = None + self.prev: Node | None = None if __name__ == "__main__": From bdd135d40343daf047a00abc9a7360db192793d9 Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj Date: Tue, 2 Nov 2021 15:40:25 +0530 Subject: [PATCH 190/726] Split base85.py into functions, Add doctests (#5746) * Update base16.py * Rename base64_encoding.py to base64.py * Split into functions, Add doctests * Update base16.py --- ciphers/base16.py | 16 +++++------ ciphers/{base64_encoding.py => base64.py} | 0 ciphers/base85.py | 34 ++++++++++++++++++----- 3 files changed, 35 insertions(+), 15 deletions(-) rename ciphers/{base64_encoding.py => base64.py} (100%) diff --git a/ciphers/base16.py b/ciphers/base16.py index 1ef60868d..a149a6d8c 100644 --- a/ciphers/base16.py +++ b/ciphers/base16.py @@ -1,30 +1,30 @@ import base64 -def encode_to_b16(inp: str) -> bytes: +def base16_encode(inp: str) -> bytes: """ Encodes a given utf-8 string into base-16. - >>> encode_to_b16('Hello World!') + >>> base16_encode('Hello World!') b'48656C6C6F20576F726C6421' - >>> encode_to_b16('HELLO WORLD!') + >>> base16_encode('HELLO WORLD!') b'48454C4C4F20574F524C4421' - >>> encode_to_b16('') + >>> base16_encode('') b'' """ # encode the input into a bytes-like object and then encode b16encode that return base64.b16encode(inp.encode("utf-8")) -def decode_from_b16(b16encoded: bytes) -> str: +def base16_decode(b16encoded: bytes) -> str: """ Decodes from base-16 to a utf-8 string. - >>> decode_from_b16(b'48656C6C6F20576F726C6421') + >>> base16_decode(b'48656C6C6F20576F726C6421') 'Hello World!' - >>> decode_from_b16(b'48454C4C4F20574F524C4421') + >>> base16_decode(b'48454C4C4F20574F524C4421') 'HELLO WORLD!' - >>> decode_from_b16(b'') + >>> base16_decode(b'') '' """ # b16decode the input into bytes and decode that into a human readable string diff --git a/ciphers/base64_encoding.py b/ciphers/base64.py similarity index 100% rename from ciphers/base64_encoding.py rename to ciphers/base64.py diff --git a/ciphers/base85.py b/ciphers/base85.py index 9740299b9..afd1aff79 100644 --- a/ciphers/base85.py +++ b/ciphers/base85.py @@ -1,13 +1,33 @@ import base64 -def main() -> None: - inp = input("->") - encoded = inp.encode("utf-8") # encoded the input (we need a bytes like object) - a85encoded = base64.a85encode(encoded) # a85encoded the encoded string - print(a85encoded) - print(base64.a85decode(a85encoded).decode("utf-8")) # decoded it +def base85_encode(string: str) -> bytes: + """ + >>> base85_encode("") + b'' + >>> base85_encode("12345") + b'0etOA2#' + >>> base85_encode("base 85") + b'@UX=h+?24' + """ + # encoded the input to a bytes-like object and then a85encode that + return base64.a85encode(string.encode("utf-8")) + + +def base85_decode(a85encoded: bytes) -> str: + """ + >>> base85_decode(b"") + '' + >>> base85_decode(b"0etOA2#") + '12345' + >>> base85_decode(b"@UX=h+?24") + 'base 85' + """ + # a85decode the input into bytes and decode that into a human readable string + return base64.a85decode(a85encoded).decode("utf-8") if __name__ == "__main__": - main() + import doctest + + doctest.testmod() From 0124b73484aeb6a35b036842f382f7445fcec258 Mon Sep 17 00:00:00 2001 From: krishchopra02 <77331421+krishchopra02@users.noreply.github.com> Date: Tue, 2 Nov 2021 15:43:49 +0530 Subject: [PATCH 191/726] Add a gray_code_sequence.py file to the bit_manipulation folder (#5038) * Added a gray_code_sequence.py file to the bit_manipulation folder * Added a descriptive name for variable n changing it to bit count * Update gray_code_sequence.py Co-authored-by: krishchopra02 Co-authored-by: John Law --- bit_manipulation/gray_code_sequence.py | 94 ++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 bit_manipulation/gray_code_sequence.py diff --git a/bit_manipulation/gray_code_sequence.py b/bit_manipulation/gray_code_sequence.py new file mode 100644 index 000000000..636578d89 --- /dev/null +++ b/bit_manipulation/gray_code_sequence.py @@ -0,0 +1,94 @@ +def gray_code(bit_count: int) -> list: + """ + Takes in an integer n and returns a n-bit + gray code sequence + An n-bit gray code sequence is a sequence of 2^n + integers where: + + a) Every integer is between [0,2^n -1] inclusive + b) The sequence begins with 0 + c) An integer appears at most one times in the sequence + d)The binary representation of every pair of integers differ + by exactly one bit + e) The binary representation of first and last bit also + differ by exactly one bit + + >>> gray_code(2) + [0, 1, 3, 2] + + >>> gray_code(1) + [0, 1] + + >>> gray_code(3) + [0, 1, 3, 2, 6, 7, 5, 4] + + >>> gray_code(-1) + Traceback (most recent call last): + ... + ValueError: The given input must be positive + + >>> gray_code(10.6) + Traceback (most recent call last): + ... + TypeError: unsupported operand type(s) for <<: 'int' and 'float' + """ + + # bit count represents no. of bits in the gray code + if bit_count < 0: + raise ValueError("The given input must be positive") + + # get the generated string sequence + sequence = gray_code_sequence_string(bit_count) + # + # convert them to integers + for i in range(len(sequence)): + sequence[i] = int(sequence[i], 2) + + return sequence + + +def gray_code_sequence_string(bit_count: int) -> list: + """ + Will output the n-bit grey sequence as a + string of bits + + >>> gray_code_sequence_string(2) + ['00', '01', '11', '10'] + + >>> gray_code_sequence_string(1) + ['0', '1'] + """ + + # The approach is a recursive one + # Base case achieved when either n = 0 or n=1 + if bit_count == 0: + return ["0"] + + if bit_count == 1: + return ["0", "1"] + + seq_len = 1 << bit_count # defines the length of the sequence + # 1<< n is equivalent to 2^n + + # recursive answer will generate answer for n-1 bits + smaller_sequence = gray_code_sequence_string(bit_count - 1) + + sequence = [] + + # append 0 to first half of the smaller sequence generated + for i in range(seq_len // 2): + generated_no = "0" + smaller_sequence[i] + sequence.append(generated_no) + + # append 1 to second half ... start from the end of the list + for i in reversed(range(seq_len // 2)): + generated_no = "1" + smaller_sequence[i] + sequence.append(generated_no) + + return sequence + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From dd19d8120df2eeba8f3173f952187be4e7656144 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Tue, 2 Nov 2021 16:07:07 +0300 Subject: [PATCH 192/726] Uncomment code that has been commented due to slow execution affecting Travis (#5745) --- project_euler/problem_009/sol3.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/project_euler/problem_009/sol3.py b/project_euler/problem_009/sol3.py index 03aed4b70..d299f821d 100644 --- a/project_euler/problem_009/sol3.py +++ b/project_euler/problem_009/sol3.py @@ -24,9 +24,8 @@ def solution() -> int: 1. a**2 + b**2 = c**2 2. a + b + c = 1000 - # The code below has been commented due to slow execution affecting Travis. - # >>> solution() - # 31875000 + >>> solution() + 31875000 """ return [ From 60ad32920d92a6095b28aa6952a759b40e5759c7 Mon Sep 17 00:00:00 2001 From: Leoriem-code <73761711+Leoriem-code@users.noreply.github.com> Date: Tue, 2 Nov 2021 22:17:57 +0100 Subject: [PATCH 193/726] fixed typo for codespell (#5753) --- project_euler/problem_045/sol1.py | 2 +- web_programming/get_user_tweets.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/project_euler/problem_045/sol1.py b/project_euler/problem_045/sol1.py index cb30a4d97..cdf5c14cf 100644 --- a/project_euler/problem_045/sol1.py +++ b/project_euler/problem_045/sol1.py @@ -43,7 +43,7 @@ def is_pentagonal(n: int) -> bool: def solution(start: int = 144) -> int: """ - Returns the next number which is traingular, pentagonal and hexagonal. + Returns the next number which is triangular, pentagonal and hexagonal. >>> solution(144) 1533776805 """ diff --git a/web_programming/get_user_tweets.py b/web_programming/get_user_tweets.py index 0f70201dc..28cf85541 100644 --- a/web_programming/get_user_tweets.py +++ b/web_programming/get_user_tweets.py @@ -32,7 +32,7 @@ def get_all_tweets(screen_name: str) -> None: while len(new_tweets) > 0: print(f"getting tweets before {oldest}") - # all subsiquent requests use the max_id param to prevent duplicates + # all subsequent requests use the max_id param to prevent duplicates new_tweets = api.user_timeline( screen_name=screen_name, count=200, max_id=oldest ) From 37bc6bdebf159d395b559dd7094934a337d59c8a Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Wed, 3 Nov 2021 00:28:09 +0300 Subject: [PATCH 194/726] Replace Travis CI mentions with GitHub actions (#5751) --- CONTRIBUTING.md | 4 ++-- project_euler/README.md | 4 ++-- project_euler/problem_012/sol2.py | 5 ++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4df60ed3f..c9525aa40 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,7 +23,7 @@ __Improving comments__ and __writing proper tests__ are also highly welcome. We appreciate any contribution, from fixing a grammar mistake in a comment to implementing complex algorithms. Please read this section if you are contributing your work. -Your contribution will be tested by our [automated testing on Travis CI](https://travis-ci.org/TheAlgorithms/Python/pull_requests) to save time and mental energy. After you have submitted your pull request, you should see the Travis tests start to run at the bottom of your submission page. If those tests fail, then click on the ___details___ button try to read through the Travis output to understand the failure. If you do not understand, please leave a comment on your submission page and a community member will try to help. +Your contribution will be tested by our [automated testing on GitHub Actions](https://github.com/TheAlgorithms/Python/actions) to save time and mental energy. After you have submitted your pull request, you should see the GitHub Actions tests start to run at the bottom of your submission page. If those tests fail, then click on the ___details___ button try to read through the GitHub Actions output to understand the failure. If you do not understand, please leave a comment on your submission page and a community member will try to help. Please help us keep our issue list small by adding fixes: #{$ISSUE_NO} to the commit message of pull requests that resolve open issues. GitHub will use this tag to auto-close the issue when the PR is merged. @@ -170,7 +170,7 @@ We want your work to be readable by others; therefore, we encourage you to note - If possible, follow the standard *within* the folder you are submitting to. - If you have modified/added code work, make sure the code compiles before submitting. - If you have modified/added documentation work, ensure your language is concise and contains no grammar errors. -- Do not update the README.md or DIRECTORY.md file which will be periodically autogenerated by our Travis CI processes. +- Do not update the README.md or DIRECTORY.md file which will be periodically autogenerated by our GitHub Actions processes. - Add a corresponding explanation to [Algorithms-Explanation](https://github.com/TheAlgorithms/Algorithms-Explanation) (Optional but recommended). - All submissions will be tested with [__mypy__](http://www.mypy-lang.org) so we encourage you to add [__Python type hints__](https://docs.python.org/3/library/typing.html) where it makes sense to do so. diff --git a/project_euler/README.md b/project_euler/README.md index c4c0a8544..e3dc035ee 100644 --- a/project_euler/README.md +++ b/project_euler/README.md @@ -5,7 +5,7 @@ Problems are taken from https://projecteuler.net/, the Project Euler. [Problems Project Euler is a series of challenging mathematical/computer programming problems that require more than just mathematical insights to solve. Project Euler is ideal for mathematicians who are learning to code. -The solutions will be checked by our [automated testing on Travis CI](https://travis-ci.com/github/TheAlgorithms/Python/pull_requests) with the help of [this script](https://github.com/TheAlgorithms/Python/blob/master/scripts/validate_solutions.py). The efficiency of your code is also checked. You can view the top 10 slowest solutions on Travis CI logs (under `slowest 10 durations`) and open a pull request to improve those solutions. +The solutions will be checked by our [automated testing on GitHub Actions](https://github.com/TheAlgorithms/Python/actions) with the help of [this script](https://github.com/TheAlgorithms/Python/blob/master/scripts/validate_solutions.py). The efficiency of your code is also checked. You can view the top 10 slowest solutions on GitHub Actions logs (under `slowest 10 durations`) and open a pull request to improve those solutions. ## Solution Guidelines @@ -28,7 +28,7 @@ Welcome to [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python)! Befo * When the `solution` function is called without any arguments like so: `solution()`, it should return the answer to the problem. * Every function, which includes all the helper functions, if any, and the main solution function, should have `doctest` in the function docstring along with a brief statement mentioning what the function is about. - * There should not be a `doctest` for testing the answer as that is done by our Travis CI build using this [script](https://github.com/TheAlgorithms/Python/blob/master/scripts/validate_solutions.py). Keeping in mind the above example of [Problem 1](https://projecteuler.net/problem=1): + * There should not be a `doctest` for testing the answer as that is done by our GitHub Actions build using this [script](https://github.com/TheAlgorithms/Python/blob/master/scripts/validate_solutions.py). Keeping in mind the above example of [Problem 1](https://projecteuler.net/problem=1): ```python def solution(limit: int = 1000): diff --git a/project_euler/problem_012/sol2.py b/project_euler/problem_012/sol2.py index 7578caa98..1cc79fc4c 100644 --- a/project_euler/problem_012/sol2.py +++ b/project_euler/problem_012/sol2.py @@ -36,9 +36,8 @@ def solution(): """Returns the value of the first triangle number to have over five hundred divisors. - # The code below has been commented due to slow execution affecting Travis. - # >>> solution() - # 76576500 + >>> solution() + 76576500 """ return next(i for i in triangle_number_generator() if count_divisors(i) > 500) From 0ea5c734e13e40fcefdea336bc5f735536f133a0 Mon Sep 17 00:00:00 2001 From: Souvik Ghosh <42302494+SouvikGhosh05@users.noreply.github.com> Date: Thu, 4 Nov 2021 01:54:50 +0530 Subject: [PATCH 196/726] sock_merchant.py: Matching socks by color (#5761) * Python file for finding number of pairs * updating DIRECTORY.md * fixed iterative_pair.py * further fixed with type casting * fixed naming conventions * further fixed with naming convention * documented done * build issue fixed * updating DIRECTORY.md * Revert "documented done" This reverts commit 3be15ca374f3ea3f01f725912dba59b939b058b5. * Update canny.py * Update test_digital_image_processing.py * Update sobel_filter.py * requirements.txt fixed * keras<2.7.0 * Update sock_merchant.py * doctest with black fixed * Update sock_merchant.py Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss --- DIRECTORY.md | 6 +++++- maths/sock_merchant.py | 20 ++++++++++++++++++++ requirements.txt | 2 +- 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 maths/sock_merchant.py diff --git a/DIRECTORY.md b/DIRECTORY.md index e70c0aab6..fd164c92e 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -39,6 +39,7 @@ * [Binary Xor Operator](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_xor_operator.py) * [Count 1S Brian Kernighan Method](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/count_1s_brian_kernighan_method.py) * [Count Number Of One Bits](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/count_number_of_one_bits.py) + * [Gray Code Sequence](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/gray_code_sequence.py) * [Reverse Bits](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/reverse_bits.py) * [Single Bit Manipulation Operations](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/single_bit_manipulation_operations.py) @@ -63,7 +64,7 @@ * [Baconian Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/baconian_cipher.py) * [Base16](https://github.com/TheAlgorithms/Python/blob/master/ciphers/base16.py) * [Base32](https://github.com/TheAlgorithms/Python/blob/master/ciphers/base32.py) - * [Base64 Encoding](https://github.com/TheAlgorithms/Python/blob/master/ciphers/base64_encoding.py) + * [Base64](https://github.com/TheAlgorithms/Python/blob/master/ciphers/base64.py) * [Base85](https://github.com/TheAlgorithms/Python/blob/master/ciphers/base85.py) * [Beaufort Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/beaufort_cipher.py) * [Bifid](https://github.com/TheAlgorithms/Python/blob/master/ciphers/bifid.py) @@ -219,6 +220,7 @@ * Filters * [Bilateral Filter](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/filters/bilateral_filter.py) * [Convolve](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/filters/convolve.py) + * [Gabor Filter](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/filters/gabor_filter.py) * [Gaussian Filter](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/filters/gaussian_filter.py) * [Median Filter](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/filters/median_filter.py) * [Sobel Filter](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/filters/sobel_filter.py) @@ -511,6 +513,7 @@ * [Modular Exponential](https://github.com/TheAlgorithms/Python/blob/master/maths/modular_exponential.py) * [Monte Carlo](https://github.com/TheAlgorithms/Python/blob/master/maths/monte_carlo.py) * [Monte Carlo Dice](https://github.com/TheAlgorithms/Python/blob/master/maths/monte_carlo_dice.py) + * [Nevilles Method](https://github.com/TheAlgorithms/Python/blob/master/maths/nevilles_method.py) * [Newton Raphson](https://github.com/TheAlgorithms/Python/blob/master/maths/newton_raphson.py) * [Number Of Digits](https://github.com/TheAlgorithms/Python/blob/master/maths/number_of_digits.py) * [Numerical Integration](https://github.com/TheAlgorithms/Python/blob/master/maths/numerical_integration.py) @@ -546,6 +549,7 @@ * [Sieve Of Eratosthenes](https://github.com/TheAlgorithms/Python/blob/master/maths/sieve_of_eratosthenes.py) * [Sigmoid](https://github.com/TheAlgorithms/Python/blob/master/maths/sigmoid.py) * [Simpson Rule](https://github.com/TheAlgorithms/Python/blob/master/maths/simpson_rule.py) + * [Sock Merchant](https://github.com/TheAlgorithms/Python/blob/master/maths/sock_merchant.py) * [Softmax](https://github.com/TheAlgorithms/Python/blob/master/maths/softmax.py) * [Square Root](https://github.com/TheAlgorithms/Python/blob/master/maths/square_root.py) * [Sum Of Arithmetic Series](https://github.com/TheAlgorithms/Python/blob/master/maths/sum_of_arithmetic_series.py) diff --git a/maths/sock_merchant.py b/maths/sock_merchant.py new file mode 100644 index 000000000..304efec9b --- /dev/null +++ b/maths/sock_merchant.py @@ -0,0 +1,20 @@ +from collections import Counter + + +def sock_merchant(colors: list[int]) -> int: + """ + >>> sock_merchant([10, 20, 20, 10, 10, 30, 50, 10, 20]) + 3 + >>> sock_merchant([1, 1, 3, 3]) + 2 + """ + return sum(socks_by_color // 2 for socks_by_color in Counter(colors).values()) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + + colors = [int(x) for x in input("Enter socks by color :").rstrip().split()] + print(f"sock_merchant({colors}) = {sock_merchant(colors)}") diff --git a/requirements.txt b/requirements.txt index c28238a07..ef4e18043 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ beautifulsoup4 fake_useragent -keras +keras<2.7.0 lxml matplotlib numpy From 765be4581e66f1e8e92f24606c243a8cd45e4d3c Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Wed, 3 Nov 2021 23:32:10 +0300 Subject: [PATCH 197/726] Improve Project Euler problem 012 solution 2 (#5760) * Improve solution * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- project_euler/problem_012/sol2.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/project_euler/problem_012/sol2.py b/project_euler/problem_012/sol2.py index 1cc79fc4c..380a9b74b 100644 --- a/project_euler/problem_012/sol2.py +++ b/project_euler/problem_012/sol2.py @@ -29,7 +29,18 @@ 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) + divisors_count = 1 + i = 2 + while i * i <= n: + multiplicity = 0 + while n % i == 0: + n //= i + multiplicity += 1 + divisors_count *= multiplicity + 1 + i += 1 + if n > 1: + divisors_count *= 2 + return divisors_count def solution(): From 7954a3ae166db66ae6a43043c76417dda688a8e5 Mon Sep 17 00:00:00 2001 From: Andrew Grangaard Date: Wed, 3 Nov 2021 13:32:49 -0700 Subject: [PATCH 198/726] [mypy] Fixes typing errors in other/dpll (#5759) + As per usage examples, clause literals are a list of strings. + Note: symbols extracted from literals are expected to be exactly two characters. + self.literal boolean values are initialized to None, so must be optional + model values should be Booleans, but aren't guaranteed to be non-None in the code. + uses newer '... | None' annotation for Optional values + clauses are passed to the Formula initializer as both lists and sets, they are stored as lists. Returned clauses will always be lists. + use explicit tuple annotation from __future__ rather than using (..., ...) in return signatures + mapping returned by dpll_algorithm is optional per the documentation. --- other/davisb_putnamb_logemannb_loveland.py | 35 +++++++++++----------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/other/davisb_putnamb_logemannb_loveland.py b/other/davisb_putnamb_logemannb_loveland.py index 00068930b..031f0dbed 100644 --- a/other/davisb_putnamb_logemannb_loveland.py +++ b/other/davisb_putnamb_logemannb_loveland.py @@ -11,6 +11,7 @@ For more information about the algorithm: https://en.wikipedia.org/wiki/DPLL_alg from __future__ import annotations import random +from typing import Iterable class Clause: @@ -27,12 +28,12 @@ class Clause: True """ - def __init__(self, literals: list[int]) -> None: + def __init__(self, literals: list[str]) -> None: """ Represent the literals and an assignment in a clause." """ # Assign all literals to None initially - self.literals = {literal: None for literal in literals} + self.literals: dict[str, bool | None] = {literal: None for literal in literals} def __str__(self) -> str: """ @@ -52,7 +53,7 @@ class Clause: """ return len(self.literals) - def assign(self, model: dict[str, bool]) -> None: + def assign(self, model: dict[str, bool | None]) -> None: """ Assign values to literals of the clause as given by model. """ @@ -68,7 +69,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 | None]) -> bool | None: """ Evaluates the clause with the assignments in model. This has the following steps: @@ -97,7 +98,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: Iterable[Clause]) -> None: """ Represent the number of clauses and the clauses themselves. """ @@ -139,14 +140,14 @@ def generate_formula() -> Formula: """ Randomly generate a formula. """ - clauses = set() + clauses: set[Clause] = set() no_of_clauses = random.randint(1, 10) while len(clauses) < no_of_clauses: clauses.add(generate_clause()) - return Formula(set(clauses)) + return Formula(clauses) -def generate_parameters(formula: Formula) -> (list[Clause], list[str]): +def generate_parameters(formula: Formula) -> tuple[list[Clause], list[str]]: """ Return the clauses and symbols from a formula. A symbol is the uncomplemented form of a literal. @@ -173,8 +174,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 | None] +) -> tuple[list[str], dict[str, bool | None]]: """ Return pure symbols and their values to satisfy clause. Pure symbols are symbols in a formula that exist only @@ -198,11 +199,11 @@ def find_pure_symbols( {'A1': True, 'A2': False, 'A3': True, 'A5': False} """ pure_symbols = [] - assignment = dict() + assignment: dict[str, bool | None] = dict() literals = [] for clause in clauses: - if clause.evaluate(model) is True: + if clause.evaluate(model): continue for literal in clause.literals: literals.append(literal) @@ -225,8 +226,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 | None] +) -> tuple[list[str], dict[str, bool | None]]: """ Returns the unit symbols and their values to satisfy clause. Unit symbols are symbols in a formula that are: @@ -263,7 +264,7 @@ def find_unit_clauses( Ncount += 1 if Fcount == len(clause) - 1 and Ncount == 1: unit_symbols.append(sym) - assignment = dict() + assignment: dict[str, bool | None] = dict() for i in unit_symbols: symbol = i[:2] assignment[symbol] = len(i) == 2 @@ -273,8 +274,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 | None] +) -> tuple[bool | None, dict[str, bool | None] | None]: """ Returns the model if the formula is satisfiable, else None This has the following steps: From 331fe6d3bc075ac2d91af766cf2bdf7df09f1281 Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Wed, 3 Nov 2021 17:34:08 -0300 Subject: [PATCH 199/726] [mypy] Fix type annotations in `data_structures/binary_tree/lowest_common_ancestor.py` (#5757) * Fix type annotations in lowest_common_ancestor.py * Refactor line 53 in lowest_common_ancestor.py --- .../binary_tree/lowest_common_ancestor.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py index 2f1e893fc..651037703 100644 --- a/data_structures/binary_tree/lowest_common_ancestor.py +++ b/data_structures/binary_tree/lowest_common_ancestor.py @@ -3,7 +3,7 @@ from __future__ import annotations -import queue +from queue import Queue def swap(a: int, b: int) -> tuple[int, int]: @@ -37,7 +37,7 @@ def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]: # returns lca of node u,v def lowest_common_ancestor( u: int, v: int, level: list[int], parent: list[list[int]] -) -> list[list[int]]: +) -> int: # u must be deeper in the tree than v if level[u] < level[v]: u, v = swap(u, v) @@ -50,7 +50,7 @@ def lowest_common_ancestor( return u # moving both nodes upwards till lca in found for i in range(18, -1, -1): - if parent[i][u] != 0 and parent[i][u] != parent[i][v]: + if parent[i][u] not in [0, parent[i][v]]: u, v = parent[i][u], parent[i][v] # returning longest common ancestor of u,v return parent[0][u] @@ -61,8 +61,8 @@ def breadth_first_search( level: list[int], parent: list[list[int]], max_node: int, - graph: dict[int, int], - root=1, + graph: dict[int, list[int]], + root: int = 1, ) -> tuple[list[int], list[list[int]]]: """ sets every nodes direct parent @@ -70,7 +70,7 @@ def breadth_first_search( calculates depth of each node from root node """ level[root] = 0 - q = queue.Queue(maxsize=max_node) + q: Queue[int] = Queue(maxsize=max_node) q.put(root) while q.qsize() != 0: u = q.get() @@ -88,7 +88,7 @@ def main() -> None: parent = [[0 for _ in range(max_node + 10)] for _ in range(20)] # initializing with -1 which means every node is unvisited level = [-1 for _ in range(max_node + 10)] - graph = { + graph: dict[int, list[int]] = { 1: [2, 3, 4], 2: [5], 3: [6, 7], From 9655ec2a05f1ebbafb3c0ac5acf3d6278b498030 Mon Sep 17 00:00:00 2001 From: Divyesh Vishwakarma Date: Thu, 4 Nov 2021 16:18:57 +0530 Subject: [PATCH 200/726] Added newtons_second_law_of_motion.py (#5474) --- physics/newtons_second_law_of_motion.py | 81 +++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 physics/newtons_second_law_of_motion.py diff --git a/physics/newtons_second_law_of_motion.py b/physics/newtons_second_law_of_motion.py new file mode 100644 index 000000000..cb53f8f65 --- /dev/null +++ b/physics/newtons_second_law_of_motion.py @@ -0,0 +1,81 @@ +""" +Description : +Newton's second law of motion pertains to the behavior of objects for which +all existing forces are not balanced. +The second law states that the acceleration of an object is dependent upon two variables +- the net force acting upon the object and the mass of the object. +The acceleration of an object depends directly +upon the net force acting upon the object, +and inversely upon the mass of the object. +As the force acting upon an object is increased, +the acceleration of the object is increased. +As the mass of an object is increased, the acceleration of the object is decreased. +Source: https://www.physicsclassroom.com/class/newtlaws/Lesson-3/Newton-s-Second-Law +Formulation: Fnet = m • a +Diagrammatic Explanation: + Forces are unbalanced + | + | + | + V + There is acceleration + /\ + / \ + / \ + / \ + / \ + / \ + / \ + __________________ ____ ________________ + |The acceleration | |The acceleration | + |depends directly | |depends inversely | + |on the net Force | |upon the object's | + |_________________| |mass_______________| +Units: +1 Newton = 1 kg X meters / (seconds^2) +How to use? +Inputs: + ___________________________________________________ + |Name | Units | Type | + |-------------|-------------------------|-----------| + |mass | (in kgs) | float | + |-------------|-------------------------|-----------| + |acceleration | (in meters/(seconds^2)) | float | + |_____________|_________________________|___________| + +Output: + ___________________________________________________ + |Name | Units | Type | + |-------------|-------------------------|-----------| + |force | (in Newtons) | float | + |_____________|_________________________|___________| + +""" + + +def newtons_second_law_of_motion(mass: float, acceleration: float) -> float: + """ + >>> newtons_second_law_of_motion(10, 10) + 100 + >>> newtons_second_law_of_motion(2.0, 1) + 2.0 + """ + force = float() + try: + force = mass * acceleration + except Exception: + return -0.0 + return force + + +if __name__ == "__main__": + import doctest + + # run doctest + doctest.testmod() + + # demo + mass = 12.5 + acceleration = 10 + force = newtons_second_law_of_motion(mass, acceleration) + print("The force is ", force, "N") From 47dd31f4a1aaa371f3b822e178fd273c68f45962 Mon Sep 17 00:00:00 2001 From: Leoriem-code <73761711+Leoriem-code@users.noreply.github.com> Date: Thu, 4 Nov 2021 11:49:36 +0100 Subject: [PATCH 201/726] Add README files 1/7 (#5754) * Added 5 README files * corrected arithmetic_analysis README * Update audio_filters/README.md Co-authored-by: John Law * Update backtracking/README.md Co-authored-by: John Law * Update bit_manipulation/README.md Co-authored-by: John Law Co-authored-by: John Law --- arithmetic_analysis/README.md | 7 +++++++ audio_filters/README.md | 9 +++++++++ backtracking/README.md | 8 ++++++++ bit_manipulation/README.md | 17 +++++++++++------ boolean_algebra/README.md | 7 +++++++ 5 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 arithmetic_analysis/README.md create mode 100644 audio_filters/README.md create mode 100644 backtracking/README.md create mode 100644 boolean_algebra/README.md diff --git a/arithmetic_analysis/README.md b/arithmetic_analysis/README.md new file mode 100644 index 000000000..45cf321eb --- /dev/null +++ b/arithmetic_analysis/README.md @@ -0,0 +1,7 @@ +# Arithmetic analysis + +Arithmetic analysis is a branch of mathematics that deals with solving linear equations. + +* +* +* diff --git a/audio_filters/README.md b/audio_filters/README.md new file mode 100644 index 000000000..4419bd8bd --- /dev/null +++ b/audio_filters/README.md @@ -0,0 +1,9 @@ +# Audio Filter + +Audio filters work on the frequency of an audio signal to attenuate unwanted frequency and amplify wanted ones. +They are used within anything related to sound, whether it is radio communication or a hi-fi system. + +* +* +* +* diff --git a/backtracking/README.md b/backtracking/README.md new file mode 100644 index 000000000..d4975dfb5 --- /dev/null +++ b/backtracking/README.md @@ -0,0 +1,8 @@ +# Backtracking + +Backtracking is a way to speed up the search process by removing candidates when they can't be the solution of a problem. + +* +* +* +* diff --git a/bit_manipulation/README.md b/bit_manipulation/README.md index e5f82a270..3f5e028be 100644 --- a/bit_manipulation/README.md +++ b/bit_manipulation/README.md @@ -1,6 +1,11 @@ -* https://docs.python.org/3/reference/expressions.html#binary-bitwise-operations -* https://docs.python.org/3/reference/expressions.html#unary-arithmetic-and-bitwise-operations -* https://docs.python.org/3/library/stdtypes.html#bitwise-operations-on-integer-types -* https://wiki.python.org/moin/BitManipulation -* https://wiki.python.org/moin/BitwiseOperators -* https://www.tutorialspoint.com/python3/bitwise_operators_example.htm +# Bit manipulation + +Bit manipulation is the act of manipulating bits to detect errors (hamming code), encrypts and decrypts messages (more on that in the 'ciphers' folder) or just do anything at the lowest level of your computer. + +* +* +* +* +* +* +* diff --git a/boolean_algebra/README.md b/boolean_algebra/README.md new file mode 100644 index 000000000..45969c855 --- /dev/null +++ b/boolean_algebra/README.md @@ -0,0 +1,7 @@ +# Boolean Algebra + +Boolean algebra is used to do arithmetic with bits of values True (1) or False (0). +There are three basic operations: 'and', 'or' and 'not'. + +* +* From 3815a97575a2ab3209fd82ac4077942020c2d9bd Mon Sep 17 00:00:00 2001 From: Sailesh Shrestha <34860977+werewolf-65@users.noreply.github.com> Date: Thu, 4 Nov 2021 21:03:38 +0545 Subject: [PATCH 202/726] Add all_construct dynamic programming implementation (#5626) * Add all_construct dynamic programming implementation * all_construct: remove the main function * all_construct: Add type hints * all_construct: changed map to list comprehension,fix mutable default arguments * all_construct: fixed type hints * all_construct: cleaner code for initializing word_bank argument * all_construct: added an import for annotations * all_construct: added None in the argument with word_bank * all_construct: fixed a type hint * all_construct: Fixed some more type hints --- dynamic_programming/all_construct.py | 58 ++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 dynamic_programming/all_construct.py diff --git a/dynamic_programming/all_construct.py b/dynamic_programming/all_construct.py new file mode 100644 index 000000000..5ffed2caa --- /dev/null +++ b/dynamic_programming/all_construct.py @@ -0,0 +1,58 @@ +""" +Program to list all the ways a target string can be +constructed from the given list of substrings +""" +from __future__ import annotations + + +def all_construct(target: str, word_bank: list[str] | None = None) -> list[list[str]]: + """ + returns the list containing all the possible + combinations a string(target) can be constructed from + the given list of substrings(word_bank) + >>> all_construct("hello", ["he", "l", "o"]) + [['he', 'l', 'l', 'o']] + >>> all_construct("purple",["purp","p","ur","le","purpl"]) + [['purp', 'le'], ['p', 'ur', 'p', 'le']] + """ + + word_bank = word_bank or [] + # create a table + table_size: int = len(target) + 1 + + table: list[list[list[str]]] = [] + for i in range(table_size): + table.append([]) + # seed value + table[0] = [[]] # because empty string has empty combination + + # iterate through the indices + for i in range(table_size): + # condition + if table[i] != []: + for word in word_bank: + # slice condition + if target[i : i + len(word)] == word: + new_combinations: list[list[str]] = [ + [word] + way for way in table[i] + ] + # adds the word to every combination the current position holds + # now,push that combination to the table[i+len(word)] + table[i + len(word)] += new_combinations + + # combinations are in reverse order so reverse for better output + for combination in table[len(target)]: + combination.reverse() + + return table[len(target)] + + +if __name__ == "__main__": + print(all_construct("jwajalapa", ["jwa", "j", "w", "a", "la", "lapa"])) + print(all_construct("rajamati", ["s", "raj", "amat", "raja", "ma", "i", "t"])) + print( + all_construct( + "hexagonosaurus", + ["h", "ex", "hex", "ag", "ago", "ru", "auru", "rus", "go", "no", "o", "s"], + ) + ) From b6eb448e63a7eb8b145a600c368419e77872f134 Mon Sep 17 00:00:00 2001 From: Jaydeep Das Date: Thu, 4 Nov 2021 21:06:22 +0530 Subject: [PATCH 203/726] Added reddit.py to get data from reddit (#5698) * Rewritten reddit.py * Removed logging module import * Fixed minor bug which was causing extreme rate limiting * Update reddit.py * Update reddit.py * Update reddit.py Co-authored-by: Christian Clauss --- web_programming/reddit.py | 53 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 web_programming/reddit.py diff --git a/web_programming/reddit.py b/web_programming/reddit.py new file mode 100644 index 000000000..672109f13 --- /dev/null +++ b/web_programming/reddit.py @@ -0,0 +1,53 @@ +from __future__ import annotations + +import requests + +valid_terms = set( + """approved_at_utc approved_by author_flair_background_color +author_flair_css_class author_flair_richtext author_flair_template_id author_fullname +author_premium can_mod_post category clicked content_categories created_utc downs +edited gilded gildings hidden hide_score is_created_from_ads_ui is_meta +is_original_content is_reddit_media_domain is_video link_flair_css_class +link_flair_richtext link_flair_text link_flair_text_color media_embed mod_reason_title +name permalink pwls quarantine saved score secure_media secure_media_embed selftext +subreddit subreddit_name_prefixed subreddit_type thumbnail title top_awarded_type +total_awards_received ups upvote_ratio url user_reports""".split() +) + + +def get_subreddit_data( + subreddit: str, limit: int = 1, age: str = "new", wanted_data: list | None = None +) -> dict: + """ + subreddit : Subreddit to query + limit : Number of posts to fetch + age : ["new", "top", "hot"] + wanted_data : Get only the required data in the list + + >>> pass + """ + wanted_data = wanted_data or [] + if invalid_search_terms := ", ".join(sorted(set(wanted_data) - valid_terms)): + raise ValueError(f"Invalid search term: {invalid_search_terms}") + response = requests.get( + f"https://reddit.com/r/{subreddit}/{age}.json?limit={limit}", + headers={"User-agent": "A random string"}, + ) + if response.status_code == 429: + raise requests.HTTPError + + data = response.json() + if not wanted_data: + return {id_: data["data"]["children"][id_] for id_ in range(limit)} + + data_dict = {} + for id_ in range(limit): + data_dict[id_] = { + item: data["data"]["children"][id_]["data"][item] for item in wanted_data + } + return data_dict + + +if __name__ == "__main__": + # If you get Error 429, that means you are rate limited.Try after some time + print(get_subreddit_data("learnpython", wanted_data=["title", "url", "selftext"])) From e835e9685617198095ca44f5d9fda7dc02a3ec83 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Thu, 4 Nov 2021 18:37:47 +0300 Subject: [PATCH 204/726] Improve Project Euler problem 014 solution 1 (#5747) * Improve solution * Uncomment code that has been commented due to slow execution affecting Travis * Fix --- project_euler/problem_014/sol1.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/project_euler/problem_014/sol1.py b/project_euler/problem_014/sol1.py index 43aa4e726..033349590 100644 --- a/project_euler/problem_014/sol1.py +++ b/project_euler/problem_014/sol1.py @@ -25,9 +25,8 @@ def solution(n: int = 1000000) -> int: n → n/2 (n is even) n → 3n + 1 (n is odd) - # The code below has been commented due to slow execution affecting Travis. - # >>> solution(1000000) - # 837799 + >>> solution(1000000) + 837799 >>> solution(200) 171 >>> solution(5000) @@ -35,14 +34,18 @@ def solution(n: int = 1000000) -> int: >>> solution(15000) 13255 """ - largest_number = 0 - pre_counter = 0 + largest_number = 1 + pre_counter = 1 + counters = {1: 1} - for input1 in range(n): - counter = 1 + for input1 in range(2, n): + counter = 0 number = input1 - while number > 1: + while True: + if number in counters: + counter += counters[number] + break if number % 2 == 0: number //= 2 counter += 1 @@ -50,6 +53,9 @@ def solution(n: int = 1000000) -> int: number = (3 * number) + 1 counter += 1 + if input1 not in counters: + counters[input1] = counter + if counter > pre_counter: largest_number = input1 pre_counter = counter From 7a605766fe7fe79a00ba1f30447877be4b77a6f2 Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Thu, 4 Nov 2021 12:38:43 -0300 Subject: [PATCH 205/726] [mypy] Fix type annotations in `data_structures/binary_tree/red_black_tree.py` (#5739) * [mypy] Fix type annotations in red_black_tree.py * Remove blank lines * Update red_black_tree.py --- data_structures/binary_tree/red_black_tree.py | 121 ++++++++++-------- 1 file changed, 69 insertions(+), 52 deletions(-) diff --git a/data_structures/binary_tree/red_black_tree.py b/data_structures/binary_tree/red_black_tree.py index e27757f20..35517f307 100644 --- a/data_structures/binary_tree/red_black_tree.py +++ b/data_structures/binary_tree/red_black_tree.py @@ -51,6 +51,8 @@ class RedBlackTree: """ parent = self.parent right = self.right + if right is None: + return self self.right = right.left if self.right: self.right.parent = self @@ -69,6 +71,8 @@ class RedBlackTree: returns the new root to this subtree. Performing one rotation can be done in O(1). """ + if self.left is None: + return self parent = self.parent left = self.left self.left = left.right @@ -123,23 +127,30 @@ class RedBlackTree: if color(uncle) == 0: if self.is_left() and self.parent.is_right(): self.parent.rotate_right() - self.right._insert_repair() + if self.right: + self.right._insert_repair() elif self.is_right() and self.parent.is_left(): self.parent.rotate_left() - self.left._insert_repair() + if self.left: + self.left._insert_repair() elif self.is_left(): - self.grandparent.rotate_right() - self.parent.color = 0 - self.parent.right.color = 1 + if self.grandparent: + self.grandparent.rotate_right() + self.parent.color = 0 + if self.parent.right: + self.parent.right.color = 1 else: - self.grandparent.rotate_left() - self.parent.color = 0 - self.parent.left.color = 1 + if self.grandparent: + self.grandparent.rotate_left() + self.parent.color = 0 + if self.parent.left: + self.parent.left.color = 1 else: self.parent.color = 0 - uncle.color = 0 - self.grandparent.color = 1 - self.grandparent._insert_repair() + if uncle and self.grandparent: + uncle.color = 0 + self.grandparent.color = 1 + self.grandparent._insert_repair() def remove(self, label: int) -> RedBlackTree: """Remove label from this tree.""" @@ -149,8 +160,9 @@ class RedBlackTree: # so we replace this node with the greatest one less than # it and remove that. value = self.left.get_max() - self.label = value - self.left.remove(value) + if value is not None: + self.label = value + self.left.remove(value) else: # This node has at most one non-None child, so we don't # need to replace @@ -160,10 +172,11 @@ class RedBlackTree: # The only way this happens to a node with one child # is if both children are None leaves. # We can just remove this node and call it a day. - if self.is_left(): - self.parent.left = None - else: - self.parent.right = None + if self.parent: + if self.is_left(): + self.parent.left = None + else: + self.parent.right = None else: # The node is black if child is None: @@ -188,7 +201,7 @@ class RedBlackTree: self.left.parent = self if self.right: self.right.parent = self - elif self.label > label: + elif self.label is not None and self.label > label: if self.left: self.left.remove(label) else: @@ -198,6 +211,13 @@ class RedBlackTree: def _remove_repair(self) -> None: """Repair the coloring of the tree that may have been messed up.""" + if ( + self.parent is None + or self.sibling is None + or self.parent.sibling is None + or self.grandparent is None + ): + return if color(self.sibling) == 1: self.sibling.color = 0 self.parent.color = 1 @@ -231,7 +251,8 @@ class RedBlackTree: ): self.sibling.rotate_right() self.sibling.color = 0 - self.sibling.right.color = 1 + if self.sibling.right: + self.sibling.right.color = 1 if ( self.is_right() and color(self.sibling) == 0 @@ -240,7 +261,8 @@ class RedBlackTree: ): self.sibling.rotate_left() self.sibling.color = 0 - self.sibling.left.color = 1 + if self.sibling.left: + self.sibling.left.color = 1 if ( self.is_left() and color(self.sibling) == 0 @@ -275,21 +297,17 @@ class RedBlackTree: """ # I assume property 1 to hold because there is nothing that can # make the color be anything other than 0 or 1. - # Property 2 if self.color: # The root was red print("Property 2") return False - # Property 3 does not need to be checked, because None is assumed # to be black and is all the leaves. - # Property 4 if not self.check_coloring(): print("Property 4") return False - # Property 5 if self.black_height() is None: print("Property 5") @@ -297,7 +315,7 @@ class RedBlackTree: # All properties were met return True - def check_coloring(self) -> None: + def check_coloring(self) -> bool: """A helper function to recursively check Property 4 of a Red-Black Tree. See check_color_properties for more info. """ @@ -310,12 +328,12 @@ class RedBlackTree: return False return True - def black_height(self) -> int: + def black_height(self) -> int | None: """Returns the number of black nodes from this node to the leaves of the tree, or None if there isn't one such value (the tree is color incorrectly). """ - if self is None: + if self is None or self.left is None or self.right is None: # If we're already at a leaf, there is no path return 1 left = RedBlackTree.black_height(self.left) @@ -332,21 +350,21 @@ class RedBlackTree: # Here are functions which are general to all binary search trees - def __contains__(self, label) -> bool: + def __contains__(self, label: int) -> bool: """Search through the tree for label, returning True iff it is found somewhere in the tree. Guaranteed to run in O(log(n)) time. """ return self.search(label) is not None - def search(self, label: int) -> RedBlackTree: + def search(self, label: int) -> RedBlackTree | None: """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. """ if self.label == label: return self - elif label > self.label: + elif self.label is not None and label > self.label: if self.right is None: return None else: @@ -357,12 +375,12 @@ class RedBlackTree: else: return self.left.search(label) - def floor(self, label: int) -> int: + def floor(self, label: int) -> int | None: """Returns the largest element in this tree which is at most label. This method is guaranteed to run in O(log(n)) time.""" if self.label == label: return self.label - elif self.label > label: + elif self.label is not None and self.label > label: if self.left: return self.left.floor(label) else: @@ -374,13 +392,13 @@ class RedBlackTree: return attempt return self.label - def ceil(self, label: int) -> int: + def ceil(self, label: int) -> int | None: """Returns the smallest element in this tree which is at least label. This method is guaranteed to run in O(log(n)) time. """ if self.label == label: return self.label - elif self.label < label: + elif self.label is not None and self.label < label: if self.right: return self.right.ceil(label) else: @@ -392,7 +410,7 @@ class RedBlackTree: return attempt return self.label - def get_max(self) -> int: + def get_max(self) -> int | None: """Returns the largest element in this tree. This method is guaranteed to run in O(log(n)) time. """ @@ -402,7 +420,7 @@ class RedBlackTree: else: return self.label - def get_min(self) -> int: + def get_min(self) -> int | None: """Returns the smallest element in this tree. This method is guaranteed to run in O(log(n)) time. """ @@ -413,7 +431,7 @@ class RedBlackTree: return self.label @property - def grandparent(self) -> RedBlackTree: + def grandparent(self) -> RedBlackTree | None: """Get the current node's grandparent, or None if it doesn't exist.""" if self.parent is None: return None @@ -421,7 +439,7 @@ class RedBlackTree: return self.parent.parent @property - def sibling(self) -> RedBlackTree: + def sibling(self) -> RedBlackTree | None: """Get the current node's sibling, or None if it doesn't exist.""" if self.parent is None: return None @@ -432,11 +450,15 @@ class RedBlackTree: def is_left(self) -> bool: """Returns true iff this node is the left child of its parent.""" - return self.parent and self.parent.left is self + if self.parent is None: + return False + return self.parent.left is self.parent.left is self def is_right(self) -> bool: """Returns true iff this node is the right child of its parent.""" - return self.parent and self.parent.right is self + if self.parent is None: + return False + return self.parent.right is self def __bool__(self) -> bool: return True @@ -452,21 +474,21 @@ class RedBlackTree: ln += len(self.right) return ln - def preorder_traverse(self) -> Iterator[int]: + def preorder_traverse(self) -> Iterator[int | None]: yield self.label if self.left: yield from self.left.preorder_traverse() if self.right: yield from self.right.preorder_traverse() - def inorder_traverse(self) -> Iterator[int]: + def inorder_traverse(self) -> Iterator[int | None]: if self.left: yield from self.left.inorder_traverse() yield self.label if self.right: yield from self.right.inorder_traverse() - def postorder_traverse(self) -> Iterator[int]: + def postorder_traverse(self) -> Iterator[int | None]: if self.left: yield from self.left.postorder_traverse() if self.right: @@ -488,15 +510,17 @@ class RedBlackTree: indent=1, ) - def __eq__(self, other) -> bool: + def __eq__(self, other: object) -> bool: """Test if two trees are equal.""" + if not isinstance(other, RedBlackTree): + return NotImplemented if self.label == other.label: return self.left == other.left and self.right == other.right else: return False -def color(node) -> int: +def color(node: RedBlackTree | None) -> int: """Returns the color of a node, allowing for None leaves.""" if node is None: return 0 @@ -699,19 +723,12 @@ def main() -> None: >>> pytests() """ print_results("Rotating right and left", test_rotations()) - print_results("Inserting", test_insert()) - print_results("Searching", test_insert_and_search()) - print_results("Deleting", test_insert_delete()) - print_results("Floor and ceil", test_floor_ceil()) - print_results("Tree traversal", test_tree_traversal()) - print_results("Tree traversal", test_tree_chaining()) - print("Testing tree balancing...") print("This should only be a few seconds.") test_insertion_speed() From 729aaf64275c61b8bc864ef9138eed078dea9cb2 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Thu, 4 Nov 2021 19:01:21 +0300 Subject: [PATCH 206/726] Improve Project Euler problem 014 solution 2 (#5744) * Improve solution * Uncomment code that has been commented due to slow execution affecting Travis * Fix * scikit-fuzzy is causing broken builds * fuzz = None * Update fuzzy_operations.py Co-authored-by: Christian Clauss --- fuzzy_logic/fuzzy_operations.py | 9 +++++++-- project_euler/problem_014/sol2.py | 22 ++++++++++++---------- requirements.txt | 2 +- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/fuzzy_logic/fuzzy_operations.py b/fuzzy_logic/fuzzy_operations.py index 0f573f158..fbaca9421 100644 --- a/fuzzy_logic/fuzzy_operations.py +++ b/fuzzy_logic/fuzzy_operations.py @@ -1,4 +1,5 @@ -"""README, Author - Jigyasa Gandhi(mailto:jigsgandhi97@gmail.com) +""" +README, Author - Jigyasa Gandhi(mailto:jigsgandhi97@gmail.com) Requirements: - scikit-fuzzy - numpy @@ -7,7 +8,11 @@ Python: - 3.5 """ import numpy as np -import skfuzzy as fuzz + +try: + import skfuzzy as fuzz +except ImportError: + fuzz = None if __name__ == "__main__": # Create universe of discourse in Python using linspace () diff --git a/project_euler/problem_014/sol2.py b/project_euler/problem_014/sol2.py index 0a58f8d9a..d2a1d9f0e 100644 --- a/project_euler/problem_014/sol2.py +++ b/project_euler/problem_014/sol2.py @@ -27,25 +27,27 @@ Which starting number, under one million, produces the longest chain? """ from __future__ import annotations +COLLATZ_SEQUENCE_LENGTHS = {1: 1} + def collatz_sequence_length(n: int) -> int: """Returns the Collatz sequence length for n.""" - sequence_length = 1 - while n != 1: - if n % 2 == 0: - n //= 2 - else: - n = 3 * n + 1 - sequence_length += 1 + if n in COLLATZ_SEQUENCE_LENGTHS: + return COLLATZ_SEQUENCE_LENGTHS[n] + if n % 2 == 0: + next_n = n // 2 + else: + next_n = 3 * n + 1 + sequence_length = collatz_sequence_length(next_n) + 1 + COLLATZ_SEQUENCE_LENGTHS[n] = sequence_length return sequence_length def solution(n: int = 1000000) -> int: """Returns the number under n that generates the longest Collatz sequence. - # The code below has been commented due to slow execution affecting Travis. - # >>> solution(1000000) - # 837799 + >>> solution(1000000) + 837799 >>> solution(200) 171 >>> solution(5000) diff --git a/requirements.txt b/requirements.txt index ef4e18043..e01d87cff 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,7 +9,7 @@ pandas pillow qiskit requests -scikit-fuzzy +# scikit-fuzzy # Causing broken builds sklearn statsmodels sympy From 7390777f9aa4d60fcd87dc02b7628e61f92edc12 Mon Sep 17 00:00:00 2001 From: Snimerjot Singh Date: Thu, 4 Nov 2021 21:38:18 +0530 Subject: [PATCH 207/726] Added 2 shaped in volume.py (#5560) --- maths/volume.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/maths/volume.py b/maths/volume.py index fd24aa9ee..b11995bab 100644 --- a/maths/volume.py +++ b/maths/volume.py @@ -153,6 +153,21 @@ def vol_sphere(radius: float) -> float: return 4 / 3 * pi * pow(radius, 3) +def vol_hemisphere(radius: float): + """Calculate the volume of a hemisphere + Wikipedia reference: https://en.wikipedia.org/wiki/Hemisphere + Other references: https://www.cuemath.com/geometry/hemisphere + :return 2/3 * pi * radius^3 + + >>> vol_hemisphere(1) + 2.0943951023931953 + + >>> vol_hemisphere(7) + 718.3775201208659 + """ + return 2 / 3 * pi * pow(radius, 3) + + def vol_circular_cylinder(radius: float, height: float) -> float: """Calculate the Volume of a Circular Cylinder. Wikipedia reference: https://en.wikipedia.org/wiki/Cylinder @@ -166,6 +181,26 @@ def vol_circular_cylinder(radius: float, height: float) -> float: return pi * pow(radius, 2) * height +def vol_conical_frustum(height: float, radius_1: float, radius_2: float): + """Calculate the Volume of a Conical Frustum. + Wikipedia reference: https://en.wikipedia.org/wiki/Frustum + :return 1/3 * pi * height * (radius_1^2 + radius_top^2 + radius_1 * radius_2) + + >>> vol_conical_frustum(45, 7, 28) + 48490.482608158454 + + >>> vol_conical_frustum(1, 1, 2) + 7.330382858376184 + """ + return ( + 1 + / 3 + * pi + * height + * (pow(radius_1, 2) + pow(radius_2, 2) + radius_1 * radius_2) + ) + + def main(): """Print the Results of Various Volume Calculations.""" print("Volumes:") @@ -176,7 +211,9 @@ def main(): print("Prism: " + str(vol_prism(2, 2))) # = 4 print("Pyramid: " + str(vol_pyramid(2, 2))) # ~= 1.33 print("Sphere: " + str(vol_sphere(2))) # ~= 33.5 + print("Hemisphere: " + str(vol_hemisphere(2))) # ~= 16.75 print("Circular Cylinder: " + str(vol_circular_cylinder(2, 2))) # ~= 25.1 + print("Conical Frustum: " + str(vol_conical_frustum(2, 2, 4))) # ~= 58.6 print("Spherical cap: " + str(vol_spherical_cap(1, 2))) # ~= 5.24 print("Spheres intersetion: " + str(vol_spheres_intersect(2, 2, 1))) # ~= 21.21 From dbddac74d3dbc0dc7c3d710ac3b42839685160a6 Mon Sep 17 00:00:00 2001 From: Boris Galochkin Date: Thu, 4 Nov 2021 19:51:31 +0300 Subject: [PATCH 208/726] Fix `graphs/finding_bridges.py` algorithm + doctests (#5765) * Fix finding_bridges algorithms + tests * update type hints * Better, more obvious condition fix * fix prev commit + more tests * Short explanation + url * Update finding_bridges.py Co-authored-by: Christian Clauss --- graphs/finding_bridges.py | 98 +++++++++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 20 deletions(-) diff --git a/graphs/finding_bridges.py b/graphs/finding_bridges.py index 6555dd7bc..a877a9748 100644 --- a/graphs/finding_bridges.py +++ b/graphs/finding_bridges.py @@ -1,5 +1,77 @@ -# Finding Bridges in Undirected Graph -def computeBridges(graph): +""" +An edge is a bridge if, after removing it count of connected components in graph will +be increased by one. Bridges represent vulnerabilities in a connected network and are +useful for designing reliable networks. For example, in a wired computer network, an +articulation point indicates the critical computers and a bridge indicates the critical +wires or connections. + +For more details, refer this article: +https://www.geeksforgeeks.org/bridge-in-a-graph/ +""" + + +def __get_demo_graph(index): + return [ + { + 0: [1, 2], + 1: [0, 2], + 2: [0, 1, 3, 5], + 3: [2, 4], + 4: [3], + 5: [2, 6, 8], + 6: [5, 7], + 7: [6, 8], + 8: [5, 7], + }, + { + 0: [6], + 1: [9], + 2: [4, 5], + 3: [4], + 4: [2, 3], + 5: [2], + 6: [0, 7], + 7: [6], + 8: [], + 9: [1], + }, + { + 0: [4], + 1: [6], + 2: [], + 3: [5, 6, 7], + 4: [0, 6], + 5: [3, 8, 9], + 6: [1, 3, 4, 7], + 7: [3, 6, 8, 9], + 8: [5, 7], + 9: [5, 7], + }, + { + 0: [1, 3], + 1: [0, 2, 4], + 2: [1, 3, 4], + 3: [0, 2, 4], + 4: [1, 2, 3], + }, + ][index] + + +def compute_bridges(graph: dict[int, list[int]]) -> list[tuple[int, int]]: + """ + Return the list of undirected graph bridges [(a1, b1), ..., (ak, bk)]; ai <= bi + >>> compute_bridges(__get_demo_graph(0)) + [(3, 4), (2, 3), (2, 5)] + >>> compute_bridges(__get_demo_graph(1)) + [(6, 7), (0, 6), (1, 9), (3, 4), (2, 4), (2, 5)] + >>> compute_bridges(__get_demo_graph(2)) + [(1, 6), (4, 6), (0, 4)] + >>> compute_bridges(__get_demo_graph(3)) + [] + >>> compute_bridges({}) + [] + """ + id = 0 n = len(graph) # No of vertices in graph low = [0] * n @@ -15,28 +87,14 @@ def computeBridges(graph): elif not visited[to]: dfs(to, at, bridges, id) low[at] = min(low[at], low[to]) - if at < low[to]: - bridges.append([at, to]) + if id <= low[to]: + bridges.append((at, to) if at < to else (to, at)) else: # This edge is a back edge and cannot be a bridge - low[at] = min(low[at], to) + low[at] = min(low[at], low[to]) bridges = [] for i in range(n): if not visited[i]: dfs(i, -1, bridges, id) - print(bridges) - - -graph = { - 0: [1, 2], - 1: [0, 2], - 2: [0, 1, 3, 5], - 3: [2, 4], - 4: [3], - 5: [2, 6, 8], - 6: [5, 7], - 7: [6, 8], - 8: [5, 7], -} -computeBridges(graph) + return bridges From 6b2b476f8633504e4c032dc948ab7dda04cd3d3f Mon Sep 17 00:00:00 2001 From: Leoriem-code <73761711+Leoriem-code@users.noreply.github.com> Date: Fri, 5 Nov 2021 06:06:37 +0100 Subject: [PATCH 209/726] fix typo on line 126 (#5768) --- scheduling/shortest_job_first.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scheduling/shortest_job_first.py b/scheduling/shortest_job_first.py index 17409108a..9372e9dbc 100644 --- a/scheduling/shortest_job_first.py +++ b/scheduling/shortest_job_first.py @@ -123,7 +123,7 @@ if __name__ == "__main__": processes = list(range(1, no_of_processes + 1)) for i in range(no_of_processes): - print("Enter the arrival time and brust time for process:--" + str(i + 1)) + print("Enter the arrival time and burst time for process:--" + str(i + 1)) arrival_time[i], burst_time[i] = map(int, input().split()) waiting_time = calculate_waitingtime(arrival_time, burst_time, no_of_processes) From 48960268a2629fe0549ce7a67619852be91baa5f Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj Date: Sat, 6 Nov 2021 01:13:52 +0530 Subject: [PATCH 210/726] Improve Project Euler Problem 10 Sol-1 (#5773) * Improve Project Euler Problem 10 Sol-1 * Name correction * psf/black formatting * More formatting --- project_euler/problem_010/sol1.py | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/project_euler/problem_010/sol1.py b/project_euler/problem_010/sol1.py index bd49b3523..e060761ee 100644 --- a/project_euler/problem_010/sol1.py +++ b/project_euler/problem_010/sol1.py @@ -28,11 +28,11 @@ def is_prime(n: int) -> bool: True """ - for i in range(2, int(sqrt(n)) + 1): - if n % i == 0: - return False - - return True + if 1 < n < 4: + return True + elif n < 2 or not n % 2: + return False + return not any(not n % i for i in range(3, int(sqrt(n) + 1), 2)) def solution(n: int = 2000000) -> int: @@ -49,16 +49,7 @@ def solution(n: int = 2000000) -> int: 10 """ - if n > 2: - sum_of_primes = 2 - else: - return 0 - - for i in range(3, n, 2): - if is_prime(i): - sum_of_primes += i - - return sum_of_primes + return sum(num for num in range(3, n, 2) if is_prime(num)) + 2 if n > 2 else 0 if __name__ == "__main__": From 1a43c92c77790632e7958df9c1048ed77aa36f68 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Fri, 5 Nov 2021 22:44:24 +0300 Subject: [PATCH 211/726] Improve Project Euler problem 043 solution 1 (#5772) * updating DIRECTORY.md * Fix typo * Improve solution Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 3 +++ project_euler/problem_043/sol1.py | 21 ++++++++++++++------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index fd164c92e..32ca8cd3b 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -253,6 +253,7 @@ ## Dynamic Programming * [Abbreviation](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/abbreviation.py) + * [All Construct](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/all_construct.py) * [Bitmask](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/bitmask.py) * [Catalan Numbers](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/catalan_numbers.py) * [Climbing Stairs](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/climbing_stairs.py) @@ -612,6 +613,7 @@ ## Physics * [N Body Simulation](https://github.com/TheAlgorithms/Python/blob/master/physics/n_body_simulation.py) + * [Newtons Second Law Of Motion](https://github.com/TheAlgorithms/Python/blob/master/physics/newtons_second_law_of_motion.py) ## Project Euler * Problem 001 @@ -1018,6 +1020,7 @@ * [Nasa Data](https://github.com/TheAlgorithms/Python/blob/master/web_programming/nasa_data.py) * [Random Anime Character](https://github.com/TheAlgorithms/Python/blob/master/web_programming/random_anime_character.py) * [Recaptcha Verification](https://github.com/TheAlgorithms/Python/blob/master/web_programming/recaptcha_verification.py) + * [Reddit](https://github.com/TheAlgorithms/Python/blob/master/web_programming/reddit.py) * [Search Books By Isbn](https://github.com/TheAlgorithms/Python/blob/master/web_programming/search_books_by_isbn.py) * [Slack Message](https://github.com/TheAlgorithms/Python/blob/master/web_programming/slack_message.py) * [Test Fetch Github Info](https://github.com/TheAlgorithms/Python/blob/master/web_programming/test_fetch_github_info.py) diff --git a/project_euler/problem_043/sol1.py b/project_euler/problem_043/sol1.py index 1febe4a4d..c533f40da 100644 --- a/project_euler/problem_043/sol1.py +++ b/project_euler/problem_043/sol1.py @@ -33,9 +33,18 @@ def is_substring_divisible(num: tuple) -> bool: >>> is_substring_divisible((1, 4, 0, 6, 3, 5, 7, 2, 8, 9)) True """ - tests = [2, 3, 5, 7, 11, 13, 17] + if num[3] % 2 != 0: + return False + + if (num[2] + num[3] + num[4]) % 3 != 0: + return False + + if num[5] % 5 != 0: + return False + + tests = [7, 11, 13, 17] for i, test in enumerate(tests): - if (num[i + 1] * 100 + num[i + 2] * 10 + num[i + 3]) % test != 0: + if (num[i + 4] * 100 + num[i + 5] * 10 + num[i + 6]) % test != 0: return False return True @@ -43,17 +52,15 @@ def is_substring_divisible(num: tuple) -> bool: def solution(n: int = 10) -> int: """ Returns the sum of all pandigital numbers which pass the - divisiility tests. + divisibility tests. >>> solution(10) 16695334890 """ - list_nums = [ + return sum( int("".join(map(str, num))) for num in permutations(range(n)) if is_substring_divisible(num) - ] - - return sum(list_nums) + ) if __name__ == "__main__": From e7381b513b526e2f3ca134022389832778bdf080 Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Fri, 5 Nov 2021 16:45:37 -0300 Subject: [PATCH 212/726] [mypy] Fix type annotations in `data_structures/stacks/next_greater_element.py` (#5763) * Fix type annotations in next_greater_element.py * Refactor next_greater_element.py --- .../stacks/next_greater_element.py | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/data_structures/stacks/next_greater_element.py b/data_structures/stacks/next_greater_element.py index d8c7ed173..5bab7c609 100644 --- a/data_structures/stacks/next_greater_element.py +++ b/data_structures/stacks/next_greater_element.py @@ -1,8 +1,10 @@ +from __future__ import annotations + arr = [-10, -5, 0, 5, 5.1, 11, 13, 21, 3, 4, -21, -10, -5, -1, 0] expect = [-5, 0, 5, 5.1, 11, 13, 21, -1, 4, -1, -10, -5, -1, 0, -1] -def next_greatest_element_slow(arr: list) -> list: +def next_greatest_element_slow(arr: list[float]) -> list[float]: """ Get the Next Greatest Element (NGE) for all elements in a list. Maximum element present after the current one which is also greater than the @@ -10,10 +12,13 @@ def next_greatest_element_slow(arr: list) -> list: >>> next_greatest_element_slow(arr) == expect True """ + result = [] - for i in range(0, len(arr), 1): - next = -1 - for j in range(i + 1, len(arr), 1): + arr_size = len(arr) + + for i in range(arr_size): + next: float = -1 + for j in range(i + 1, arr_size): if arr[i] < arr[j]: next = arr[j] break @@ -21,7 +26,7 @@ def next_greatest_element_slow(arr: list) -> list: return result -def next_greatest_element_fast(arr: list) -> list: +def next_greatest_element_fast(arr: list[float]) -> list[float]: """ Like next_greatest_element_slow() but changes the loops to use enumerate() instead of range(len()) for the outer loop and @@ -31,7 +36,7 @@ def next_greatest_element_fast(arr: list) -> list: """ result = [] for i, outer in enumerate(arr): - next = -1 + next: float = -1 for inner in arr[i + 1 :]: if outer < inner: next = inner @@ -40,7 +45,7 @@ def next_greatest_element_fast(arr: list) -> list: return result -def next_greatest_element(arr: list) -> list: +def next_greatest_element(arr: list[float]) -> list[float]: """ Get the Next Greatest Element (NGE) for all elements in a list. Maximum element present after the current one which is also greater than the @@ -53,21 +58,19 @@ def next_greatest_element(arr: list) -> list: >>> next_greatest_element(arr) == expect True """ - stack = [] - result = [-1] * len(arr) + arr_size = len(arr) + stack: list[float] = [] + result: list[float] = [-1] * arr_size - for index in reversed(range(len(arr))): - if len(stack): + for index in reversed(range(arr_size)): + if stack: while stack[-1] <= arr[index]: stack.pop() - if len(stack) == 0: + if not stack: break - - if len(stack) != 0: + if stack: result[index] = stack[-1] - stack.append(arr[index]) - return result From 8ac86f2ce559e323064b09a54267d35cf3c51ec6 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 6 Nov 2021 13:58:15 +0100 Subject: [PATCH 213/726] mypy: Exclude only 20 files that are still failing (#5608) * DRAFT: Run a mypy reality check Let's see what is required to finish #4052 * mypy --ignore-missing-imports --install-types --non-interactive * Check our progress... * Update build.yml * Update build.yml * Update build.yml * Update build.yml * mypy --exclude 20 files * --exclude with no `=` * Update build.yml * 558 character regex!!! * With quotes * mypy.ini: mega exclude * Update mypy.ini * Update build.yml * Update mypy.ini * Update build.yml * Update mypy.ini * .py --> .p* * Escape the dots!: `.` --> `\.` * Remove the comment * Leading slash * Update mypy.ini Co-authored-by: Dylan Buchi Co-authored-by: Dylan Buchi --- .github/workflows/build.yml | 2 +- mypy.ini | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f710e1e0e..e5f8d6b39 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,7 +21,7 @@ jobs: run: | python -m pip install --upgrade pip setuptools six wheel python -m pip install mypy pytest-cov -r requirements.txt - - run: mypy --install-types --non-interactive . + - run: mypy . # See `mypy.ini` for configuration settings. - name: Run tests run: pytest --doctest-modules --ignore=project_euler/ --ignore=scripts/validate_solutions.py --cov-report=term-missing:skip-covered --cov=. . - if: ${{ success() }} diff --git a/mypy.ini b/mypy.ini index ba552f878..1a2282c44 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,5 +1,6 @@ [mypy] ignore_missing_imports = True +install_types = True +non_interactive = True +exclude = (data_structures/stacks/next_greater_element.py|graphs/boruvka.py|graphs/breadth_first_search.py|graphs/breadth_first_search_2.py|graphs/check_cycle.py|graphs/finding_bridges.py|graphs/greedy_min_vertex_cover.py|graphs/random_graph_generator.py|maths/average_mode.py|maths/gamma_recursive.py|maths/proth_number.py|maths/series/geometric_series.py|maths/series/p_series.py|matrix_operation.py|other/fischer_yates_shuffle.py|other/least_recently_used.py|other/lfu_cache.py|other/lru_cache.py|searches/simulated_annealing.py|searches/ternary_search.py) -; FIXME: #4052 fix mypy errors in the exclude directories and remove them below -exclude = (data_structures|graphs|maths|matrix|other|searches)/$ From accee50cde961af501bd0c6f424cd07dc5d63269 Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj Date: Sun, 7 Nov 2021 15:44:42 +0530 Subject: [PATCH 214/726] [mypy] Fix `other/fischer_yates_shuffle.py` (#5789) * [mypy] Fix `other/fischer_yates_shuffle.py` * Update mypy.ini --- mypy.ini | 2 +- other/fischer_yates_shuffle.py | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/mypy.ini b/mypy.ini index 1a2282c44..123ffae85 100644 --- a/mypy.ini +++ b/mypy.ini @@ -2,5 +2,5 @@ ignore_missing_imports = True install_types = True non_interactive = True -exclude = (data_structures/stacks/next_greater_element.py|graphs/boruvka.py|graphs/breadth_first_search.py|graphs/breadth_first_search_2.py|graphs/check_cycle.py|graphs/finding_bridges.py|graphs/greedy_min_vertex_cover.py|graphs/random_graph_generator.py|maths/average_mode.py|maths/gamma_recursive.py|maths/proth_number.py|maths/series/geometric_series.py|maths/series/p_series.py|matrix_operation.py|other/fischer_yates_shuffle.py|other/least_recently_used.py|other/lfu_cache.py|other/lru_cache.py|searches/simulated_annealing.py|searches/ternary_search.py) +exclude = (data_structures/stacks/next_greater_element.py|graphs/boruvka.py|graphs/breadth_first_search.py|graphs/breadth_first_search_2.py|graphs/check_cycle.py|graphs/finding_bridges.py|graphs/greedy_min_vertex_cover.py|graphs/random_graph_generator.py|maths/average_mode.py|maths/gamma_recursive.py|maths/proth_number.py|maths/series/geometric_series.py|maths/series/p_series.py|matrix_operation.py|other/least_recently_used.py|other/lfu_cache.py|other/lru_cache.py|searches/simulated_annealing.py|searches/ternary_search.py) diff --git a/other/fischer_yates_shuffle.py b/other/fischer_yates_shuffle.py index 035fcb482..fa2f4dce9 100644 --- a/other/fischer_yates_shuffle.py +++ b/other/fischer_yates_shuffle.py @@ -6,14 +6,15 @@ For more details visit wikipedia/Fischer-Yates-Shuffle. """ import random +from typing import Any -def fisher_yates_shuffle(data: list) -> list: - for _ in range(len(list)): - a = random.randint(0, len(list) - 1) - b = random.randint(0, len(list) - 1) - list[a], list[b] = list[b], list[a] - return list +def fisher_yates_shuffle(data: list) -> list[Any]: + for _ in range(len(data)): + a = random.randint(0, len(data) - 1) + b = random.randint(0, len(data) - 1) + data[a], data[b] = data[b], data[a] + return data if __name__ == "__main__": From db5aa1d18890439e4108fa416679dbab5859f30c Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj Date: Sun, 7 Nov 2021 20:10:23 +0530 Subject: [PATCH 215/726] Add equated_monthly_installments.py in Financials (#5775) * Add equated_monthly_installments.py in Financials * Formatting * More formatting, Descriptive names * Errors with name change * Formatting * Formatting, Naming Error * dedent * Update DIRECTORY.md --- DIRECTORY.md | 1 + financial/equated_monthly_installments.py | 61 +++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 financial/equated_monthly_installments.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 32ca8cd3b..f515277f4 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -298,6 +298,7 @@ ## Financial * [Interest](https://github.com/TheAlgorithms/Python/blob/master/financial/interest.py) + * [EMI Calculation](https://github.com/TheAlgorithms/Python/blob/master/financial/equated_monthly_installments.py) ## Fractals * [Julia Sets](https://github.com/TheAlgorithms/Python/blob/master/fractals/julia_sets.py) diff --git a/financial/equated_monthly_installments.py b/financial/equated_monthly_installments.py new file mode 100644 index 000000000..3af922493 --- /dev/null +++ b/financial/equated_monthly_installments.py @@ -0,0 +1,61 @@ +""" +Program to calculate the amortization amount per month, given +- Principal borrowed +- Rate of interest per annum +- Years to repay the loan + +Wikipedia Reference: https://en.wikipedia.org/wiki/Equated_monthly_installment +""" + + +def equated_monthly_installments( + principal: float, rate_per_annum: float, years_to_repay: int +) -> float: + """ + Formula for amortization amount per month: + A = p * r * (1 + r)^n / ((1 + r)^n - 1) + where p is the principal, r is the rate of interest per month + and n is the number of payments + + >>> equated_monthly_installments(25000, 0.12, 3) + 830.3577453212793 + >>> equated_monthly_installments(25000, 0.12, 10) + 358.67737100646826 + >>> equated_monthly_installments(0, 0.12, 3) + Traceback (most recent call last): + ... + Exception: Principal borrowed must be > 0 + >>> equated_monthly_installments(25000, -1, 3) + Traceback (most recent call last): + ... + Exception: Rate of interest must be >= 0 + >>> equated_monthly_installments(25000, 0.12, 0) + Traceback (most recent call last): + ... + Exception: Years to repay must be an integer > 0 + """ + if principal <= 0: + raise Exception("Principal borrowed must be > 0") + if rate_per_annum < 0: + raise Exception("Rate of interest must be >= 0") + if years_to_repay <= 0 or not isinstance(years_to_repay, int): + raise Exception("Years to repay must be an integer > 0") + + # Yearly rate is divided by 12 to get monthly rate + rate_per_month = rate_per_annum / 12 + + # Years to repay is multiplied by 12 to get number of payments as payment is monthly + number_of_payments = years_to_repay * 12 + + return ( + principal + * rate_per_month + * (1 + rate_per_month) ** number_of_payments + / ((1 + rate_per_month) ** number_of_payments - 1) + ) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From a98465230f21e6ece76332eeca1558613788c387 Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj Date: Sun, 7 Nov 2021 20:43:58 +0530 Subject: [PATCH 216/726] [mypy] Fix type annotations for maths directory (#5782) * [mypy] Fix annotations in `maths/series/p_series.py` * Update p_series.py * Update p_series.py * Remove from excluded in mypy.ini * Type annotation for series * Annotate maths/proth_number.py (properly) * Remove from excluded in mypy.ini * Annotate average_mode.py * Update average_mode.py * Update average_mode.py * Update average_mode.py * Update average_mode.py * Remove from excluded in mypy.ini * Fix annotations in gamma_recursive.py * Remove from excluded in mypy.ini * Annotations for geometric_series.py * Update geometric_series.py * Update mypy.ini * Update average_mode.py * Update average_mode.py * Update average_mode.py * Update mypy.ini * Update mypy.ini * Update mypy.ini * Update average_mode.py * Update proth_number.py * Update average_mode.py * Update gamma_recursive.py * Update proth_number.py * Update mypy.ini * Update geometric_series.py * Update average_mode.py * Update proth_number.py * Update geometric_series.py * Update geometric_series.py * Update geometric_series.py * Update p_series.py * Update geometric_series.py * Update p_series.py * Update p_series.py * Update geometric_series.py * Update p_series.py * Update p_series.py * Remove data_structures/stacks/next_greater_element.py| Co-authored-by: Christian Clauss --- maths/average_mode.py | 31 ++++++++++------------ maths/gamma_recursive.py | 3 +-- maths/proth_number.py | 14 ++++------ maths/series/geometric_series.py | 44 ++++++++++++++++++++------------ maths/series/p_series.py | 32 +++++++++++++---------- mypy.ini | 3 +-- 6 files changed, 66 insertions(+), 61 deletions(-) diff --git a/maths/average_mode.py b/maths/average_mode.py index 83db82007..40f88f41f 100644 --- a/maths/average_mode.py +++ b/maths/average_mode.py @@ -1,34 +1,29 @@ -def mode(input_list: list) -> list: # Defining function "mode." +from typing import Any + + +def mode(input_list: list) -> list[Any]: """This function returns the mode(Mode as in the measures of central tendency) of the input data. The input list may contain any Datastructure or any Datatype. - >>> input_list = [2, 3, 4, 5, 3, 4, 2, 5, 2, 2, 4, 2, 2, 2] - >>> mode(input_list) + >>> mode([2, 3, 4, 5, 3, 4, 2, 5, 2, 2, 4, 2, 2, 2]) [2] - >>> input_list = [3, 4, 5, 3, 4, 2, 5, 2, 2, 4, 4, 2, 2, 2] - >>> mode(input_list) + >>> mode([3, 4, 5, 3, 4, 2, 5, 2, 2, 4, 4, 2, 2, 2]) [2] - >>> input_list = [3, 4, 5, 3, 4, 2, 5, 2, 2, 4, 4, 4, 2, 2, 4, 2] - >>> mode(input_list) + >>> mode([3, 4, 5, 3, 4, 2, 5, 2, 2, 4, 4, 4, 2, 2, 4, 2]) [2, 4] - >>> input_list = ["x", "y", "y", "z"] - >>> mode(input_list) + >>> mode(["x", "y", "y", "z"]) ['y'] - >>> input_list = ["x", "x" , "y", "y", "z"] - >>> mode(input_list) + >>> mode(["x", "x" , "y", "y", "z"]) ['x', 'y'] """ - result = list() # Empty list to store the counts of elements in input_list - for x in input_list: - result.append(input_list.count(x)) - if not result: + if not input_list: return [] - y = max(result) # Gets the maximum value in the result list. + result = [input_list.count(value) for value in input_list] + y = max(result) # Gets the maximum count in the input list. # Gets values of modes - result = {input_list[i] for i, value in enumerate(result) if value == y} - return sorted(result) + return sorted({input_list[i] for i, value in enumerate(result) if value == y}) if __name__ == "__main__": diff --git a/maths/gamma_recursive.py b/maths/gamma_recursive.py index 683d7adb1..3d6b8c5e8 100644 --- a/maths/gamma_recursive.py +++ b/maths/gamma_recursive.py @@ -2,7 +2,6 @@ Gamma function is a very useful tool in math and physics. It helps calculating complex integral in a convenient way. for more info: https://en.wikipedia.org/wiki/Gamma_function - Python's Standard Library math.gamma() function overflows around gamma(171.624). """ from math import pi, sqrt @@ -71,7 +70,7 @@ if __name__ == "__main__": from doctest import testmod testmod() - num = 1 + num = 1.0 while num: num = float(input("Gamma of: ")) print(f"gamma({num}) = {gamma(num)}") diff --git a/maths/proth_number.py b/maths/proth_number.py index 065244ed7..e17503143 100644 --- a/maths/proth_number.py +++ b/maths/proth_number.py @@ -1,6 +1,5 @@ """ Calculate the nth Proth number - Source: https://handwiki.org/wiki/Proth_number """ @@ -12,22 +11,17 @@ def proth(number: int) -> int: """ :param number: nth number to calculate in the sequence :return: the nth number in Proth number - Note: indexing starts at 1 i.e. proth(1) gives the first Proth number of 3 - >>> proth(6) 25 - >>> proth(0) Traceback (most recent call last): ... ValueError: Input value of [number=0] must be > 0 - >>> proth(-1) Traceback (most recent call last): ... ValueError: Input value of [number=-1] must be > 0 - >>> proth(6.0) Traceback (most recent call last): ... @@ -44,14 +38,12 @@ def proth(number: int) -> int: elif number == 2: return 5 else: - block_index = number // 3 """ +1 for binary starting at 0 i.e. 2^0, 2^1, etc. +1 to start the sequence at the 3rd Proth number Hence, we have a +2 in the below statement """ - block_index = math.log(block_index, 2) + 2 - block_index = int(block_index) + block_index = int(math.log(number // 3, 2)) + 2 proth_list = [3, 5] proth_index = 2 @@ -66,6 +58,10 @@ def proth(number: int) -> int: if __name__ == "__main__": + import doctest + + doctest.testmod() + for number in range(11): value = 0 try: diff --git a/maths/series/geometric_series.py b/maths/series/geometric_series.py index d12382e6d..a875ab89a 100644 --- a/maths/series/geometric_series.py +++ b/maths/series/geometric_series.py @@ -1,7 +1,6 @@ """ This is a pure Python implementation of the Geometric Series algorithm https://en.wikipedia.org/wiki/Geometric_series - Run the doctests with the following command: python3 -m doctest -v geometric_series.py or @@ -11,8 +10,17 @@ python3 geometric_series.py """ -def geometric_series(nth_term: int, start_term_a: int, common_ratio_r: int) -> list: - """Pure Python implementation of Geometric Series algorithm +from __future__ import annotations + + +def geometric_series( + nth_term: float | int, + start_term_a: float | int, + common_ratio_r: float | int, +) -> list[float | int]: + """ + Pure Python implementation of Geometric Series algorithm + :param nth_term: The last term (nth term of Geometric Series) :param start_term_a : The first term of Geometric Series :param common_ratio_r : The common ratio between all the terms @@ -20,15 +28,15 @@ def geometric_series(nth_term: int, start_term_a: int, common_ratio_r: int) -> l ration with first term with increase in power till last term (nth term) Examples: >>> geometric_series(4, 2, 2) - [2, '4.0', '8.0', '16.0'] + [2, 4.0, 8.0, 16.0] >>> geometric_series(4.0, 2.0, 2.0) - [2.0, '4.0', '8.0', '16.0'] + [2.0, 4.0, 8.0, 16.0] >>> geometric_series(4.1, 2.1, 2.1) - [2.1, '4.41', '9.261000000000001', '19.448100000000004'] + [2.1, 4.41, 9.261000000000001, 19.448100000000004] >>> geometric_series(4, 2, -2) - [2, '-4.0', '8.0', '-16.0'] + [2, -4.0, 8.0, -16.0] >>> geometric_series(4, -2, 2) - [-2, '-4.0', '-8.0', '-16.0'] + [-2, -4.0, -8.0, -16.0] >>> geometric_series(-4, 2, 2) [] >>> geometric_series(0, 100, 500) @@ -38,9 +46,9 @@ def geometric_series(nth_term: int, start_term_a: int, common_ratio_r: int) -> l >>> geometric_series(0, 0, 0) [] """ - if "" in (nth_term, start_term_a, common_ratio_r): - return "" - series = [] + if not all((nth_term, start_term_a, common_ratio_r)): + return [] + series: list[float | int] = [] power = 1 multiple = common_ratio_r for _ in range(int(nth_term)): @@ -48,16 +56,20 @@ def geometric_series(nth_term: int, start_term_a: int, common_ratio_r: int) -> l series.append(start_term_a) else: power += 1 - series.append(str(float(start_term_a) * float(multiple))) + series.append(float(start_term_a * multiple)) multiple = pow(float(common_ratio_r), power) return series if __name__ == "__main__": - nth_term = input("Enter the last number (n term) of the Geometric Series") - start_term_a = input("Enter the starting term (a) of the Geometric Series") - common_ratio_r = input( - "Enter the common ratio between two terms (r) of the Geometric Series" + import doctest + + doctest.testmod() + + nth_term = float(input("Enter the last number (n term) of the Geometric Series")) + start_term_a = float(input("Enter the starting term (a) of the Geometric Series")) + common_ratio_r = float( + input("Enter the common ratio between two terms (r) of the Geometric Series") ) print("Formula of Geometric Series => a + ar + ar^2 ... +ar^n") print(geometric_series(nth_term, start_term_a, common_ratio_r)) diff --git a/maths/series/p_series.py b/maths/series/p_series.py index 04019aed5..34fa3f239 100644 --- a/maths/series/p_series.py +++ b/maths/series/p_series.py @@ -1,48 +1,52 @@ """ This is a pure Python implementation of the P-Series algorithm https://en.wikipedia.org/wiki/Harmonic_series_(mathematics)#P-series - For doctests run following command: python -m doctest -v p_series.py or python3 -m doctest -v p_series.py - For manual testing run: python3 p_series.py """ -def p_series(nth_term: int, power: int) -> list: - """Pure Python implementation of P-Series algorithm +from __future__ import annotations + +def p_series(nth_term: int | float | str, power: int | float | str) -> list[str]: + """ + Pure Python implementation of P-Series algorithm :return: The P-Series starting from 1 to last (nth) term - Examples: >>> p_series(5, 2) - [1, '1/4', '1/9', '1/16', '1/25'] + ['1', '1 / 4', '1 / 9', '1 / 16', '1 / 25'] >>> p_series(-5, 2) [] >>> p_series(5, -2) - [1, '1/0.25', '1/0.1111111111111111', '1/0.0625', '1/0.04'] + ['1', '1 / 0.25', '1 / 0.1111111111111111', '1 / 0.0625', '1 / 0.04'] >>> p_series("", 1000) - '' + [''] >>> p_series(0, 0) [] >>> p_series(1, 1) - [1] + ['1'] """ if nth_term == "": - return nth_term + return [""] nth_term = int(nth_term) power = int(power) - series = [] + series: list[str] = [] for temp in range(int(nth_term)): - series.append(f"1/{pow(temp + 1, int(power))}" if series else 1) + series.append(f"1 / {pow(temp + 1, int(power))}" if series else "1") return series if __name__ == "__main__": - nth_term = input("Enter the last number (nth term) of the P-Series") - power = input("Enter the power for P-Series") + import doctest + + doctest.testmod() + + nth_term = int(input("Enter the last number (nth term) of the P-Series")) + power = int(input("Enter the power for P-Series")) print("Formula of P-Series => 1+1/2^p+1/3^p ..... 1/n^p") print(p_series(nth_term, power)) diff --git a/mypy.ini b/mypy.ini index 123ffae85..df69fa841 100644 --- a/mypy.ini +++ b/mypy.ini @@ -2,5 +2,4 @@ ignore_missing_imports = True install_types = True non_interactive = True -exclude = (data_structures/stacks/next_greater_element.py|graphs/boruvka.py|graphs/breadth_first_search.py|graphs/breadth_first_search_2.py|graphs/check_cycle.py|graphs/finding_bridges.py|graphs/greedy_min_vertex_cover.py|graphs/random_graph_generator.py|maths/average_mode.py|maths/gamma_recursive.py|maths/proth_number.py|maths/series/geometric_series.py|maths/series/p_series.py|matrix_operation.py|other/least_recently_used.py|other/lfu_cache.py|other/lru_cache.py|searches/simulated_annealing.py|searches/ternary_search.py) - +exclude = (graphs/boruvka.py|graphs/breadth_first_search.py|graphs/breadth_first_search_2.py|graphs/check_cycle.py|graphs/finding_bridges.py|graphs/greedy_min_vertex_cover.py|graphs/random_graph_generator.py|matrix_operation.py|other/least_recently_used.py|other/lfu_cache.py|other/lru_cache.py|searches/simulated_annealing.py|searches/ternary_search.py) From 2f6a7ae1fa44514f52f9a97f83d7bbb2b18e53f2 Mon Sep 17 00:00:00 2001 From: Khoi Vo Date: Mon, 8 Nov 2021 12:35:40 +0700 Subject: [PATCH 217/726] ADD the algorithms of image augmentation (#5792) * ADD the algorithms of image augmentation * ADD the algorithms of image augmentation * ADD the algorithms of image augmentation * ADD the algorithms of image augmentation * ADD the algorithms of image augmentation * ADD the algorithms of image augmentation * UPDATE format code * UPDATE format and recode structure * UPDATE format import library * UPDATE code structure * Fix all checks have failded * FIX variable format * FIX variable format * FIX variable format * FIX code structure * FIX code structure * FIX code structure * FIX code structure --- computer_vision/flip_augmentation.py | 131 +++++++++++++++++ computer_vision/mosaic_augmentation.py | 189 +++++++++++++++++++++++++ 2 files changed, 320 insertions(+) create mode 100644 computer_vision/flip_augmentation.py create mode 100644 computer_vision/mosaic_augmentation.py diff --git a/computer_vision/flip_augmentation.py b/computer_vision/flip_augmentation.py new file mode 100644 index 000000000..1272357fd --- /dev/null +++ b/computer_vision/flip_augmentation.py @@ -0,0 +1,131 @@ +import glob +import os +import random +from string import ascii_lowercase, digits + +import cv2 + +""" +Flip image and bounding box for computer vision task +https://paperswithcode.com/method/randomhorizontalflip +""" + +# Params +LABEL_DIR = "" +IMAGE_DIR = "" +OUTPUT_DIR = "" +FLIP_TYPE = 1 # (0 is vertical, 1 is horizontal) + + +def main() -> None: + """ + Get images list and annotations list from input dir. + Update new images and annotations. + Save images and annotations in output dir. + >>> pass # A doctest is not possible for this function. + """ + img_paths, annos = get_dataset(LABEL_DIR, IMAGE_DIR) + print("Processing...") + new_images, new_annos, paths = update_image_and_anno(img_paths, annos, FLIP_TYPE) + + for index, image in enumerate(new_images): + # Get random string code: '7b7ad245cdff75241935e4dd860f3bad' + letter_code = random_chars(32) + file_name = paths[index].split(os.sep)[-1].rsplit(".", 1)[0] + file_root = f"{OUTPUT_DIR}/{file_name}_FLIP_{letter_code}" + cv2.imwrite(f"/{file_root}.jpg", image, [cv2.IMWRITE_JPEG_QUALITY, 85]) + print(f"Success {index+1}/{len(new_images)} with {file_name}") + annos_list = [] + for anno in new_annos[index]: + obj = f"{anno[0]} {anno[1]} {anno[2]} {anno[3]} {anno[4]}" + annos_list.append(obj) + with open(f"/{file_root}.txt", "w") as outfile: + outfile.write("\n".join(line for line in annos_list)) + + +def get_dataset(label_dir: str, img_dir: str) -> tuple[list, list]: + """ + - label_dir : Path to label include annotation of images + - img_dir : Path to folder contain images + Return : List of images path and labels + >>> pass # A doctest is not possible for this function. + """ + img_paths = [] + labels = [] + for label_file in glob.glob(os.path.join(label_dir, "*.txt")): + label_name = label_file.split(os.sep)[-1].rsplit(".", 1)[0] + with open(label_file) as in_file: + obj_lists = in_file.readlines() + img_path = os.path.join(img_dir, f"{label_name}.jpg") + + boxes = [] + for obj_list in obj_lists: + obj = obj_list.rstrip("\n").split(" ") + boxes.append( + [ + int(obj[0]), + float(obj[1]), + float(obj[2]), + float(obj[3]), + float(obj[4]), + ] + ) + if not boxes: + continue + img_paths.append(img_path) + labels.append(boxes) + return img_paths, labels + + +def update_image_and_anno( + img_list: list, anno_list: list, flip_type: int = 1 +) -> tuple[list, list, list]: + """ + - img_list : list of all images + - anno_list : list of all annotations of specific image + - flip_type : 0 is vertical, 1 is horizontal + Return: + - new_imgs_list : image after resize + - new_annos_lists : list of new annotation after scale + - path_list : list the name of image file + >>> pass # A doctest is not possible for this function. + """ + new_annos_lists = [] + path_list = [] + new_imgs_list = [] + for idx in range(len(img_list)): + new_annos = [] + path = img_list[idx] + path_list.append(path) + img_annos = anno_list[idx] + img = cv2.imread(path) + if flip_type == 1: + new_img = cv2.flip(img, flip_type) + for bbox in img_annos: + x_center_new = 1 - bbox[1] + new_annos.append([bbox[0], x_center_new, bbox[2], bbox[3], bbox[4]]) + elif flip_type == 0: + new_img = cv2.flip(img, flip_type) + for bbox in img_annos: + y_center_new = 1 - bbox[2] + new_annos.append([bbox[0], bbox[1], y_center_new, bbox[3], bbox[4]]) + new_annos_lists.append(new_annos) + new_imgs_list.append(new_img) + return new_imgs_list, new_annos_lists, path_list + + +def random_chars(number_char: int = 32) -> str: + """ + Automatic generate random 32 characters. + Get random string code: '7b7ad245cdff75241935e4dd860f3bad' + >>> len(random_chars(32)) + 32 + """ + assert number_char > 1, "The number of character should greater than 1" + letter_code = ascii_lowercase + digits + return "".join(random.choice(letter_code) for _ in range(number_char)) + + +if __name__ == "__main__": + main() + print("DONE ✅") diff --git a/computer_vision/mosaic_augmentation.py b/computer_vision/mosaic_augmentation.py new file mode 100644 index 000000000..4fd81957c --- /dev/null +++ b/computer_vision/mosaic_augmentation.py @@ -0,0 +1,189 @@ +"""Source: https://github.com/jason9075/opencv-mosaic-data-aug""" + +import glob +import os +import random +from string import ascii_lowercase, digits + +import cv2 +import numpy as np + +# Parrameters +OUTPUT_SIZE = (720, 1280) # Height, Width +SCALE_RANGE = (0.4, 0.6) # if height or width lower than this scale, drop it. +FILTER_TINY_SCALE = 1 / 100 +LABEL_DIR = "" +IMG_DIR = "" +OUTPUT_DIR = "" +NUMBER_IMAGES = 250 + + +def main() -> None: + """ + Get images list and annotations list from input dir. + Update new images and annotations. + Save images and annotations in output dir. + >>> pass # A doctest is not possible for this function. + """ + img_paths, annos = get_dataset(LABEL_DIR, IMG_DIR) + for index in range(NUMBER_IMAGES): + idxs = random.sample(range(len(annos)), 4) + new_image, new_annos, path = update_image_and_anno( + img_paths, + annos, + idxs, + OUTPUT_SIZE, + SCALE_RANGE, + filter_scale=FILTER_TINY_SCALE, + ) + + # Get random string code: '7b7ad245cdff75241935e4dd860f3bad' + letter_code = random_chars(32) + file_name = path.split(os.sep)[-1].rsplit(".", 1)[0] + file_root = f"{OUTPUT_DIR}/{file_name}_MOSAIC_{letter_code}" + cv2.imwrite(f"{file_root}.jpg", new_image, [cv2.IMWRITE_JPEG_QUALITY, 85]) + print(f"Succeeded {index+1}/{NUMBER_IMAGES} with {file_name}") + annos_list = [] + for anno in new_annos: + width = anno[3] - anno[1] + height = anno[4] - anno[2] + x_center = anno[1] + width / 2 + y_center = anno[2] + height / 2 + obj = f"{anno[0]} {x_center} {y_center} {width} {height}" + annos_list.append(obj) + with open(f"{file_root}.txt", "w") as outfile: + outfile.write("\n".join(line for line in annos_list)) + + +def get_dataset(label_dir: str, img_dir: str) -> tuple[list, list]: + """ + - label_dir : Path to label include annotation of images + - img_dir : Path to folder contain images + Return : List of images path and labels + >>> pass # A doctest is not possible for this function. + """ + img_paths = [] + labels = [] + for label_file in glob.glob(os.path.join(label_dir, "*.txt")): + label_name = label_file.split(os.sep)[-1].rsplit(".", 1)[0] + with open(label_file) as in_file: + obj_lists = in_file.readlines() + img_path = os.path.join(img_dir, f"{label_name}.jpg") + + boxes = [] + for obj_list in obj_lists: + obj = obj_list.rstrip("\n").split(" ") + xmin = float(obj[1]) - float(obj[3]) / 2 + ymin = float(obj[2]) - float(obj[4]) / 2 + xmax = float(obj[1]) + float(obj[3]) / 2 + ymax = float(obj[2]) + float(obj[4]) / 2 + + boxes.append([int(obj[0]), xmin, ymin, xmax, ymax]) + if not boxes: + continue + img_paths.append(img_path) + labels.append(boxes) + return img_paths, labels + + +def update_image_and_anno( + all_img_list: list, + all_annos: list, + idxs: list[int], + output_size: tuple[int, int], + scale_range: tuple[float, float], + filter_scale: float = 0.0, +) -> tuple[list, list, str]: + """ + - all_img_list : list of all images + - all_annos : list of all annotations of specific image + - idxs : index of image in list + - output_size : size of output image (Height, Width) + - scale_range : range of scale image + - filter_scale : the condition of downscale image and bounding box + Return: + - output_img : image after resize + - new_anno : list of new annotation after scale + - path[0] : get the name of image file + >>> pass # A doctest is not possible for this function. + """ + output_img = np.zeros([output_size[0], output_size[1], 3], dtype=np.uint8) + scale_x = scale_range[0] + random.random() * (scale_range[1] - scale_range[0]) + scale_y = scale_range[0] + random.random() * (scale_range[1] - scale_range[0]) + divid_point_x = int(scale_x * output_size[1]) + divid_point_y = int(scale_y * output_size[0]) + + new_anno = [] + path_list = [] + for i, index in enumerate(idxs): + path = all_img_list[index] + path_list.append(path) + img_annos = all_annos[index] + img = cv2.imread(path) + if i == 0: # top-left + img = cv2.resize(img, (divid_point_x, divid_point_y)) + output_img[:divid_point_y, :divid_point_x, :] = img + for bbox in img_annos: + xmin = bbox[1] * scale_x + ymin = bbox[2] * scale_y + xmax = bbox[3] * scale_x + ymax = bbox[4] * scale_y + new_anno.append([bbox[0], xmin, ymin, xmax, ymax]) + elif i == 1: # top-right + img = cv2.resize(img, (output_size[1] - divid_point_x, divid_point_y)) + output_img[:divid_point_y, divid_point_x : output_size[1], :] = img + for bbox in img_annos: + xmin = scale_x + bbox[1] * (1 - scale_x) + ymin = bbox[2] * scale_y + xmax = scale_x + bbox[3] * (1 - scale_x) + ymax = bbox[4] * scale_y + new_anno.append([bbox[0], xmin, ymin, xmax, ymax]) + elif i == 2: # bottom-left + img = cv2.resize(img, (divid_point_x, output_size[0] - divid_point_y)) + output_img[divid_point_y : output_size[0], :divid_point_x, :] = img + for bbox in img_annos: + xmin = bbox[1] * scale_x + ymin = scale_y + bbox[2] * (1 - scale_y) + xmax = bbox[3] * scale_x + ymax = scale_y + bbox[4] * (1 - scale_y) + new_anno.append([bbox[0], xmin, ymin, xmax, ymax]) + else: # bottom-right + img = cv2.resize( + img, (output_size[1] - divid_point_x, output_size[0] - divid_point_y) + ) + output_img[ + divid_point_y : output_size[0], divid_point_x : output_size[1], : + ] = img + for bbox in img_annos: + xmin = scale_x + bbox[1] * (1 - scale_x) + ymin = scale_y + bbox[2] * (1 - scale_y) + xmax = scale_x + bbox[3] * (1 - scale_x) + ymax = scale_y + bbox[4] * (1 - scale_y) + new_anno.append([bbox[0], xmin, ymin, xmax, ymax]) + + # Remove bounding box small than scale of filter + if 0 < filter_scale: + new_anno = [ + anno + for anno in new_anno + if filter_scale < (anno[3] - anno[1]) and filter_scale < (anno[4] - anno[2]) + ] + + return output_img, new_anno, path_list[0] + + +def random_chars(number_char: int) -> str: + """ + Automatic generate random 32 characters. + Get random string code: '7b7ad245cdff75241935e4dd860f3bad' + >>> len(random_chars(32)) + 32 + """ + assert number_char > 1, "The number of character should greater than 1" + letter_code = ascii_lowercase + digits + return "".join(random.choice(letter_code) for _ in range(number_char)) + + +if __name__ == "__main__": + main() + print("DONE ✅") From ac4bdfd66dbbd4c7c92c73d894469aa4a5c3e5ab Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Mon, 8 Nov 2021 10:47:09 -0300 Subject: [PATCH 218/726] [mypy] Fix type annotations in `graphs/boruvka.py` (#5794) * Fix type annotations in boruvka.py * Remove graphs/boruvka.py| * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 4 +++- graphs/boruvka.py | 8 +++++--- mypy.ini | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index f515277f4..228d95472 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -109,8 +109,10 @@ ## Computer Vision * [Cnn Classification](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/cnn_classification.py) + * [Flip Augmentation](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/flip_augmentation.py) * [Harris Corner](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/harris_corner.py) * [Mean Threshold](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/mean_threshold.py) + * [Mosaic Augmentation](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/mosaic_augmentation.py) ## Conversions * [Binary To Decimal](https://github.com/TheAlgorithms/Python/blob/master/conversions/binary_to_decimal.py) @@ -297,8 +299,8 @@ * [Test Send File](https://github.com/TheAlgorithms/Python/blob/master/file_transfer/tests/test_send_file.py) ## Financial + * [Equated Monthly Installments](https://github.com/TheAlgorithms/Python/blob/master/financial/equated_monthly_installments.py) * [Interest](https://github.com/TheAlgorithms/Python/blob/master/financial/interest.py) - * [EMI Calculation](https://github.com/TheAlgorithms/Python/blob/master/financial/equated_monthly_installments.py) ## Fractals * [Julia Sets](https://github.com/TheAlgorithms/Python/blob/master/fractals/julia_sets.py) diff --git a/graphs/boruvka.py b/graphs/boruvka.py index eea0b0009..2715a3085 100644 --- a/graphs/boruvka.py +++ b/graphs/boruvka.py @@ -26,6 +26,8 @@ """ from __future__ import annotations +from typing import Any + class Graph: def __init__(self, num_of_nodes: int) -> None: @@ -62,7 +64,7 @@ class Graph: for k in self.m_component: self.m_component[k] = self.find_component(k) - def union(self, component_size: list, u_node: int, v_node: int) -> None: + def union(self, component_size: list[int], u_node: int, v_node: int) -> None: """Union finds the roots of components for two nodes, compares the components in terms of size, and attaches the smaller one to the larger one to form single component""" @@ -84,7 +86,7 @@ class Graph: component_size = [] mst_weight = 0 - minimum_weight_edge: list[int] = [-1] * self.m_num_of_nodes + minimum_weight_edge: list[Any] = [-1] * self.m_num_of_nodes # A list of components (initialized to all of the nodes) for node in range(self.m_num_of_nodes): @@ -119,7 +121,7 @@ class Graph: minimum_weight_edge[component] = [u, v, w] for edge in minimum_weight_edge: - if edge != -1: + if isinstance(edge, list): u, v, w = edge u_component = self.m_component[u] diff --git a/mypy.ini b/mypy.ini index df69fa841..16ca60c4d 100644 --- a/mypy.ini +++ b/mypy.ini @@ -2,4 +2,4 @@ ignore_missing_imports = True install_types = True non_interactive = True -exclude = (graphs/boruvka.py|graphs/breadth_first_search.py|graphs/breadth_first_search_2.py|graphs/check_cycle.py|graphs/finding_bridges.py|graphs/greedy_min_vertex_cover.py|graphs/random_graph_generator.py|matrix_operation.py|other/least_recently_used.py|other/lfu_cache.py|other/lru_cache.py|searches/simulated_annealing.py|searches/ternary_search.py) +exclude = (graphs/breadth_first_search.py|graphs/breadth_first_search_2.py|graphs/check_cycle.py|graphs/finding_bridges.py|graphs/greedy_min_vertex_cover.py|graphs/random_graph_generator.py|matrix_operation.py|other/least_recently_used.py|other/lfu_cache.py|other/lru_cache.py|searches/simulated_annealing.py|searches/ternary_search.py) From a8aeabdf1891397a4a55988f33ac435ae0313c55 Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj Date: Mon, 8 Nov 2021 22:48:33 +0530 Subject: [PATCH 219/726] [mypy] Type annotations for `graphs/finding_bridges.py` and `graphs/random_graph_generator.py` (#5795) * [mypy] Annotate `graphs/finding_bridges.py` * Remove from excluded in `mypy.ini` * Add doctest.testmod() * psf/black formatting * Annotations for `graphs/random_graph_generator.py` * Remove from excluded in `mypy.ini` * Resolve merge conflict * Resolve merge conflict * Update mypy.ini * Update mypy.ini * Remove from excluded --- graphs/finding_bridges.py | 8 +++++++- graphs/random_graph_generator.py | 2 +- mypy.ini | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/graphs/finding_bridges.py b/graphs/finding_bridges.py index a877a9748..3813c4ebb 100644 --- a/graphs/finding_bridges.py +++ b/graphs/finding_bridges.py @@ -93,8 +93,14 @@ def compute_bridges(graph: dict[int, list[int]]) -> list[tuple[int, int]]: # This edge is a back edge and cannot be a bridge low[at] = min(low[at], low[to]) - bridges = [] + bridges: list[tuple[int, int]] = [] for i in range(n): if not visited[i]: dfs(i, -1, bridges, id) return bridges + + +if __name__ == "__main__": + import doctest + + doctest.testmod() diff --git a/graphs/random_graph_generator.py b/graphs/random_graph_generator.py index d7d5de8a3..15ccee5b3 100644 --- a/graphs/random_graph_generator.py +++ b/graphs/random_graph_generator.py @@ -26,7 +26,7 @@ def random_graph( >>> random_graph(4, 0.5, True) {0: [1], 1: [2, 3], 2: [3], 3: []} """ - graph = {i: [] for i in range(vertices_number)} + graph: dict = {i: [] for i in range(vertices_number)} # if probability is greater or equal than 1, then generate a complete graph if probability >= 1: diff --git a/mypy.ini b/mypy.ini index 16ca60c4d..429c6804d 100644 --- a/mypy.ini +++ b/mypy.ini @@ -2,4 +2,4 @@ ignore_missing_imports = True install_types = True non_interactive = True -exclude = (graphs/breadth_first_search.py|graphs/breadth_first_search_2.py|graphs/check_cycle.py|graphs/finding_bridges.py|graphs/greedy_min_vertex_cover.py|graphs/random_graph_generator.py|matrix_operation.py|other/least_recently_used.py|other/lfu_cache.py|other/lru_cache.py|searches/simulated_annealing.py|searches/ternary_search.py) +exclude = (graphs/breadth_first_search.py|graphs/breadth_first_search_2.py|graphs/check_cycle.py|graphs/greedy_min_vertex_cover.py|matrix_operation.py|other/least_recently_used.py|other/lfu_cache.py|other/lru_cache.py|searches/simulated_annealing.py|searches/ternary_search.py) From 4c9949f636248a547b9ff832ad18df372df57ed5 Mon Sep 17 00:00:00 2001 From: Leoriem-code <73761711+Leoriem-code@users.noreply.github.com> Date: Mon, 8 Nov 2021 18:58:15 +0100 Subject: [PATCH 220/726] edited strings/anagram.py (#5770) * rewrote anagrams.py, added doctests * corrected mistakes * add anagrams.txt * Update anagrams.py * Update strings/anagrams.py Co-authored-by: Christian Clauss Co-authored-by: Christian Clauss --- strings/anagrams.py | 55 +- strings/anagrams.txt | 33957 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 33989 insertions(+), 23 deletions(-) create mode 100644 strings/anagrams.txt diff --git a/strings/anagrams.py b/strings/anagrams.py index 1a7c675d6..b671d3f3d 100644 --- a/strings/anagrams.py +++ b/strings/anagrams.py @@ -1,35 +1,44 @@ +from __future__ import annotations + import collections -import os import pprint -import time - -start_time = time.time() -print("creating word list...") -path = os.path.split(os.path.realpath(__file__)) -with open(path[0] + "/words.txt") as f: - word_list = sorted(list({word.strip().lower() for word in f})) +from pathlib import Path -def signature(word): +def signature(word: str) -> str: + """Return a word sorted + >>> signature("test") + 'estt' + >>> signature("this is a test") + ' aehiisssttt' + >>> signature("finaltest") + 'aefilnstt' + """ return "".join(sorted(word)) +def anagram(my_word: str) -> list[str]: + """Return every anagram of the given word + >>> anagram('test') + ['sett', 'stet', 'test'] + >>> anagram('this is a test') + [] + >>> anagram('final') + ['final'] + """ + return word_bysig[signature(my_word)] + + +data: str = Path(__file__).parent.joinpath("words.txt").read_text(encoding="utf-8") +word_list = sorted({word.strip().lower() for word in data.splitlines()}) + word_bysig = collections.defaultdict(list) for word in word_list: word_bysig[signature(word)].append(word) +if __name__ == "__main__": + all_anagrams = {word: anagram(word) for word in word_list if len(anagram(word)) > 1} -def anagram(my_word): - return word_bysig[signature(my_word)] - - -print("finding anagrams...") -all_anagrams = {word: anagram(word) for word in word_list if len(anagram(word)) > 1} - -print("writing anagrams to file...") -with open("anagrams.txt", "w") as file: - file.write("all_anagrams = ") - file.write(pprint.pformat(all_anagrams)) - -total_time = round(time.time() - start_time, 2) -print(("Done [", total_time, "seconds ]")) + with open("anagrams.txt", "w") as file: + file.write("all_anagrams = \n ") + file.write(pprint.pformat(all_anagrams)) diff --git a/strings/anagrams.txt b/strings/anagrams.txt new file mode 100644 index 000000000..52a0fcf3e --- /dev/null +++ b/strings/anagrams.txt @@ -0,0 +1,33957 @@ +all_anagrams = + {'aal': ['aal', 'ala'], + 'aam': ['aam', 'ama'], + 'aaronic': ['aaronic', 'nicarao', 'ocarina'], + 'aaronite': ['aaronite', 'aeration'], + 'aaru': ['aaru', 'aura'], + 'ab': ['ab', 'ba'], + 'aba': ['aba', 'baa'], + 'abac': ['abac', 'caba'], + 'abactor': ['abactor', 'acrobat'], + 'abaft': ['abaft', 'bafta'], + 'abalone': ['abalone', 'balonea'], + 'abandoner': ['abandoner', 'reabandon'], + 'abanic': ['abanic', 'bianca'], + 'abaris': ['abaris', 'arabis'], + 'abas': ['abas', 'saba'], + 'abaser': ['abaser', 'abrase'], + 'abate': ['abate', 'ateba', 'batea', 'beata'], + 'abater': ['abater', 'artabe', 'eartab', 'trabea'], + 'abb': ['abb', 'bab'], + 'abba': ['abba', 'baba'], + 'abbey': ['abbey', 'bebay'], + 'abby': ['abby', 'baby'], + 'abdat': ['abdat', 'batad'], + 'abdiel': ['abdiel', 'baldie'], + 'abdominovaginal': ['abdominovaginal', 'vaginoabdominal'], + 'abdominovesical': ['abdominovesical', 'vesicoabdominal'], + 'abe': ['abe', 'bae', 'bea'], + 'abed': ['abed', 'bade', 'bead'], + 'abel': ['abel', 'able', 'albe', 'bale', 'beal', 'bela', 'blae'], + 'abele': ['abele', 'albee'], + 'abelian': ['abelian', 'nebalia'], + 'abenteric': ['abenteric', 'bicrenate'], + 'aberia': ['aberia', 'baeria', 'baiera'], + 'abet': ['abet', 'bate', 'beat', 'beta'], + 'abetment': ['abetment', 'batement'], + 'abettor': ['abettor', 'taboret'], + 'abhorrent': ['abhorrent', 'earthborn'], + 'abhorrer': ['abhorrer', 'harborer'], + 'abider': ['abider', 'bardie'], + 'abies': ['abies', 'beisa'], + 'abilla': ['abilla', 'labial'], + 'abilo': ['abilo', 'aboil'], + 'abir': ['abir', 'bari', 'rabi'], + 'abiston': ['abiston', 'bastion'], + 'abiuret': ['abiuret', 'aubrite', 'biurate', 'rubiate'], + 'abkar': ['abkar', 'arkab'], + 'abkhas': ['abkhas', 'kasbah'], + 'ablactate': ['ablactate', 'cabaletta'], + 'ablare': ['ablare', 'arable', 'arbela'], + 'ablastemic': ['ablastemic', 'masticable'], + 'ablation': ['ablation', 'obtainal'], + 'ablaut': ['ablaut', 'tabula'], + 'able': ['abel', 'able', 'albe', 'bale', 'beal', 'bela', 'blae'], + 'ableness': ['ableness', 'blaeness', 'sensable'], + 'ablepsia': ['ablepsia', 'epibasal'], + 'abler': ['abler', 'baler', 'belar', 'blare', 'blear'], + 'ablest': ['ablest', 'stable', 'tables'], + 'abloom': ['abloom', 'mabolo'], + 'ablow': ['ablow', 'balow', 'bowla'], + 'ablude': ['ablude', 'belaud'], + 'abluent': ['abluent', 'tunable'], + 'ablution': ['ablution', 'abutilon'], + 'ably': ['ably', 'blay', 'yalb'], + 'abmho': ['abmho', 'abohm'], + 'abner': ['abner', 'arneb', 'reban'], + 'abnet': ['abnet', 'beant'], + 'abo': ['abo', 'boa'], + 'aboard': ['aboard', 'aborad', 'abroad'], + 'abode': ['abode', 'adobe'], + 'abohm': ['abmho', 'abohm'], + 'aboil': ['abilo', 'aboil'], + 'abolisher': ['abolisher', 'reabolish'], + 'abongo': ['abongo', 'gaboon'], + 'aborad': ['aboard', 'aborad', 'abroad'], + 'aboral': ['aboral', 'arbalo'], + 'abord': ['abord', 'bardo', 'board', 'broad', 'dobra', 'dorab'], + 'abort': ['abort', 'tabor'], + 'aborticide': ['aborticide', 'bacterioid'], + 'abortient': ['abortient', 'torbanite'], + 'abortin': ['abortin', 'taborin'], + 'abortion': ['abortion', 'robotian'], + 'abortive': ['abortive', 'bravoite'], + 'abouts': ['abouts', 'basuto'], + 'abram': ['abram', 'ambar'], + 'abramis': ['abramis', 'arabism'], + 'abrasax': ['abrasax', 'abraxas'], + 'abrase': ['abaser', 'abrase'], + 'abrasion': ['abrasion', 'sorabian'], + 'abrastol': ['abrastol', 'albatros'], + 'abraxas': ['abrasax', 'abraxas'], + 'abreact': ['abreact', 'bractea', 'cabaret'], + 'abret': ['abret', 'bater', 'berat'], + 'abridge': ['abridge', 'brigade'], + 'abrim': ['abrim', 'birma'], + 'abrin': ['abrin', 'bairn', 'brain', 'brian', 'rabin'], + 'abristle': ['abristle', 'libertas'], + 'abroad': ['aboard', 'aborad', 'abroad'], + 'abrotine': ['abrotine', 'baritone', 'obtainer', 'reobtain'], + 'abrus': ['abrus', 'bursa', 'subra'], + 'absalom': ['absalom', 'balsamo'], + 'abscise': ['abscise', 'scabies'], + 'absent': ['absent', 'basten'], + 'absenter': ['absenter', 'reabsent'], + 'absi': ['absi', 'bais', 'bias', 'isba'], + 'absit': ['absit', 'batis'], + 'absmho': ['absmho', 'absohm'], + 'absohm': ['absmho', 'absohm'], + 'absorber': ['absorber', 'reabsorb'], + 'absorpt': ['absorpt', 'barpost'], + 'abthain': ['abthain', 'habitan'], + 'abulic': ['abulic', 'baculi'], + 'abut': ['abut', 'tabu', 'tuba'], + 'abuta': ['abuta', 'bauta'], + 'abutilon': ['ablution', 'abutilon'], + 'aby': ['aby', 'bay'], + 'abysmal': ['abysmal', 'balsamy'], + 'academite': ['academite', 'acetamide'], + 'acadie': ['acadie', 'acedia', 'adicea'], + 'acaleph': ['acaleph', 'acephal'], + 'acalepha': ['acalepha', 'acephala'], + 'acalephae': ['acalephae', 'apalachee'], + 'acalephan': ['acalephan', 'acephalan'], + 'acalyptrate': ['acalyptrate', 'calyptratae'], + 'acamar': ['acamar', 'camara', 'maraca'], + 'acanth': ['acanth', 'anchat', 'tanach'], + 'acanthia': ['acanthia', 'achatina'], + 'acanthial': ['acanthial', 'calathian'], + 'acanthin': ['acanthin', 'chinanta'], + 'acara': ['acara', 'araca'], + 'acardia': ['acardia', 'acarida', 'arcadia'], + 'acarian': ['acarian', 'acarina', 'acrania'], + 'acarid': ['acarid', 'cardia', 'carida'], + 'acarida': ['acardia', 'acarida', 'arcadia'], + 'acarina': ['acarian', 'acarina', 'acrania'], + 'acarine': ['acarine', 'acraein', 'arecain'], + 'acastus': ['acastus', 'astacus'], + 'acatholic': ['acatholic', 'chaotical'], + 'acaudate': ['acaudate', 'ecaudata'], + 'acca': ['acca', 'caca'], + 'accelerator': ['accelerator', 'retrocaecal'], + 'acception': ['acception', 'peccation'], + 'accessioner': ['accessioner', 'reaccession'], + 'accipitres': ['accipitres', 'preascitic'], + 'accite': ['accite', 'acetic'], + 'acclinate': ['acclinate', 'analectic'], + 'accoil': ['accoil', 'calico'], + 'accomplisher': ['accomplisher', 'reaccomplish'], + 'accompt': ['accompt', 'compact'], + 'accorder': ['accorder', 'reaccord'], + 'accoy': ['accoy', 'ccoya'], + 'accretion': ['accretion', 'anorectic', 'neoarctic'], + 'accrual': ['accrual', 'carucal'], + 'accurate': ['accurate', 'carucate'], + 'accurse': ['accurse', 'accuser'], + 'accusable': ['accusable', 'subcaecal'], + 'accused': ['accused', 'succade'], + 'accuser': ['accurse', 'accuser'], + 'acedia': ['acadie', 'acedia', 'adicea'], + 'acedy': ['acedy', 'decay'], + 'acentric': ['acentric', 'encratic', 'nearctic'], + 'acentrous': ['acentrous', 'courtesan', 'nectarous'], + 'acephal': ['acaleph', 'acephal'], + 'acephala': ['acalepha', 'acephala'], + 'acephalan': ['acalephan', 'acephalan'], + 'acephali': ['acephali', 'phacelia'], + 'acephalina': ['acephalina', 'phalaecian'], + 'acer': ['acer', 'acre', 'care', 'crea', 'race'], + 'aceraceae': ['aceraceae', 'arecaceae'], + 'aceraceous': ['aceraceous', 'arecaceous'], + 'acerb': ['acerb', 'brace', 'caber'], + 'acerbic': ['acerbic', 'breccia'], + 'acerdol': ['acerdol', 'coraled'], + 'acerin': ['acerin', 'cearin'], + 'acerous': ['acerous', 'carouse', 'euscaro'], + 'acervate': ['acervate', 'revacate'], + 'acervation': ['acervation', 'vacationer'], + 'acervuline': ['acervuline', 'avirulence'], + 'acetamide': ['academite', 'acetamide'], + 'acetamido': ['acetamido', 'coadamite'], + 'acetanilid': ['acetanilid', 'laciniated', 'teniacidal'], + 'acetanion': ['acetanion', 'antoecian'], + 'acetation': ['acetation', 'itaconate'], + 'acetic': ['accite', 'acetic'], + 'acetin': ['acetin', 'actine', 'enatic'], + 'acetmethylanilide': ['acetmethylanilide', 'methylacetanilide'], + 'acetoin': ['acetoin', 'aconite', 'anoetic', 'antoeci', 'cetonia'], + 'acetol': ['acetol', 'colate', 'locate'], + 'acetone': ['acetone', 'oceanet'], + 'acetonuria': ['acetonuria', 'aeronautic'], + 'acetopyrin': ['acetopyrin', 'capernoity'], + 'acetous': ['acetous', 'outcase'], + 'acetum': ['acetum', 'tecuma'], + 'aceturic': ['aceturic', 'cruciate'], + 'ach': ['ach', 'cha'], + 'achar': ['achar', 'chara'], + 'achate': ['achate', 'chaeta'], + 'achatina': ['acanthia', 'achatina'], + 'ache': ['ache', 'each', 'haec'], + 'acheirus': ['acheirus', 'eucharis'], + 'achen': ['achen', 'chane', 'chena', 'hance'], + 'acher': ['acher', 'arche', 'chare', 'chera', 'rache', 'reach'], + 'acherontic': ['acherontic', 'anchoretic'], + 'acherontical': ['acherontical', 'anchoretical'], + 'achete': ['achete', 'hecate', 'teache', 'thecae'], + 'acheulean': ['acheulean', 'euchlaena'], + 'achill': ['achill', 'cahill', 'chilla'], + 'achillea': ['achillea', 'heliacal'], + 'acholia': ['acholia', 'alochia'], + 'achondrite': ['achondrite', 'ditrochean', 'ordanchite'], + 'achor': ['achor', 'chora', 'corah', 'orach', 'roach'], + 'achras': ['achras', 'charas'], + 'achromat': ['achromat', 'trachoma'], + 'achromatin': ['achromatin', 'chariotman', 'machinator'], + 'achromatinic': ['achromatinic', 'chromatician'], + 'achtel': ['achtel', 'chalet', 'thecal', 'thecla'], + 'achy': ['achy', 'chay'], + 'aciculated': ['aciculated', 'claudicate'], + 'acid': ['acid', 'cadi', 'caid'], + 'acidanthera': ['acidanthera', 'cantharidae'], + 'acider': ['acider', 'ericad'], + 'acidimeter': ['acidimeter', 'mediatrice'], + 'acidity': ['acidity', 'adicity'], + 'acidly': ['acidly', 'acidyl'], + 'acidometry': ['acidometry', 'medicatory', 'radiectomy'], + 'acidophilous': ['acidophilous', 'aphidicolous'], + 'acidyl': ['acidly', 'acidyl'], + 'acier': ['acier', 'aeric', 'ceria', 'erica'], + 'acieral': ['acieral', 'aerical'], + 'aciform': ['aciform', 'formica'], + 'acilius': ['acilius', 'iliacus'], + 'acinar': ['acinar', + 'arnica', + 'canari', + 'carian', + 'carina', + 'crania', + 'narica'], + 'acinic': ['acinic', 'incaic'], + 'aciniform': ['aciniform', 'formicina'], + 'acipenserid': ['acipenserid', 'presidencia'], + 'acis': ['acis', 'asci', 'saic'], + 'acker': ['acker', 'caker', 'crake', 'creak'], + 'ackey': ['ackey', 'cakey'], + 'acle': ['acle', 'alec', 'lace'], + 'acleistous': ['acleistous', 'ossiculate'], + 'aclemon': ['aclemon', 'cloamen'], + 'aclinal': ['aclinal', 'ancilla'], + 'aclys': ['aclys', 'scaly'], + 'acme': ['acme', 'came', 'mace'], + 'acmite': ['acmite', 'micate'], + 'acne': ['acne', 'cane', 'nace'], + 'acnemia': ['acnemia', 'anaemic'], + 'acnida': ['acnida', 'anacid', 'dacian'], + 'acnodal': ['acnodal', 'canadol', 'locanda'], + 'acnode': ['acnode', 'deacon'], + 'acoin': ['acoin', 'oncia'], + 'acoma': ['acoma', 'macao'], + 'acone': ['acone', 'canoe', 'ocean'], + 'aconital': ['aconital', 'actional', 'anatolic'], + 'aconite': ['acetoin', 'aconite', 'anoetic', 'antoeci', 'cetonia'], + 'aconitic': ['aconitic', 'cationic', 'itaconic'], + 'aconitin': ['aconitin', 'inaction', 'nicotian'], + 'aconitum': ['aconitum', 'acontium'], + 'acontias': ['acontias', 'tacsonia'], + 'acontium': ['aconitum', 'acontium'], + 'acontius': ['acontius', 'anticous'], + 'acopon': ['acopon', 'poonac'], + 'acor': ['acor', 'caro', 'cora', 'orca'], + 'acorn': ['acorn', 'acron', 'racon'], + 'acorus': ['acorus', 'soucar'], + 'acosmist': ['acosmist', 'massicot', 'somatics'], + 'acquest': ['acquest', 'casquet'], + 'acrab': ['acrab', 'braca'], + 'acraein': ['acarine', 'acraein', 'arecain'], + 'acrania': ['acarian', 'acarina', 'acrania'], + 'acraniate': ['acraniate', 'carinatae'], + 'acratia': ['acratia', 'cataria'], + 'acre': ['acer', 'acre', 'care', 'crea', 'race'], + 'acream': ['acream', 'camera', 'mareca'], + 'acred': ['acred', 'cader', 'cadre', 'cedar'], + 'acrid': ['acrid', 'caird', 'carid', 'darci', 'daric', 'dirca'], + 'acridan': ['acridan', 'craniad'], + 'acridian': ['acridian', 'cnidaria'], + 'acrididae': ['acrididae', 'cardiidae', 'cidaridae'], + 'acridly': ['acridly', 'acridyl'], + 'acridonium': ['acridonium', 'dicoumarin'], + 'acridyl': ['acridly', 'acridyl'], + 'acrimonious': ['acrimonious', 'isocoumarin'], + 'acrisius': ['acrisius', 'sicarius'], + 'acrita': ['acrita', 'arctia'], + 'acritan': ['acritan', 'arctian'], + 'acrite': ['acrite', 'arcite', 'tercia', 'triace', 'tricae'], + 'acroa': ['acroa', 'caroa'], + 'acrobat': ['abactor', 'acrobat'], + 'acrocera': ['acrocera', 'caracore'], + 'acroclinium': ['acroclinium', 'alcicornium'], + 'acrodus': ['acrodus', 'crusado'], + 'acrogen': ['acrogen', 'cornage'], + 'acrolein': ['acrolein', + 'arecolin', + 'caroline', + 'colinear', + 'cornelia', + 'creolian', + 'lonicera'], + 'acrolith': ['acrolith', 'trochila'], + 'acron': ['acorn', 'acron', 'racon'], + 'acronical': ['acronical', 'alcoranic'], + 'acronym': ['acronym', 'romancy'], + 'acropetal': ['acropetal', 'cleopatra'], + 'acrose': ['acrose', 'coarse'], + 'acrostic': ['acrostic', 'sarcotic', 'socratic'], + 'acrostical': ['acrostical', 'socratical'], + 'acrostically': ['acrostically', 'socratically'], + 'acrosticism': ['acrosticism', 'socraticism'], + 'acrotic': ['acrotic', 'carotic'], + 'acrotism': ['acrotism', 'rotacism'], + 'acrotrophic': ['acrotrophic', 'prothoracic'], + 'acryl': ['acryl', 'caryl', 'clary'], + 'act': ['act', 'cat'], + 'actaeonidae': ['actaeonidae', 'donatiaceae'], + 'actian': ['actian', 'natica', 'tanica'], + 'actifier': ['actifier', 'artifice'], + 'actin': ['actin', 'antic'], + 'actinal': ['actinal', 'alantic', 'alicant', 'antical'], + 'actine': ['acetin', 'actine', 'enatic'], + 'actiniform': ['actiniform', 'naticiform'], + 'actinine': ['actinine', 'naticine'], + 'actinism': ['actinism', 'manistic'], + 'actinogram': ['actinogram', 'morganatic'], + 'actinoid': ['actinoid', 'diatonic', 'naticoid'], + 'actinon': ['actinon', 'cantion', 'contain'], + 'actinopteran': ['actinopteran', 'precantation'], + 'actinopteri': ['actinopteri', 'crepitation', 'precitation'], + 'actinost': ['actinost', 'oscitant'], + 'actinula': ['actinula', 'nautical'], + 'action': ['action', 'atonic', 'cation'], + 'actional': ['aconital', 'actional', 'anatolic'], + 'actioner': ['actioner', 'anerotic', 'ceration', 'creation', 'reaction'], + 'activable': ['activable', 'biclavate'], + 'activate': ['activate', 'cavitate'], + 'activation': ['activation', 'cavitation'], + 'activin': ['activin', 'civitan'], + 'actomyosin': ['actomyosin', 'inocystoma'], + 'acton': ['acton', 'canto', 'octan'], + 'actor': ['actor', 'corta', 'croat', 'rocta', 'taroc', 'troca'], + 'actorship': ['actorship', 'strophaic'], + 'acts': ['acts', 'cast', 'scat'], + 'actuator': ['actuator', 'autocrat'], + 'acture': ['acture', 'cauter', 'curate'], + 'acuan': ['acuan', 'aucan'], + 'acubens': ['acubens', 'benacus'], + 'acumen': ['acumen', 'cueman'], + 'acuminose': ['acuminose', 'mniaceous'], + 'acutenaculum': ['acutenaculum', 'unaccumulate'], + 'acuteness': ['acuteness', 'encaustes'], + 'acutorsion': ['acutorsion', 'octonarius'], + 'acyl': ['acyl', 'clay', 'lacy'], + 'acylation': ['acylation', 'claytonia'], + 'acylogen': ['acylogen', 'cynogale'], + 'ad': ['ad', 'da'], + 'adad': ['adad', 'adda', 'dada'], + 'adage': ['adage', 'agade'], + 'adam': ['adam', 'dama'], + 'adamic': ['adamic', 'cadmia'], + 'adamine': ['adamine', 'manidae'], + 'adamite': ['adamite', 'amidate'], + 'adamsite': ['adamsite', 'diastema'], + 'adance': ['adance', 'ecanda'], + 'adapter': ['adapter', 'predata', 'readapt'], + 'adaption': ['adaption', 'adoptian'], + 'adaptionism': ['adaptionism', 'adoptianism'], + 'adar': ['adar', 'arad', 'raad', 'rada'], + 'adarme': ['adarme', 'adream'], + 'adat': ['adat', 'data'], + 'adawn': ['adawn', 'wadna'], + 'adays': ['adays', 'dasya'], + 'add': ['add', 'dad'], + 'adda': ['adad', 'adda', 'dada'], + 'addendum': ['addendum', 'unmadded'], + 'adder': ['adder', 'dread', 'readd'], + 'addicent': ['addicent', 'dedicant'], + 'addlings': ['addlings', 'saddling'], + 'addresser': ['addresser', 'readdress'], + 'addu': ['addu', 'dadu', 'daud', 'duad'], + 'addy': ['addy', 'dyad'], + 'ade': ['ade', 'dae'], + 'adeem': ['adeem', 'ameed', 'edema'], + 'adela': ['adela', 'dalea'], + 'adeline': ['adeline', 'daniele', 'delaine'], + 'adeling': ['adeling', 'dealing', 'leading'], + 'adelops': ['adelops', 'deposal'], + 'ademonist': ['ademonist', 'demoniast', 'staminode'], + 'ademption': ['ademption', 'tampioned'], + 'adendric': ['adendric', 'riddance'], + 'adenectopic': ['adenectopic', 'pentadecoic'], + 'adenia': ['adenia', 'idaean'], + 'adenochondroma': ['adenochondroma', 'chondroadenoma'], + 'adenocystoma': ['adenocystoma', 'cystoadenoma'], + 'adenofibroma': ['adenofibroma', 'fibroadenoma'], + 'adenolipoma': ['adenolipoma', 'palaemonoid'], + 'adenosarcoma': ['adenosarcoma', 'sarcoadenoma'], + 'adenylic': ['adenylic', 'lycaenid'], + 'adeptness': ['adeptness', 'pedantess'], + 'adequation': ['adequation', 'deaquation'], + 'adermia': ['adermia', 'madeira'], + 'adermin': ['adermin', 'amerind', 'dimeran'], + 'adet': ['adet', 'date', 'tade', 'tead', 'teda'], + 'adevism': ['adevism', 'vedaism'], + 'adhere': ['adhere', 'header', 'hedera', 'rehead'], + 'adherent': ['adherent', 'headrent', 'neatherd', 'threaden'], + 'adiaphon': ['adiaphon', 'aphodian'], + 'adib': ['adib', 'ibad'], + 'adicea': ['acadie', 'acedia', 'adicea'], + 'adicity': ['acidity', 'adicity'], + 'adiel': ['adiel', 'delia', 'ideal'], + 'adieux': ['adieux', 'exaudi'], + 'adighe': ['adighe', 'hidage'], + 'adin': ['adin', 'andi', 'dain', 'dani', 'dian', 'naid'], + 'adinole': ['adinole', 'idoneal'], + 'adion': ['adion', 'danio', 'doina', 'donia'], + 'adipocele': ['adipocele', 'cepolidae', 'ploceidae'], + 'adipocere': ['adipocere', 'percoidea'], + 'adipyl': ['adipyl', 'plaidy'], + 'adit': ['adit', 'dita'], + 'adital': ['adital', 'altaid'], + 'aditus': ['aditus', 'studia'], + 'adjuster': ['adjuster', 'readjust'], + 'adlai': ['adlai', 'alida'], + 'adlay': ['adlay', 'dayal'], + 'adlet': ['adlet', 'dealt', 'delta', 'lated', 'taled'], + 'adlumine': ['adlumine', 'unmailed'], + 'adman': ['adman', 'daman', 'namda'], + 'admi': ['admi', 'amid', 'madi', 'maid'], + 'adminicle': ['adminicle', 'medicinal'], + 'admire': ['admire', 'armied', 'damier', 'dimera', 'merida'], + 'admired': ['admired', 'diaderm'], + 'admirer': ['admirer', 'madrier', 'married'], + 'admissive': ['admissive', 'misadvise'], + 'admit': ['admit', 'atmid'], + 'admittee': ['admittee', 'meditate'], + 'admonisher': ['admonisher', 'rhamnoside'], + 'admonition': ['admonition', 'domination'], + 'admonitive': ['admonitive', 'dominative'], + 'admonitor': ['admonitor', 'dominator'], + 'adnascence': ['adnascence', 'ascendance'], + 'adnascent': ['adnascent', 'ascendant'], + 'adnate': ['adnate', 'entada'], + 'ado': ['ado', 'dao', 'oda'], + 'adobe': ['abode', 'adobe'], + 'adolph': ['adolph', 'pholad'], + 'adonai': ['adonai', 'adonia'], + 'adonia': ['adonai', 'adonia'], + 'adonic': ['adonic', 'anodic'], + 'adonin': ['adonin', 'nanoid', 'nonaid'], + 'adoniram': ['adoniram', 'radioman'], + 'adonize': ['adonize', 'anodize'], + 'adopter': ['adopter', 'protead', 'readopt'], + 'adoptian': ['adaption', 'adoptian'], + 'adoptianism': ['adaptionism', 'adoptianism'], + 'adoptional': ['adoptional', 'aplodontia'], + 'adorability': ['adorability', 'roadability'], + 'adorable': ['adorable', 'roadable'], + 'adorant': ['adorant', 'ondatra'], + 'adore': ['adore', 'oared', 'oread'], + 'adorer': ['adorer', 'roader'], + 'adorn': ['adorn', 'donar', 'drona', 'radon'], + 'adorner': ['adorner', 'readorn'], + 'adpao': ['adpao', 'apoda'], + 'adpromission': ['adpromission', 'proadmission'], + 'adream': ['adarme', 'adream'], + 'adrenin': ['adrenin', 'nardine'], + 'adrenine': ['adrenine', 'adrienne'], + 'adrenolytic': ['adrenolytic', 'declinatory'], + 'adrenotropic': ['adrenotropic', 'incorporated'], + 'adrian': ['adrian', 'andira', 'andria', 'radian', 'randia'], + 'adrienne': ['adrenine', 'adrienne'], + 'adrip': ['adrip', 'rapid'], + 'adroitly': ['adroitly', 'dilatory', 'idolatry'], + 'adrop': ['adrop', 'pardo'], + 'adry': ['adry', 'dray', 'yard'], + 'adscendent': ['adscendent', 'descendant'], + 'adsmith': ['adsmith', 'mahdist'], + 'adular': ['adular', 'aludra', 'radula'], + 'adulation': ['adulation', 'laudation'], + 'adulator': ['adulator', 'laudator'], + 'adulatory': ['adulatory', 'laudatory'], + 'adult': ['adult', 'dulat'], + 'adulterine': ['adulterine', 'laurentide'], + 'adultness': ['adultness', 'dauntless'], + 'adustion': ['adustion', 'sudation'], + 'advene': ['advene', 'evadne'], + 'adventism': ['adventism', 'vedantism'], + 'adventist': ['adventist', 'vedantist'], + 'adventure': ['adventure', 'unaverted'], + 'advice': ['advice', 'vedaic'], + 'ady': ['ady', 'day', 'yad'], + 'adz': ['adz', 'zad'], + 'adze': ['adze', 'daze'], + 'adzer': ['adzer', 'zerda'], + 'ae': ['ae', 'ea'], + 'aecidioform': ['aecidioform', 'formicoidea'], + 'aedilian': ['aedilian', 'laniidae'], + 'aedilic': ['aedilic', 'elaidic'], + 'aedility': ['aedility', 'ideality'], + 'aegipan': ['aegipan', 'apinage'], + 'aegirine': ['aegirine', 'erigenia'], + 'aegirite': ['aegirite', 'ariegite'], + 'aegle': ['aegle', 'eagle', 'galee'], + 'aenean': ['aenean', 'enaena'], + 'aeolharmonica': ['aeolharmonica', 'chloroanaemia'], + 'aeolian': ['aeolian', 'aeolina', 'aeonial'], + 'aeolic': ['aeolic', 'coelia'], + 'aeolina': ['aeolian', 'aeolina', 'aeonial'], + 'aeolis': ['aeolis', 'laiose'], + 'aeolist': ['aeolist', 'isolate'], + 'aeolistic': ['aeolistic', 'socialite'], + 'aeon': ['aeon', 'eoan'], + 'aeonial': ['aeolian', 'aeolina', 'aeonial'], + 'aeonist': ['aeonist', 'asiento', 'satieno'], + 'aer': ['aer', 'are', 'ear', 'era', 'rea'], + 'aerage': ['aerage', 'graeae'], + 'aerarian': ['aerarian', 'arenaria'], + 'aeration': ['aaronite', 'aeration'], + 'aerial': ['aerial', 'aralie'], + 'aeric': ['acier', 'aeric', 'ceria', 'erica'], + 'aerical': ['acieral', 'aerical'], + 'aeried': ['aeried', 'dearie'], + 'aerogenic': ['aerogenic', 'recoinage'], + 'aerographer': ['aerographer', 'areographer'], + 'aerographic': ['aerographic', 'areographic'], + 'aerographical': ['aerographical', 'areographical'], + 'aerography': ['aerography', 'areography'], + 'aerologic': ['aerologic', 'areologic'], + 'aerological': ['aerological', 'areological'], + 'aerologist': ['aerologist', 'areologist'], + 'aerology': ['aerology', 'areology'], + 'aeromantic': ['aeromantic', 'cameration', 'maceration', 'racemation'], + 'aerometer': ['aerometer', 'areometer'], + 'aerometric': ['aerometric', 'areometric'], + 'aerometry': ['aerometry', 'areometry'], + 'aeronautic': ['acetonuria', 'aeronautic'], + 'aeronautism': ['aeronautism', 'measuration'], + 'aerope': ['aerope', 'operae'], + 'aerophilic': ['aerophilic', 'epichorial'], + 'aerosol': ['aerosol', 'roseola'], + 'aerostatics': ['aerostatics', 'aortectasis'], + 'aery': ['aery', 'eyra', 'yare', 'year'], + 'aes': ['aes', 'ase', 'sea'], + 'aesthetic': ['aesthetic', 'chaetites'], + 'aethalioid': ['aethalioid', 'haliotidae'], + 'aetian': ['aetian', 'antiae', 'taenia'], + 'aetobatus': ['aetobatus', 'eastabout'], + 'afebrile': ['afebrile', 'balefire', 'fireable'], + 'afenil': ['afenil', 'finale'], + 'affair': ['affair', 'raffia'], + 'affecter': ['affecter', 'reaffect'], + 'affeer': ['affeer', 'raffee'], + 'affiance': ['affiance', 'caffeina'], + 'affirmer': ['affirmer', 'reaffirm'], + 'afflicter': ['afflicter', 'reafflict'], + 'affy': ['affy', 'yaff'], + 'afghan': ['afghan', 'hafgan'], + 'afield': ['afield', 'defial'], + 'afire': ['afire', 'feria'], + 'aflare': ['aflare', 'rafael'], + 'aflat': ['aflat', 'fatal'], + 'afresh': ['afresh', 'fasher', 'ferash'], + 'afret': ['afret', 'after'], + 'afric': ['afric', 'firca'], + 'afshar': ['afshar', 'ashraf'], + 'aft': ['aft', 'fat'], + 'after': ['afret', 'after'], + 'afteract': ['afteract', 'artefact', 'farcetta', 'farctate'], + 'afterage': ['afterage', 'fregatae'], + 'afterblow': ['afterblow', 'batfowler'], + 'aftercome': ['aftercome', 'forcemeat'], + 'aftercrop': ['aftercrop', 'prefactor'], + 'aftergo': ['aftergo', 'fagoter'], + 'afterguns': ['afterguns', 'transfuge'], + 'aftermath': ['aftermath', 'hamfatter'], + 'afterstate': ['afterstate', 'aftertaste'], + 'aftertaste': ['afterstate', 'aftertaste'], + 'afunctional': ['afunctional', 'unfactional'], + 'agade': ['adage', 'agade'], + 'agal': ['agal', 'agla', 'alga', 'gala'], + 'agalite': ['agalite', 'tailage', 'taliage'], + 'agalma': ['agalma', 'malaga'], + 'agama': ['agama', 'amaga'], + 'agamid': ['agamid', 'madiga'], + 'agapeti': ['agapeti', 'agpaite'], + 'agapornis': ['agapornis', 'sporangia'], + 'agar': ['agar', 'agra', 'gara', 'raga'], + 'agaricin': ['agaricin', 'garcinia'], + 'agau': ['agau', 'agua'], + 'aged': ['aged', 'egad', 'gade'], + 'ageless': ['ageless', 'eagless'], + 'agen': ['agen', 'gaen', 'gane', 'gean', 'gena'], + 'agenesic': ['agenesic', 'genesiac'], + 'agenesis': ['agenesis', 'assignee'], + 'agential': ['agential', 'alginate'], + 'agentive': ['agentive', 'negative'], + 'ager': ['ager', 'agre', 'gare', 'gear', 'rage'], + 'agger': ['agger', 'gager', 'regga'], + 'aggeration': ['aggeration', 'agregation'], + 'aggry': ['aggry', 'raggy'], + 'agialid': ['agialid', 'galidia'], + 'agib': ['agib', 'biga', 'gabi'], + 'agiel': ['agiel', 'agile', 'galei'], + 'agile': ['agiel', 'agile', 'galei'], + 'agileness': ['agileness', 'signalese'], + 'agistment': ['agistment', 'magnetist'], + 'agistor': ['agistor', 'agrotis', 'orgiast'], + 'agla': ['agal', 'agla', 'alga', 'gala'], + 'aglaos': ['aglaos', 'salago'], + 'aglare': ['aglare', 'alegar', 'galera', 'laager'], + 'aglet': ['aglet', 'galet'], + 'agley': ['agley', 'galey'], + 'agmatine': ['agmatine', 'agminate'], + 'agminate': ['agmatine', 'agminate'], + 'agminated': ['agminated', 'diamagnet'], + 'agnail': ['agnail', 'linaga'], + 'agname': ['agname', 'manage'], + 'agnel': ['agnel', 'angel', 'angle', 'galen', 'genal', 'glean', 'lagen'], + 'agnes': ['agnes', 'gesan'], + 'agnize': ['agnize', 'ganzie'], + 'agnosis': ['agnosis', 'ganosis'], + 'agnostic': ['agnostic', 'coasting'], + 'agnus': ['agnus', 'angus', 'sugan'], + 'ago': ['ago', 'goa'], + 'agon': ['agon', 'ango', 'gaon', 'goan', 'gona'], + 'agonal': ['agonal', 'angola'], + 'agone': ['agone', 'genoa'], + 'agoniadin': ['agoniadin', 'anangioid', 'ganoidian'], + 'agonic': ['agonic', 'angico', 'gaonic', 'goniac'], + 'agonista': ['agonista', 'santiago'], + 'agonizer': ['agonizer', 'orangize', 'organize'], + 'agpaite': ['agapeti', 'agpaite'], + 'agra': ['agar', 'agra', 'gara', 'raga'], + 'agral': ['agral', 'argal'], + 'agrania': ['agrania', 'angaria', 'niagara'], + 'agre': ['ager', 'agre', 'gare', 'gear', 'rage'], + 'agree': ['agree', 'eager', 'eagre'], + 'agreed': ['agreed', 'geared'], + 'agregation': ['aggeration', 'agregation'], + 'agrege': ['agrege', 'raggee'], + 'agrestian': ['agrestian', 'gerastian', 'stangeria'], + 'agrestic': ['agrestic', 'ergastic'], + 'agria': ['agria', 'igara'], + 'agricolist': ['agricolist', 'algoristic'], + 'agrilus': ['agrilus', 'gularis'], + 'agrin': ['agrin', 'grain'], + 'agrito': ['agrito', 'ortiga'], + 'agroan': ['agroan', 'angora', 'anogra', 'arango', 'argoan', 'onagra'], + 'agrom': ['agrom', 'morga'], + 'agrotis': ['agistor', 'agrotis', 'orgiast'], + 'aground': ['aground', 'durango'], + 'agrufe': ['agrufe', 'gaufer', 'gaufre'], + 'agrypnia': ['agrypnia', 'paginary'], + 'agsam': ['agsam', 'magas'], + 'agua': ['agau', 'agua'], + 'ague': ['ague', 'auge'], + 'agush': ['agush', 'saugh'], + 'agust': ['agust', 'tsuga'], + 'agy': ['agy', 'gay'], + 'ah': ['ah', 'ha'], + 'ahem': ['ahem', 'haem', 'hame'], + 'ahet': ['ahet', 'haet', 'hate', 'heat', 'thea'], + 'ahey': ['ahey', 'eyah', 'yeah'], + 'ahind': ['ahind', 'dinah'], + 'ahint': ['ahint', 'hiant', 'tahin'], + 'ahir': ['ahir', 'hair'], + 'ahmed': ['ahmed', 'hemad'], + 'ahmet': ['ahmet', 'thema'], + 'aho': ['aho', 'hao'], + 'ahom': ['ahom', 'moha'], + 'ahong': ['ahong', 'hogan'], + 'ahorse': ['ahorse', 'ashore', 'hoarse', 'shorea'], + 'ahoy': ['ahoy', 'hoya'], + 'ahriman': ['ahriman', 'miranha'], + 'ahsan': ['ahsan', 'hansa', 'hasan'], + 'aht': ['aht', 'hat', 'tha'], + 'ahtena': ['ahtena', 'aneath', 'athena'], + 'ahu': ['ahu', 'auh', 'hau'], + 'ahum': ['ahum', 'huma'], + 'ahunt': ['ahunt', 'haunt', 'thuan', 'unhat'], + 'aid': ['aid', 'ida'], + 'aidance': ['aidance', 'canidae'], + 'aide': ['aide', 'idea'], + 'aidenn': ['aidenn', 'andine', 'dannie', 'indane'], + 'aider': ['aider', 'deair', 'irade', 'redia'], + 'aides': ['aides', 'aside', 'sadie'], + 'aiel': ['aiel', 'aile', 'elia'], + 'aiglet': ['aiglet', 'ligate', 'taigle', 'tailge'], + 'ail': ['ail', 'ila', 'lai'], + 'ailantine': ['ailantine', 'antialien'], + 'ailanto': ['ailanto', 'alation', 'laotian', 'notalia'], + 'aile': ['aiel', 'aile', 'elia'], + 'aileen': ['aileen', 'elaine'], + 'aileron': ['aileron', 'alienor'], + 'ailing': ['ailing', 'angili', 'nilgai'], + 'ailment': ['ailment', 'aliment'], + 'aim': ['aim', 'ami', 'ima'], + 'aimer': ['aimer', 'maire', 'marie', 'ramie'], + 'aimless': ['aimless', 'melissa', 'seismal'], + 'ainaleh': ['ainaleh', 'halenia'], + 'aint': ['aint', 'anti', 'tain', 'tina'], + 'aion': ['aion', 'naio'], + 'air': ['air', 'ira', 'ria'], + 'aira': ['aira', 'aria', 'raia'], + 'airan': ['airan', 'arain', 'arian'], + 'airdrome': ['airdrome', 'armoried'], + 'aire': ['aire', 'eria'], + 'airer': ['airer', 'arrie'], + 'airlike': ['airlike', 'kiliare'], + 'airman': ['airman', 'amarin', 'marian', 'marina', 'mirana'], + 'airplane': ['airplane', 'perianal'], + 'airplanist': ['airplanist', 'triplasian'], + 'airt': ['airt', 'rita', 'tari', 'tiar'], + 'airy': ['airy', 'yair'], + 'aisle': ['aisle', 'elias'], + 'aisled': ['aisled', 'deasil', 'ladies', 'sailed'], + 'aisling': ['aisling', 'sailing'], + 'aissor': ['aissor', 'rissoa'], + 'ait': ['ait', 'ati', 'ita', 'tai'], + 'aitch': ['aitch', 'chait', 'chati', 'chita', 'taich', 'tchai'], + 'aition': ['aition', 'itonia'], + 'aizle': ['aizle', 'eliza'], + 'ajar': ['ajar', 'jara', 'raja'], + 'ajhar': ['ajhar', 'rajah'], + 'ajuga': ['ajuga', 'jagua'], + 'ak': ['ak', 'ka'], + 'akal': ['akal', 'kala'], + 'akali': ['akali', 'alaki'], + 'akan': ['akan', 'kana'], + 'ake': ['ake', 'kea'], + 'akebi': ['akebi', 'bakie'], + 'akha': ['akha', 'kaha'], + 'akim': ['akim', 'maki'], + 'akin': ['akin', 'kina', 'naik'], + 'akka': ['akka', 'kaka'], + 'aknee': ['aknee', 'ankee', 'keena'], + 'ako': ['ako', 'koa', 'oak', 'oka'], + 'akoasma': ['akoasma', 'amakosa'], + 'aku': ['aku', 'auk', 'kua'], + 'al': ['al', 'la'], + 'ala': ['aal', 'ala'], + 'alacritous': ['alacritous', 'lactarious', 'lactosuria'], + 'alain': ['alain', 'alani', 'liana'], + 'alaki': ['akali', 'alaki'], + 'alalite': ['alalite', 'tillaea'], + 'alamo': ['alamo', 'aloma'], + 'alan': ['alan', 'anal', 'lana'], + 'alangin': ['alangin', 'anginal', 'anglian', 'nagnail'], + 'alangine': ['alangine', 'angelina', 'galenian'], + 'alani': ['alain', 'alani', 'liana'], + 'alanine': ['alanine', 'linnaea'], + 'alans': ['alans', 'lanas', 'nasal'], + 'alantic': ['actinal', 'alantic', 'alicant', 'antical'], + 'alantolic': ['alantolic', 'allantoic'], + 'alanyl': ['alanyl', 'anally'], + 'alares': ['alares', 'arales'], + 'alaria': ['alaria', 'aralia'], + 'alaric': ['alaric', 'racial'], + 'alarm': ['alarm', 'malar', 'maral', 'marla', 'ramal'], + 'alarmable': ['alarmable', 'ambarella'], + 'alarmedly': ['alarmedly', 'medallary'], + 'alarming': ['alarming', 'marginal'], + 'alarmingly': ['alarmingly', 'marginally'], + 'alarmist': ['alarmist', 'alastrim'], + 'alas': ['alas', 'lasa'], + 'alastair': ['alastair', 'salariat'], + 'alaster': ['alaster', 'tarsale'], + 'alastrim': ['alarmist', 'alastrim'], + 'alatern': ['alatern', 'lateran'], + 'alaternus': ['alaternus', 'saturnale'], + 'alation': ['ailanto', 'alation', 'laotian', 'notalia'], + 'alb': ['alb', 'bal', 'lab'], + 'alba': ['alba', 'baal', 'bala'], + 'alban': ['alban', 'balan', 'banal', 'laban', 'nabal', 'nabla'], + 'albanite': ['albanite', 'balanite', 'nabalite'], + 'albardine': ['albardine', 'drainable'], + 'albarium': ['albarium', 'brumalia'], + 'albata': ['albata', 'atabal', 'balata'], + 'albatros': ['abrastol', 'albatros'], + 'albe': ['abel', 'able', 'albe', 'bale', 'beal', 'bela', 'blae'], + 'albedo': ['albedo', 'doable'], + 'albee': ['abele', 'albee'], + 'albeit': ['albeit', + 'albite', + 'baltei', + 'belait', + 'betail', + 'bletia', + 'libate'], + 'albert': ['albert', 'balter', 'labret', 'tabler'], + 'alberta': ['alberta', 'latebra', 'ratable'], + 'albertina': ['albertina', 'trainable'], + 'alberto': ['alberto', 'bloater', 'latrobe'], + 'albetad': ['albetad', 'datable'], + 'albi': ['albi', 'bail', 'bali'], + 'albian': ['albian', 'bilaan'], + 'albin': ['albin', 'binal', 'blain'], + 'albino': ['albino', 'albion', 'alboin', 'oliban'], + 'albion': ['albino', 'albion', 'alboin', 'oliban'], + 'albite': ['albeit', + 'albite', + 'baltei', + 'belait', + 'betail', + 'bletia', + 'libate'], + 'alboin': ['albino', 'albion', 'alboin', 'oliban'], + 'alboranite': ['alboranite', 'rationable'], + 'albronze': ['albronze', 'blazoner'], + 'albuca': ['albuca', 'bacula'], + 'albuminate': ['albuminate', 'antelabium'], + 'alburnum': ['alburnum', 'laburnum'], + 'alcaic': ['alcaic', 'cicala'], + 'alcaide': ['alcaide', 'alcidae'], + 'alcamine': ['alcamine', 'analcime', 'calamine', 'camelina'], + 'alcantarines': ['alcantarines', 'lancasterian'], + 'alcedo': ['alcedo', 'dacelo'], + 'alces': ['alces', 'casel', 'scale'], + 'alchemic': ['alchemic', 'chemical'], + 'alchemistic': ['alchemistic', 'hemiclastic'], + 'alchera': ['alchera', 'archeal'], + 'alchitran': ['alchitran', 'clathrina'], + 'alcicornium': ['acroclinium', 'alcicornium'], + 'alcidae': ['alcaide', 'alcidae'], + 'alcidine': ['alcidine', 'danielic', 'lecaniid'], + 'alcine': ['alcine', 'ancile'], + 'alco': ['alco', 'coal', 'cola', 'loca'], + 'alcoate': ['alcoate', 'coelata'], + 'alcogel': ['alcogel', 'collage'], + 'alcor': ['alcor', 'calor', 'carlo', 'carol', 'claro', 'coral'], + 'alcoran': ['alcoran', 'ancoral', 'carolan'], + 'alcoranic': ['acronical', 'alcoranic'], + 'alcove': ['alcove', 'coeval', 'volcae'], + 'alcyon': ['alcyon', 'cyanol'], + 'alcyone': ['alcyone', 'cyanole'], + 'aldamine': ['aldamine', 'lamnidae'], + 'aldeament': ['aldeament', 'mandelate'], + 'alder': ['alder', 'daler', 'lader'], + 'aldermanry': ['aldermanry', 'marylander'], + 'aldern': ['aldern', + 'darnel', + 'enlard', + 'lander', + 'lenard', + 'randle', + 'reland'], + 'aldime': ['aldime', 'mailed', 'medial'], + 'aldine': ['aldine', 'daniel', 'delian', 'denial', 'enalid', 'leadin'], + 'aldus': ['aldus', 'sauld'], + 'ale': ['ale', 'lea'], + 'alec': ['acle', 'alec', 'lace'], + 'aleconner': ['aleconner', 'noncereal'], + 'alecost': ['alecost', 'lactose', 'scotale', 'talcose'], + 'alectoris': ['alectoris', 'sarcolite', 'sclerotia', 'sectorial'], + 'alectrion': ['alectrion', 'clarionet', 'crotaline', 'locarnite'], + 'alectryon': ['alectryon', 'tolerancy'], + 'alecup': ['alecup', 'clupea'], + 'alef': ['alef', 'feal', 'flea', 'leaf'], + 'aleft': ['aleft', 'alfet', 'fetal', 'fleta'], + 'alegar': ['aglare', 'alegar', 'galera', 'laager'], + 'alem': ['alem', 'alme', 'lame', 'leam', 'male', 'meal', 'mela'], + 'alemanni': ['alemanni', 'melanian'], + 'alemite': ['alemite', 'elamite'], + 'alen': ['alen', 'lane', 'lean', 'lena', 'nael', 'neal'], + 'aleph': ['aleph', 'pheal'], + 'alepot': ['alepot', 'pelota'], + 'alerce': ['alerce', 'cereal', 'relace'], + 'alerse': ['alerse', 'leaser', 'reales', 'resale', 'reseal', 'sealer'], + 'alert': ['alert', 'alter', 'artel', 'later', 'ratel', 'taler', 'telar'], + 'alertly': ['alertly', 'elytral'], + 'alestake': ['alestake', 'eastlake'], + 'aletap': ['aletap', 'palate', 'platea'], + 'aletris': ['aletris', 'alister', 'listera', 'realist', 'saltier'], + 'aleuronic': ['aleuronic', 'urceolina'], + 'aleut': ['aleut', 'atule'], + 'aleutic': ['aleutic', 'auletic', 'caulite', 'lutecia'], + 'alevin': ['alevin', 'alvine', 'valine', 'veinal', 'venial', 'vineal'], + 'alex': ['alex', 'axel', 'axle'], + 'alexandrian': ['alexandrian', 'alexandrina'], + 'alexandrina': ['alexandrian', 'alexandrina'], + 'alexin': ['alexin', 'xenial'], + 'aleyard': ['aleyard', 'already'], + 'alfenide': ['alfenide', 'enfilade'], + 'alfet': ['aleft', 'alfet', 'fetal', 'fleta'], + 'alfred': ['alfred', 'fardel'], + 'alfur': ['alfur', 'fural'], + 'alga': ['agal', 'agla', 'alga', 'gala'], + 'algae': ['algae', 'galea'], + 'algal': ['algal', 'galla'], + 'algebar': ['algebar', 'algebra'], + 'algebra': ['algebar', 'algebra'], + 'algedi': ['algedi', 'galeid'], + 'algedo': ['algedo', 'geodal'], + 'algedonic': ['algedonic', 'genocidal'], + 'algenib': ['algenib', 'bealing', 'belgian', 'bengali'], + 'algerian': ['algerian', 'geranial', 'regalian'], + 'algernon': ['algernon', 'nonglare'], + 'algesia': ['algesia', 'sailage'], + 'algesis': ['algesis', 'glassie'], + 'algieba': ['algieba', 'bailage'], + 'algin': ['algin', 'align', 'langi', 'liang', 'linga'], + 'alginate': ['agential', 'alginate'], + 'algine': ['algine', 'genial', 'linage'], + 'algist': ['algist', 'gaslit'], + 'algometer': ['algometer', 'glomerate'], + 'algometric': ['algometric', 'melotragic'], + 'algomian': ['algomian', 'magnolia'], + 'algor': ['algor', 'argol', 'goral', 'largo'], + 'algoristic': ['agricolist', 'algoristic'], + 'algorithm': ['algorithm', 'logarithm'], + 'algorithmic': ['algorithmic', 'logarithmic'], + 'algraphic': ['algraphic', 'graphical'], + 'algum': ['algum', 'almug', 'glaum', 'gluma', 'mulga'], + 'alibility': ['alibility', 'liability'], + 'alible': ['alible', 'belial', 'labile', 'liable'], + 'alicant': ['actinal', 'alantic', 'alicant', 'antical'], + 'alice': ['alice', 'celia', 'ileac'], + 'alichel': ['alichel', 'challie', 'helical'], + 'alida': ['adlai', 'alida'], + 'alien': ['alien', 'aline', 'anile', 'elain', 'elian', 'laine', 'linea'], + 'alienation': ['alienation', 'alineation'], + 'alienator': ['alienator', 'rationale'], + 'alienism': ['alienism', 'milesian'], + 'alienor': ['aileron', 'alienor'], + 'alif': ['alif', 'fail'], + 'aligerous': ['aligerous', 'glaireous'], + 'align': ['algin', 'align', 'langi', 'liang', 'linga'], + 'aligner': ['aligner', 'engrail', 'realign', 'reginal'], + 'alignment': ['alignment', 'lamenting'], + 'alike': ['alike', 'lakie'], + 'alikeness': ['alikeness', 'leakiness'], + 'alima': ['alima', 'lamia'], + 'aliment': ['ailment', 'aliment'], + 'alimenter': ['alimenter', 'marteline'], + 'alimentic': ['alimentic', 'antilemic', 'melanitic', 'metanilic'], + 'alimonied': ['alimonied', 'maleinoid'], + 'alin': ['alin', 'anil', 'lain', 'lina', 'nail'], + 'aline': ['alien', 'aline', 'anile', 'elain', 'elian', 'laine', 'linea'], + 'alineation': ['alienation', 'alineation'], + 'aliped': ['aliped', 'elapid'], + 'aliptes': ['aliptes', 'pastile', 'talipes'], + 'aliptic': ['aliptic', 'aplitic'], + 'aliseptal': ['aliseptal', 'pallasite'], + 'alish': ['alish', 'hilsa'], + 'alisier': ['alisier', 'israeli'], + 'aliso': ['aliso', 'alois'], + 'alison': ['alison', 'anolis'], + 'alisp': ['alisp', 'lapsi'], + 'alist': ['alist', 'litas', 'slait', 'talis'], + 'alister': ['aletris', 'alister', 'listera', 'realist', 'saltier'], + 'alit': ['alit', 'tail', 'tali'], + 'alite': ['alite', 'laeti'], + 'aliunde': ['aliunde', 'unideal'], + 'aliveness': ['aliveness', 'vealiness'], + 'alix': ['alix', 'axil'], + 'alk': ['alk', 'lak'], + 'alkalizer': ['alkalizer', 'lazarlike'], + 'alkamin': ['alkamin', 'malakin'], + 'alkene': ['alkene', 'lekane'], + 'alkes': ['alkes', 'sakel', 'slake'], + 'alkine': ['alkine', 'ilkane', 'inlake', 'inleak'], + 'alky': ['alky', 'laky'], + 'alkylic': ['alkylic', 'lilacky'], + 'allagite': ['allagite', 'alligate', 'talliage'], + 'allah': ['allah', 'halal'], + 'allantoic': ['alantolic', 'allantoic'], + 'allay': ['allay', 'yalla'], + 'allayer': ['allayer', 'yallaer'], + 'allbone': ['allbone', 'bellona'], + 'alle': ['alle', 'ella', 'leal'], + 'allecret': ['allecret', 'cellaret'], + 'allegate': ['allegate', 'ellagate'], + 'allegorist': ['allegorist', 'legislator'], + 'allergen': ['allergen', 'generall'], + 'allergia': ['allergia', 'galleria'], + 'allergin': ['allergin', 'gralline'], + 'allergy': ['allergy', 'gallery', 'largely', 'regally'], + 'alliable': ['alliable', 'labiella'], + 'alliably': ['alliably', 'labially'], + 'alliance': ['alliance', 'canaille'], + 'alliancer': ['alliancer', 'ralliance'], + 'allie': ['allie', 'leila', 'lelia'], + 'allies': ['allies', 'aselli'], + 'alligate': ['allagite', 'alligate', 'talliage'], + 'allium': ['allium', 'alulim', 'muilla'], + 'allocation': ['allocation', 'locational'], + 'allocute': ['allocute', 'loculate'], + 'allocution': ['allocution', 'loculation'], + 'allogenic': ['allogenic', 'collegian'], + 'allonym': ['allonym', 'malonyl'], + 'allopathy': ['allopathy', 'lalopathy'], + 'allopatric': ['allopatric', 'patrilocal'], + 'allot': ['allot', 'atoll'], + 'allothogenic': ['allothogenic', 'ethnological'], + 'allover': ['allover', 'overall'], + 'allower': ['allower', 'reallow'], + 'alloy': ['alloy', 'loyal'], + 'allude': ['allude', 'aludel'], + 'allure': ['allure', 'laurel'], + 'alma': ['alma', 'amla', 'lama', 'mala'], + 'almach': ['almach', 'chamal'], + 'almaciga': ['almaciga', 'macaglia'], + 'almain': ['almain', 'animal', 'lamina', 'manila'], + 'alman': ['alman', 'lamna', 'manal'], + 'almandite': ['almandite', 'laminated'], + 'alme': ['alem', 'alme', 'lame', 'leam', 'male', 'meal', 'mela'], + 'almerian': ['almerian', 'manerial'], + 'almoign': ['almoign', 'loaming'], + 'almon': ['almon', 'monal'], + 'almond': ['almond', 'dolman'], + 'almoner': ['almoner', 'moneral', 'nemoral'], + 'almonry': ['almonry', 'romanly'], + 'alms': ['alms', 'salm', 'slam'], + 'almuce': ['almuce', 'caelum', 'macule'], + 'almude': ['almude', 'maudle'], + 'almug': ['algum', 'almug', 'glaum', 'gluma', 'mulga'], + 'almuten': ['almuten', 'emulant'], + 'aln': ['aln', 'lan'], + 'alnage': ['alnage', 'angela', 'galena', 'lagena'], + 'alnico': ['alnico', 'cliona', 'oilcan'], + 'alnilam': ['alnilam', 'manilla'], + 'alnoite': ['alnoite', 'elation', 'toenail'], + 'alnuin': ['alnuin', 'unnail'], + 'alo': ['alo', 'lao', 'loa'], + 'alochia': ['acholia', 'alochia'], + 'alod': ['alod', 'dola', 'load', 'odal'], + 'aloe': ['aloe', 'olea'], + 'aloetic': ['aloetic', 'coalite'], + 'aloft': ['aloft', 'float', 'flota'], + 'alogian': ['alogian', 'logania'], + 'alogical': ['alogical', 'colalgia'], + 'aloid': ['aloid', 'dolia', 'idola'], + 'aloin': ['aloin', 'anoil', 'anoli'], + 'alois': ['aliso', 'alois'], + 'aloma': ['alamo', 'aloma'], + 'alone': ['alone', 'anole', 'olena'], + 'along': ['along', 'gonal', 'lango', 'longa', 'nogal'], + 'alonso': ['alonso', 'alsoon', 'saloon'], + 'alonzo': ['alonzo', 'zoonal'], + 'alop': ['alop', 'opal'], + 'alopecist': ['alopecist', 'altiscope', 'epicostal', 'scapolite'], + 'alosa': ['alosa', 'loasa', 'oasal'], + 'alose': ['alose', 'osela', 'solea'], + 'alow': ['alow', 'awol', 'lowa'], + 'aloxite': ['aloxite', 'oxalite'], + 'alp': ['alp', 'lap', 'pal'], + 'alpeen': ['alpeen', 'lenape', 'pelean'], + 'alpen': ['alpen', 'nepal', 'panel', 'penal', 'plane'], + 'alpestral': ['alpestral', 'palestral'], + 'alpestrian': ['alpestrian', 'palestrian', 'psalterian'], + 'alpestrine': ['alpestrine', 'episternal', 'interlapse', 'presential'], + 'alphenic': ['alphenic', 'cephalin'], + 'alphonse': ['alphonse', 'phenosal'], + 'alphos': ['alphos', 'pholas'], + 'alphosis': ['alphosis', 'haplosis'], + 'alpid': ['alpid', 'plaid'], + 'alpieu': ['alpieu', 'paulie'], + 'alpine': ['alpine', 'nepali', 'penial', 'pineal'], + 'alpinist': ['alpinist', 'antislip'], + 'alpist': ['alpist', 'pastil', 'spital'], + 'alraun': ['alraun', 'alruna', 'ranula'], + 'already': ['aleyard', 'already'], + 'alrighty': ['alrighty', 'arightly'], + 'alruna': ['alraun', 'alruna', 'ranula'], + 'alsine': ['alsine', 'neslia', 'saline', 'selina', 'silane'], + 'also': ['also', 'sola'], + 'alsoon': ['alonso', 'alsoon', 'saloon'], + 'alstonidine': ['alstonidine', 'nonidealist'], + 'alstonine': ['alstonine', 'tensional'], + 'alt': ['alt', 'lat', 'tal'], + 'altaian': ['altaian', 'latania', 'natalia'], + 'altaic': ['altaic', 'altica'], + 'altaid': ['adital', 'altaid'], + 'altair': ['altair', 'atrail', 'atrial', 'lariat', 'latria', 'talari'], + 'altamira': ['altamira', 'matralia'], + 'altar': ['altar', 'artal', 'ratal', 'talar'], + 'altared': ['altared', 'laterad'], + 'altarist': ['altarist', 'striatal'], + 'alter': ['alert', 'alter', 'artel', 'later', 'ratel', 'taler', 'telar'], + 'alterability': ['alterability', 'bilaterality', 'relatability'], + 'alterable': ['alterable', 'relatable'], + 'alterant': ['alterant', 'tarletan'], + 'alterer': ['alterer', 'realter', 'relater'], + 'altern': ['altern', 'antler', 'learnt', 'rental', 'ternal'], + 'alterne': ['alterne', 'enteral', 'eternal', 'teleran', 'teneral'], + 'althea': ['althea', 'elatha'], + 'altho': ['altho', 'lhota', 'loath'], + 'althorn': ['althorn', 'anthrol', 'thronal'], + 'altica': ['altaic', 'altica'], + 'altin': ['altin', 'latin'], + 'altiscope': ['alopecist', 'altiscope', 'epicostal', 'scapolite'], + 'altitude': ['altitude', 'latitude'], + 'altitudinal': ['altitudinal', 'latitudinal'], + 'altitudinarian': ['altitudinarian', 'latitudinarian'], + 'alto': ['alto', 'lota'], + 'altrices': ['altrices', 'selictar'], + 'altruism': ['altruism', 'muralist', 'traulism', 'ultraism'], + 'altruist': ['altruist', 'ultraist'], + 'altruistic': ['altruistic', 'truistical', 'ultraistic'], + 'aludel': ['allude', 'aludel'], + 'aludra': ['adular', 'aludra', 'radula'], + 'alulet': ['alulet', 'luteal'], + 'alulim': ['allium', 'alulim', 'muilla'], + 'alum': ['alum', 'maul'], + 'aluminate': ['aluminate', 'alumniate'], + 'aluminide': ['aluminide', 'unimedial'], + 'aluminosilicate': ['aluminosilicate', 'silicoaluminate'], + 'alumna': ['alumna', 'manual'], + 'alumni': ['alumni', 'unmail'], + 'alumniate': ['aluminate', 'alumniate'], + 'alur': ['alur', 'laur', 'lura', 'raul', 'ural'], + 'alure': ['alure', 'ureal'], + 'alurgite': ['alurgite', 'ligature'], + 'aluta': ['aluta', 'taula'], + 'alvan': ['alvan', 'naval'], + 'alvar': ['alvar', 'arval', 'larva'], + 'alveus': ['alveus', 'avulse'], + 'alvin': ['alvin', 'anvil', 'nival', 'vinal'], + 'alvine': ['alevin', 'alvine', 'valine', 'veinal', 'venial', 'vineal'], + 'aly': ['aly', 'lay'], + 'alypin': ['alypin', 'pialyn'], + 'alytes': ['alytes', 'astely', 'lysate', 'stealy'], + 'am': ['am', 'ma'], + 'ama': ['aam', 'ama'], + 'amacrine': ['amacrine', 'american', 'camerina', 'cinerama'], + 'amadi': ['amadi', 'damia', 'madia', 'maida'], + 'amaethon': ['amaethon', 'thomaean'], + 'amaga': ['agama', 'amaga'], + 'amah': ['amah', 'maha'], + 'amain': ['amain', 'amani', 'amnia', 'anima', 'mania'], + 'amakosa': ['akoasma', 'amakosa'], + 'amalgam': ['amalgam', 'malagma'], + 'amang': ['amang', 'ganam', 'manga'], + 'amani': ['amain', 'amani', 'amnia', 'anima', 'mania'], + 'amanist': ['amanist', 'stamina'], + 'amanitin': ['amanitin', 'maintain'], + 'amanitine': ['amanitine', 'inanimate'], + 'amanori': ['amanori', 'moarian'], + 'amapa': ['amapa', 'apama'], + 'amar': ['amar', 'amra', 'mara', 'rama'], + 'amarin': ['airman', 'amarin', 'marian', 'marina', 'mirana'], + 'amaroid': ['amaroid', 'diorama'], + 'amarth': ['amarth', 'martha'], + 'amass': ['amass', 'assam', 'massa', 'samas'], + 'amasser': ['amasser', 'reamass'], + 'amati': ['amati', 'amita', 'matai'], + 'amatorian': ['amatorian', 'inamorata'], + 'amaurosis': ['amaurosis', 'mosasauri'], + 'amazonite': ['amazonite', 'anatomize'], + 'amba': ['amba', 'maba'], + 'ambar': ['abram', 'ambar'], + 'ambarella': ['alarmable', 'ambarella'], + 'ambash': ['ambash', 'shamba'], + 'ambay': ['ambay', 'mbaya'], + 'ambeer': ['ambeer', 'beamer'], + 'amber': ['amber', 'bearm', 'bemar', 'bream', 'embar'], + 'ambier': ['ambier', 'bremia', 'embira'], + 'ambit': ['ambit', 'imbat'], + 'ambivert': ['ambivert', 'verbatim'], + 'amble': ['amble', 'belam', 'blame', 'mabel'], + 'ambler': ['ambler', 'blamer', 'lamber', 'marble', 'ramble'], + 'ambling': ['ambling', 'blaming'], + 'amblingly': ['amblingly', 'blamingly'], + 'ambo': ['ambo', 'boma'], + 'ambos': ['ambos', 'sambo'], + 'ambrein': ['ambrein', 'mirbane'], + 'ambrette': ['ambrette', 'tambreet'], + 'ambrose': ['ambrose', 'mesobar'], + 'ambrosia': ['ambrosia', 'saboraim'], + 'ambrosin': ['ambrosin', 'barosmin', 'sabromin'], + 'ambry': ['ambry', 'barmy'], + 'ambury': ['ambury', 'aumbry'], + 'ambush': ['ambush', 'shambu'], + 'amchoor': ['amchoor', 'ochroma'], + 'ame': ['ame', 'mae'], + 'ameed': ['adeem', 'ameed', 'edema'], + 'ameen': ['ameen', 'amene', 'enema'], + 'amelification': ['amelification', 'maleficiation'], + 'ameliorant': ['ameliorant', 'lomentaria'], + 'amellus': ['amellus', 'malleus'], + 'amelu': ['amelu', 'leuma', 'ulema'], + 'amelus': ['amelus', 'samuel'], + 'amen': ['amen', 'enam', 'mane', 'mean', 'name', 'nema'], + 'amenability': ['amenability', 'nameability'], + 'amenable': ['amenable', 'nameable'], + 'amend': ['amend', 'mande', 'maned'], + 'amende': ['amende', 'demean', 'meaned', 'nadeem'], + 'amender': ['amender', 'meander', 'reamend', 'reedman'], + 'amends': ['amends', 'desman'], + 'amene': ['ameen', 'amene', 'enema'], + 'amenia': ['amenia', 'anemia'], + 'amenism': ['amenism', 'immanes', 'misname'], + 'amenite': ['amenite', 'etamine', 'matinee'], + 'amenorrheal': ['amenorrheal', 'melanorrhea'], + 'ament': ['ament', 'meant', 'teman'], + 'amental': ['amental', 'leatman'], + 'amentia': ['amentia', 'aminate', 'anamite', 'animate'], + 'amerce': ['amerce', 'raceme'], + 'amercer': ['amercer', 'creamer'], + 'american': ['amacrine', 'american', 'camerina', 'cinerama'], + 'amerind': ['adermin', 'amerind', 'dimeran'], + 'amerism': ['amerism', 'asimmer', 'sammier'], + 'ameristic': ['ameristic', 'armistice', 'artemisic'], + 'amesite': ['amesite', 'mesitae', 'semitae'], + 'ametria': ['ametria', 'artemia', 'meratia', 'ramaite'], + 'ametrope': ['ametrope', 'metapore'], + 'amex': ['amex', 'exam', 'xema'], + 'amgarn': ['amgarn', 'mangar', 'marang', 'ragman'], + 'amhar': ['amhar', 'mahar', 'mahra'], + 'amherstite': ['amherstite', 'hemistater'], + 'amhran': ['amhran', 'harman', 'mahran'], + 'ami': ['aim', 'ami', 'ima'], + 'amia': ['amia', 'maia'], + 'amic': ['amic', 'mica'], + 'amical': ['amical', 'camail', 'lamaic'], + 'amiced': ['amiced', 'decima'], + 'amicicide': ['amicicide', 'cimicidae'], + 'amicron': ['amicron', 'marconi', 'minorca', 'romanic'], + 'amid': ['admi', 'amid', 'madi', 'maid'], + 'amidate': ['adamite', 'amidate'], + 'amide': ['amide', 'damie', 'media'], + 'amidide': ['amidide', 'diamide', 'mididae'], + 'amidin': ['amidin', 'damnii'], + 'amidine': ['amidine', 'diamine'], + 'amidism': ['amidism', 'maidism'], + 'amidist': ['amidist', 'dimatis'], + 'amidon': ['amidon', 'daimon', 'domain'], + 'amidophenol': ['amidophenol', 'monodelphia'], + 'amidst': ['amidst', 'datism'], + 'amigo': ['amigo', 'imago'], + 'amiidae': ['amiidae', 'maiidae'], + 'amil': ['amil', 'amli', 'lima', 'mail', 'mali', 'mila'], + 'amiles': ['amiles', 'asmile', 'mesail', 'mesial', 'samiel'], + 'amimia': ['amimia', 'miamia'], + 'amimide': ['amimide', 'mimidae'], + 'amin': ['amin', 'main', 'mani', 'mian', 'mina', 'naim'], + 'aminate': ['amentia', 'aminate', 'anamite', 'animate'], + 'amination': ['amination', 'animation'], + 'amine': ['amine', 'anime', 'maine', 'manei'], + 'amini': ['amini', 'animi'], + 'aminize': ['aminize', 'animize', 'azimine'], + 'amino': ['amino', 'inoma', 'naomi', 'omani', 'omina'], + 'aminoplast': ['aminoplast', 'plasmation'], + 'amintor': ['amintor', 'tormina'], + 'amir': ['amir', 'irma', 'mari', 'mira', 'rami', 'rima'], + 'amiranha': ['amiranha', 'maharani'], + 'amiray': ['amiray', 'myaria'], + 'amissness': ['amissness', 'massiness'], + 'amita': ['amati', 'amita', 'matai'], + 'amitosis': ['amitosis', 'omasitis'], + 'amixia': ['amixia', 'ixiama'], + 'amla': ['alma', 'amla', 'lama', 'mala'], + 'amli': ['amil', 'amli', 'lima', 'mail', 'mali', 'mila'], + 'amlong': ['amlong', 'logman'], + 'amma': ['amma', 'maam'], + 'ammelin': ['ammelin', 'limeman'], + 'ammeline': ['ammeline', 'melamine'], + 'ammeter': ['ammeter', 'metamer'], + 'ammi': ['ammi', 'imam', 'maim', 'mima'], + 'ammine': ['ammine', 'immane'], + 'ammo': ['ammo', 'mamo'], + 'ammonic': ['ammonic', 'mocmain'], + 'ammonolytic': ['ammonolytic', 'commonality'], + 'ammunition': ['ammunition', 'antimonium'], + 'amnestic': ['amnestic', 'semantic'], + 'amnia': ['amain', 'amani', 'amnia', 'anima', 'mania'], + 'amniac': ['amniac', 'caiman', 'maniac'], + 'amnic': ['amnic', 'manic'], + 'amnion': ['amnion', 'minoan', 'nomina'], + 'amnionata': ['amnionata', 'anamniota'], + 'amnionate': ['amnionate', 'anamniote', 'emanation'], + 'amniota': ['amniota', 'itonama'], + 'amniote': ['amniote', 'anomite'], + 'amniotic': ['amniotic', 'mication'], + 'amniotome': ['amniotome', 'momotinae'], + 'amok': ['amok', 'mako'], + 'amole': ['amole', 'maleo'], + 'amomis': ['amomis', 'mimosa'], + 'among': ['among', 'mango'], + 'amor': ['amor', 'maro', 'mora', 'omar', 'roam'], + 'amores': ['amores', 'ramose', 'sorema'], + 'amoret': ['amoret', 'morate'], + 'amorist': ['amorist', 'aortism', 'miastor'], + 'amoritic': ['amoritic', 'microtia'], + 'amorpha': ['amorpha', 'amphora'], + 'amorphic': ['amorphic', 'amphoric'], + 'amorphous': ['amorphous', 'amphorous'], + 'amort': ['amort', 'morat', 'torma'], + 'amortize': ['amortize', 'atomizer'], + 'amos': ['amos', 'soam', 'soma'], + 'amotion': ['amotion', 'otomian'], + 'amount': ['amount', 'moutan', 'outman'], + 'amoy': ['amoy', 'mayo'], + 'ampelis': ['ampelis', 'lepisma'], + 'ampelite': ['ampelite', 'pimelate'], + 'ampelitic': ['ampelitic', 'implicate'], + 'amper': ['amper', 'remap'], + 'amperemeter': ['amperemeter', 'permeameter'], + 'amperian': ['amperian', 'paramine', 'pearmain'], + 'amphicyon': ['amphicyon', 'hypomanic'], + 'amphigenous': ['amphigenous', 'musophagine'], + 'amphiphloic': ['amphiphloic', 'amphophilic'], + 'amphipodous': ['amphipodous', 'hippodamous'], + 'amphitropous': ['amphitropous', 'pastophorium'], + 'amphophilic': ['amphiphloic', 'amphophilic'], + 'amphora': ['amorpha', 'amphora'], + 'amphore': ['amphore', 'morphea'], + 'amphorette': ['amphorette', 'haptometer'], + 'amphoric': ['amorphic', 'amphoric'], + 'amphorous': ['amorphous', 'amphorous'], + 'amphoteric': ['amphoteric', 'metaphoric'], + 'ample': ['ample', 'maple'], + 'ampliate': ['ampliate', 'palamite'], + 'amplification': ['amplification', 'palmification'], + 'amply': ['amply', 'palmy'], + 'ampul': ['ampul', 'pluma'], + 'ampulla': ['ampulla', 'palmula'], + 'amra': ['amar', 'amra', 'mara', 'rama'], + 'amsath': ['amsath', 'asthma'], + 'amsel': ['amsel', 'melas', 'mesal', 'samel'], + 'amsonia': ['amsonia', 'anosmia'], + 'amt': ['amt', 'mat', 'tam'], + 'amulet': ['amulet', 'muleta'], + 'amunam': ['amunam', 'manuma'], + 'amuse': ['amuse', 'mesua'], + 'amused': ['amused', 'masdeu', 'medusa'], + 'amusee': ['amusee', 'saeume'], + 'amuser': ['amuser', 'mauser'], + 'amusgo': ['amusgo', 'sugamo'], + 'amvis': ['amvis', 'mavis'], + 'amy': ['amy', 'may', 'mya', 'yam'], + 'amyelic': ['amyelic', 'mycelia'], + 'amyl': ['amyl', 'lyam', 'myal'], + 'amylan': ['amylan', 'lamany', 'layman'], + 'amylenol': ['amylenol', 'myelonal'], + 'amylidene': ['amylidene', 'mydaleine'], + 'amylin': ['amylin', 'mainly'], + 'amylo': ['amylo', 'loamy'], + 'amylon': ['amylon', 'onymal'], + 'amyotrophy': ['amyotrophy', 'myoatrophy'], + 'amyrol': ['amyrol', 'molary'], + 'an': ['an', 'na'], + 'ana': ['ana', 'naa'], + 'anacara': ['anacara', 'aracana'], + 'anacard': ['anacard', 'caranda'], + 'anaces': ['anaces', 'scaean'], + 'anachorism': ['anachorism', 'chorasmian', 'maraschino'], + 'anacid': ['acnida', 'anacid', 'dacian'], + 'anacreontic': ['anacreontic', 'canceration'], + 'anacusis': ['anacusis', 'ascanius'], + 'anadem': ['anadem', 'maenad'], + 'anadenia': ['anadenia', 'danainae'], + 'anadrom': ['anadrom', 'madrona', 'mandora', 'monarda', 'roadman'], + 'anaemic': ['acnemia', 'anaemic'], + 'anaeretic': ['anaeretic', 'ecarinate'], + 'anal': ['alan', 'anal', 'lana'], + 'analcime': ['alcamine', 'analcime', 'calamine', 'camelina'], + 'analcite': ['analcite', 'anticlea', 'laitance'], + 'analcitite': ['analcitite', 'catalinite'], + 'analectic': ['acclinate', 'analectic'], + 'analeptical': ['analeptical', 'placentalia'], + 'anally': ['alanyl', 'anally'], + 'analogic': ['analogic', 'calinago'], + 'analogist': ['analogist', 'nostalgia'], + 'anam': ['anam', 'mana', 'naam', 'nama'], + 'anamesite': ['anamesite', 'seamanite'], + 'anamirta': ['anamirta', 'araminta'], + 'anamite': ['amentia', 'aminate', 'anamite', 'animate'], + 'anamniota': ['amnionata', 'anamniota'], + 'anamniote': ['amnionate', 'anamniote', 'emanation'], + 'anan': ['anan', 'anna', 'nana'], + 'ananda': ['ananda', 'danaan'], + 'anandria': ['anandria', 'andriana'], + 'anangioid': ['agoniadin', 'anangioid', 'ganoidian'], + 'ananism': ['ananism', 'samnani'], + 'ananite': ['ananite', 'anatine', 'taenian'], + 'anaphoric': ['anaphoric', 'pharaonic'], + 'anaphorical': ['anaphorical', 'pharaonical'], + 'anapnea': ['anapnea', 'napaean'], + 'anapsid': ['anapsid', 'sapinda'], + 'anapsida': ['anapsida', 'anaspida'], + 'anaptotic': ['anaptotic', 'captation'], + 'anarchic': ['anarchic', 'characin'], + 'anarchism': ['anarchism', 'arachnism'], + 'anarchist': ['anarchist', 'archsaint', 'cantharis'], + 'anarcotin': ['anarcotin', 'cantorian', 'carnation', 'narcotina'], + 'anaretic': ['anaretic', 'arcanite', 'carinate', 'craniate'], + 'anarthropod': ['anarthropod', 'arthropodan'], + 'anas': ['anas', 'ansa', 'saan'], + 'anasa': ['anasa', 'asana'], + 'anaspida': ['anapsida', 'anaspida'], + 'anastaltic': ['anastaltic', 'catalanist'], + 'anat': ['anat', 'anta', 'tana'], + 'anatidae': ['anatidae', 'taeniada'], + 'anatine': ['ananite', 'anatine', 'taenian'], + 'anatocism': ['anatocism', 'anosmatic'], + 'anatole': ['anatole', 'notaeal'], + 'anatolic': ['aconital', 'actional', 'anatolic'], + 'anatomicopathologic': ['anatomicopathologic', 'pathologicoanatomic'], + 'anatomicopathological': ['anatomicopathological', 'pathologicoanatomical'], + 'anatomicophysiologic': ['anatomicophysiologic', 'physiologicoanatomic'], + 'anatomism': ['anatomism', 'nomismata'], + 'anatomize': ['amazonite', 'anatomize'], + 'anatum': ['anatum', 'mantua', 'tamanu'], + 'anay': ['anay', 'yana'], + 'anba': ['anba', 'bana'], + 'ancestor': ['ancestor', 'entosarc'], + 'ancestral': ['ancestral', 'lancaster'], + 'anchat': ['acanth', 'anchat', 'tanach'], + 'anchietin': ['anchietin', 'cathinine'], + 'anchistea': ['anchistea', 'hanseatic'], + 'anchor': ['anchor', 'archon', 'charon', 'rancho'], + 'anchored': ['anchored', 'rondache'], + 'anchorer': ['anchorer', 'ranchero', 'reanchor'], + 'anchoretic': ['acherontic', 'anchoretic'], + 'anchoretical': ['acherontical', 'anchoretical'], + 'anchoretism': ['anchoretism', 'trichomanes'], + 'anchorite': ['anchorite', 'antechoir', 'heatronic', 'hectorian'], + 'anchoritism': ['anchoritism', 'chiromantis', 'chrismation', 'harmonistic'], + 'ancile': ['alcine', 'ancile'], + 'ancilla': ['aclinal', 'ancilla'], + 'ancillary': ['ancillary', 'carlylian', 'cranially'], + 'ancon': ['ancon', 'canon'], + 'anconitis': ['anconitis', 'antiscion', 'onanistic'], + 'ancony': ['ancony', 'canyon'], + 'ancoral': ['alcoran', 'ancoral', 'carolan'], + 'ancylus': ['ancylus', 'unscaly'], + 'ancyrene': ['ancyrene', 'cerynean'], + 'and': ['and', 'dan'], + 'anda': ['anda', 'dana'], + 'andante': ['andante', 'dantean'], + 'ande': ['ande', 'dane', 'dean', 'edna'], + 'andesitic': ['andesitic', 'dianetics'], + 'andhra': ['andhra', 'dharna'], + 'andi': ['adin', 'andi', 'dain', 'dani', 'dian', 'naid'], + 'andian': ['andian', 'danian', 'nidana'], + 'andine': ['aidenn', 'andine', 'dannie', 'indane'], + 'andira': ['adrian', 'andira', 'andria', 'radian', 'randia'], + 'andorite': ['andorite', 'nadorite', 'ordinate', 'rodentia'], + 'andre': ['andre', 'arend', 'daren', 'redan'], + 'andrew': ['andrew', 'redawn', 'wander', 'warden'], + 'andria': ['adrian', 'andira', 'andria', 'radian', 'randia'], + 'andriana': ['anandria', 'andriana'], + 'andrias': ['andrias', 'sardian', 'sarinda'], + 'andric': ['andric', 'cardin', 'rancid'], + 'andries': ['andries', 'isander', 'sardine'], + 'androgynus': ['androgynus', 'gynandrous'], + 'androl': ['androl', 'arnold', 'lardon', 'roland', 'ronald'], + 'andronicus': ['andronicus', 'unsardonic'], + 'androtomy': ['androtomy', 'dynamotor'], + 'anear': ['anear', 'arean', 'arena'], + 'aneath': ['ahtena', 'aneath', 'athena'], + 'anecdota': ['anecdota', 'coadnate'], + 'anele': ['anele', 'elean'], + 'anematosis': ['anematosis', 'menostasia'], + 'anemia': ['amenia', 'anemia'], + 'anemic': ['anemic', 'cinema', 'iceman'], + 'anemograph': ['anemograph', 'phanerogam'], + 'anemographic': ['anemographic', 'phanerogamic'], + 'anemography': ['anemography', 'phanerogamy'], + 'anemone': ['anemone', 'monaene'], + 'anent': ['anent', 'annet', 'nenta'], + 'anepia': ['anepia', 'apinae'], + 'aneretic': ['aneretic', 'centiare', 'creatine', 'increate', 'iterance'], + 'anergic': ['anergic', 'garnice', 'garniec', 'geranic', 'grecian'], + 'anergy': ['anergy', 'rangey'], + 'anerly': ['anerly', 'nearly'], + 'aneroid': ['aneroid', 'arenoid'], + 'anerotic': ['actioner', 'anerotic', 'ceration', 'creation', 'reaction'], + 'anes': ['anes', 'sane', 'sean'], + 'anesis': ['anesis', 'anseis', 'sanies', 'sansei', 'sasine'], + 'aneuric': ['aneuric', 'rinceau'], + 'aneurin': ['aneurin', 'uranine'], + 'aneurism': ['aneurism', 'arsenium', 'sumerian'], + 'anew': ['anew', 'wane', 'wean'], + 'angami': ['angami', 'magani', 'magian'], + 'angara': ['angara', 'aranga', 'nagara'], + 'angaria': ['agrania', 'angaria', 'niagara'], + 'angel': ['agnel', 'angel', 'angle', 'galen', 'genal', 'glean', 'lagen'], + 'angela': ['alnage', 'angela', 'galena', 'lagena'], + 'angeldom': ['angeldom', 'lodgeman'], + 'angelet': ['angelet', 'elegant'], + 'angelic': ['angelic', 'galenic'], + 'angelical': ['angelical', 'englacial', 'galenical'], + 'angelically': ['angelically', 'englacially'], + 'angelin': ['angelin', 'leaning'], + 'angelina': ['alangine', 'angelina', 'galenian'], + 'angelique': ['angelique', 'equiangle'], + 'angelo': ['angelo', 'engaol'], + 'angelot': ['angelot', 'tangelo'], + 'anger': ['anger', 'areng', 'grane', 'range'], + 'angerly': ['angerly', 'geranyl'], + 'angers': ['angers', 'sanger', 'serang'], + 'angico': ['agonic', 'angico', 'gaonic', 'goniac'], + 'angie': ['angie', 'gaine'], + 'angild': ['angild', 'lading'], + 'angili': ['ailing', 'angili', 'nilgai'], + 'angina': ['angina', 'inanga'], + 'anginal': ['alangin', 'anginal', 'anglian', 'nagnail'], + 'angiocholitis': ['angiocholitis', 'cholangioitis'], + 'angiochondroma': ['angiochondroma', 'chondroangioma'], + 'angiofibroma': ['angiofibroma', 'fibroangioma'], + 'angioid': ['angioid', 'gonidia'], + 'angiokeratoma': ['angiokeratoma', 'keratoangioma'], + 'angiometer': ['angiometer', 'ergotamine', 'geometrina'], + 'angka': ['angka', 'kanga'], + 'anglaise': ['anglaise', 'gelasian'], + 'angle': ['agnel', 'angel', 'angle', 'galen', 'genal', 'glean', 'lagen'], + 'angled': ['angled', 'dangle', 'englad', 'lagend'], + 'angler': ['angler', 'arleng', 'garnel', 'largen', 'rangle', 'regnal'], + 'angles': ['angles', 'gansel'], + 'angleworm': ['angleworm', 'lawmonger'], + 'anglian': ['alangin', 'anginal', 'anglian', 'nagnail'], + 'anglic': ['anglic', 'lacing'], + 'anglish': ['anglish', 'ashling'], + 'anglist': ['anglist', 'lasting', 'salting', 'slating', 'staling'], + 'angloid': ['angloid', 'loading'], + 'ango': ['agon', 'ango', 'gaon', 'goan', 'gona'], + 'angola': ['agonal', 'angola'], + 'angolar': ['angolar', 'organal'], + 'angor': ['angor', + 'argon', + 'goran', + 'grano', + 'groan', + 'nagor', + 'orang', + 'organ', + 'rogan', + 'ronga'], + 'angora': ['agroan', 'angora', 'anogra', 'arango', 'argoan', 'onagra'], + 'angriness': ['angriness', 'ranginess'], + 'angrite': ['angrite', 'granite', 'ingrate', 'tangier', 'tearing', 'tigrean'], + 'angry': ['angry', 'rangy'], + 'angst': ['angst', 'stang', 'tangs'], + 'angster': ['angster', 'garnets', 'nagster', 'strange'], + 'anguid': ['anguid', 'gaduin'], + 'anguine': ['anguine', 'guanine', 'guinean'], + 'angula': ['angula', 'nagual'], + 'angular': ['angular', 'granula'], + 'angulate': ['angulate', 'gaetulan'], + 'anguria': ['anguria', 'gaurian', 'guarani'], + 'angus': ['agnus', 'angus', 'sugan'], + 'anharmonic': ['anharmonic', 'monarchian'], + 'anhematosis': ['anhematosis', 'somasthenia'], + 'anhidrotic': ['anhidrotic', 'trachinoid'], + 'anhistous': ['anhistous', 'isanthous'], + 'anhydridize': ['anhydridize', 'hydrazidine'], + 'anhydrize': ['anhydrize', 'hydrazine'], + 'ani': ['ani', 'ian'], + 'anice': ['anice', 'eniac'], + 'aniconic': ['aniconic', 'ciconian'], + 'aniconism': ['aniconism', 'insomniac'], + 'anicular': ['anicular', 'caulinar'], + 'anicut': ['anicut', 'nautic', 'ticuna', 'tunica'], + 'anidian': ['anidian', 'indiana'], + 'aniente': ['aniente', 'itenean'], + 'anight': ['anight', 'athing'], + 'anil': ['alin', 'anil', 'lain', 'lina', 'nail'], + 'anile': ['alien', 'aline', 'anile', 'elain', 'elian', 'laine', 'linea'], + 'anilic': ['anilic', 'clinia'], + 'anilid': ['anilid', 'dialin', 'dianil', 'inlaid'], + 'anilide': ['anilide', 'elaidin'], + 'anilidic': ['anilidic', 'indicial'], + 'anima': ['amain', 'amani', 'amnia', 'anima', 'mania'], + 'animable': ['animable', 'maniable'], + 'animal': ['almain', 'animal', 'lamina', 'manila'], + 'animalic': ['animalic', 'limacina'], + 'animate': ['amentia', 'aminate', 'anamite', 'animate'], + 'animated': ['animated', 'mandaite', 'mantidae'], + 'animater': ['animater', 'marinate'], + 'animating': ['animating', 'imaginant'], + 'animation': ['amination', 'animation'], + 'animator': ['animator', 'tamanoir'], + 'anime': ['amine', 'anime', 'maine', 'manei'], + 'animi': ['amini', 'animi'], + 'animist': ['animist', 'santimi'], + 'animize': ['aminize', 'animize', 'azimine'], + 'animus': ['animus', 'anisum', 'anusim', 'manius'], + 'anionic': ['anionic', 'iconian'], + 'anis': ['anis', 'nais', 'nasi', 'nias', 'sain', 'sina'], + 'anisal': ['anisal', 'nasial', 'salian', 'salina'], + 'anisate': ['anisate', 'entasia'], + 'anise': ['anise', 'insea', 'siena', 'sinae'], + 'anisette': ['anisette', 'atestine', 'settaine'], + 'anisic': ['anisic', 'sicani', 'sinaic'], + 'anisilic': ['anisilic', 'sicilian'], + 'anisodont': ['anisodont', 'sondation'], + 'anisometric': ['anisometric', + 'creationism', + 'miscreation', + 'ramisection', + 'reactionism'], + 'anisopod': ['anisopod', 'isopodan'], + 'anisoptera': ['anisoptera', 'asperation', 'separation'], + 'anisum': ['animus', 'anisum', 'anusim', 'manius'], + 'anisuria': ['anisuria', 'isaurian'], + 'anisyl': ['anisyl', 'snaily'], + 'anita': ['anita', 'niata', 'tania'], + 'anither': ['anither', 'inearth', 'naither'], + 'ankee': ['aknee', 'ankee', 'keena'], + 'anker': ['anker', 'karen', 'naker'], + 'ankh': ['ankh', 'hank', 'khan'], + 'anklet': ['anklet', 'lanket', 'tankle'], + 'ankoli': ['ankoli', 'kaolin'], + 'ankus': ['ankus', 'kusan'], + 'ankyroid': ['ankyroid', 'dikaryon'], + 'anlace': ['anlace', 'calean'], + 'ann': ['ann', 'nan'], + 'anna': ['anan', 'anna', 'nana'], + 'annale': ['annale', 'anneal'], + 'annaline': ['annaline', 'linnaean'], + 'annalist': ['annalist', 'santalin'], + 'annalize': ['annalize', 'zelanian'], + 'annam': ['annam', 'manna'], + 'annamite': ['annamite', 'manatine'], + 'annard': ['annard', 'randan'], + 'annat': ['annat', 'tanan'], + 'annates': ['annates', 'tannase'], + 'anne': ['anne', 'nane'], + 'anneal': ['annale', 'anneal'], + 'annealer': ['annealer', 'lernaean', 'reanneal'], + 'annelid': ['annelid', 'lindane'], + 'annelism': ['annelism', 'linesman'], + 'anneloid': ['anneloid', 'nonideal'], + 'annet': ['anent', 'annet', 'nenta'], + 'annexer': ['annexer', 'reannex'], + 'annie': ['annie', 'inane'], + 'annite': ['annite', 'innate', 'tinean'], + 'annotine': ['annotine', 'tenonian'], + 'annoy': ['annoy', 'nonya'], + 'annoyancer': ['annoyancer', 'rayonnance'], + 'annoyer': ['annoyer', 'reannoy'], + 'annualist': ['annualist', 'sultanian'], + 'annulation': ['annulation', 'unnational'], + 'annulet': ['annulet', 'nauntle'], + 'annulment': ['annulment', 'tunnelman'], + 'annuloid': ['annuloid', 'uninodal'], + 'anodic': ['adonic', 'anodic'], + 'anodize': ['adonize', 'anodize'], + 'anodynic': ['anodynic', 'cydonian'], + 'anoestrous': ['anoestrous', 'treasonous'], + 'anoestrum': ['anoestrum', 'neuromast'], + 'anoetic': ['acetoin', 'aconite', 'anoetic', 'antoeci', 'cetonia'], + 'anogenic': ['anogenic', 'canoeing'], + 'anogra': ['agroan', 'angora', 'anogra', 'arango', 'argoan', 'onagra'], + 'anoil': ['aloin', 'anoil', 'anoli'], + 'anoint': ['anoint', 'nation'], + 'anointer': ['anointer', 'inornate', 'nonirate', 'reanoint'], + 'anole': ['alone', 'anole', 'olena'], + 'anoli': ['aloin', 'anoil', 'anoli'], + 'anolis': ['alison', 'anolis'], + 'anomaliped': ['anomaliped', 'palaemonid'], + 'anomalism': ['anomalism', 'malmaison'], + 'anomalist': ['anomalist', 'atonalism'], + 'anomiidae': ['anomiidae', 'maioidean'], + 'anomite': ['amniote', 'anomite'], + 'anomodont': ['anomodont', 'monodonta'], + 'anomural': ['anomural', 'monaural'], + 'anon': ['anon', 'nona', 'onan'], + 'anophyte': ['anophyte', 'typhoean'], + 'anopia': ['anopia', 'aponia', 'poiana'], + 'anorak': ['anorak', 'korana'], + 'anorchism': ['anorchism', 'harmonics'], + 'anorectic': ['accretion', 'anorectic', 'neoarctic'], + 'anorthic': ['anorthic', 'anthroic', 'tanchoir'], + 'anorthitite': ['anorthitite', 'trithionate'], + 'anorthose': ['anorthose', 'hoarstone'], + 'anosia': ['anosia', 'asonia'], + 'anosmatic': ['anatocism', 'anosmatic'], + 'anosmia': ['amsonia', 'anosmia'], + 'anosmic': ['anosmic', 'masonic'], + 'anoterite': ['anoterite', 'orientate'], + 'another': ['another', 'athenor', 'rheotan'], + 'anotia': ['anotia', 'atonia'], + 'anoxia': ['anoxia', 'axonia'], + 'anoxic': ['anoxic', 'oxanic'], + 'ansa': ['anas', 'ansa', 'saan'], + 'ansar': ['ansar', 'saran', 'sarna'], + 'ansation': ['ansation', 'sonatina'], + 'anseis': ['anesis', 'anseis', 'sanies', 'sansei', 'sasine'], + 'ansel': ['ansel', 'slane'], + 'anselm': ['anselm', 'mensal'], + 'anser': ['anser', 'nares', 'rasen', 'snare'], + 'anserine': ['anserine', 'reinsane'], + 'anserous': ['anserous', 'arsenous'], + 'ansu': ['ansu', 'anus'], + 'answerer': ['answerer', 'reanswer'], + 'ant': ['ant', 'nat', 'tan'], + 'anta': ['anat', 'anta', 'tana'], + 'antacrid': ['antacrid', 'cardiant', 'radicant', 'tridacna'], + 'antagonism': ['antagonism', 'montagnais'], + 'antagonist': ['antagonist', 'stagnation'], + 'antal': ['antal', 'natal'], + 'antanemic': ['antanemic', 'cinnamate'], + 'antar': ['antar', 'antra'], + 'antarchistical': ['antarchistical', 'charlatanistic'], + 'ante': ['ante', 'aten', 'etna', 'nate', 'neat', 'taen', 'tane', 'tean'], + 'anteact': ['anteact', 'cantate'], + 'anteal': ['anteal', 'lanate', 'teanal'], + 'antechoir': ['anchorite', 'antechoir', 'heatronic', 'hectorian'], + 'antecornu': ['antecornu', 'connature'], + 'antedate': ['antedate', 'edentata'], + 'antelabium': ['albuminate', 'antelabium'], + 'antelopian': ['antelopian', 'neapolitan', 'panelation'], + 'antelucan': ['antelucan', 'cannulate'], + 'antelude': ['antelude', 'unelated'], + 'anteluminary': ['anteluminary', 'unalimentary'], + 'antemedial': ['antemedial', 'delaminate'], + 'antenatal': ['antenatal', 'atlantean', 'tantalean'], + 'anteriad': ['anteriad', 'atridean', 'dentaria'], + 'anteroinferior': ['anteroinferior', 'inferoanterior'], + 'anterosuperior': ['anterosuperior', 'superoanterior'], + 'antes': ['antes', 'nates', 'stane', 'stean'], + 'anthela': ['anthela', 'ethanal'], + 'anthem': ['anthem', 'hetman', 'mentha'], + 'anthemwise': ['anthemwise', 'whitmanese'], + 'anther': ['anther', 'nather', 'tharen', 'thenar'], + 'anthericum': ['anthericum', 'narthecium'], + 'anthicidae': ['anthicidae', 'tachinidae'], + 'anthinae': ['anthinae', 'athenian'], + 'anthogenous': ['anthogenous', 'neognathous'], + 'anthonomus': ['anthonomus', 'monanthous'], + 'anthophile': ['anthophile', 'lithophane'], + 'anthracia': ['anthracia', 'antiarcha', 'catharina'], + 'anthroic': ['anorthic', 'anthroic', 'tanchoir'], + 'anthrol': ['althorn', 'anthrol', 'thronal'], + 'anthropic': ['anthropic', 'rhapontic'], + 'anti': ['aint', 'anti', 'tain', 'tina'], + 'antiabrin': ['antiabrin', 'britannia'], + 'antiae': ['aetian', 'antiae', 'taenia'], + 'antiager': ['antiager', 'trainage'], + 'antialbumid': ['antialbumid', 'balantidium'], + 'antialien': ['ailantine', 'antialien'], + 'antiarcha': ['anthracia', 'antiarcha', 'catharina'], + 'antiaris': ['antiaris', 'intarsia'], + 'antibenzaldoxime': ['antibenzaldoxime', 'benzantialdoxime'], + 'antiblue': ['antiblue', 'nubilate'], + 'antic': ['actin', 'antic'], + 'antical': ['actinal', 'alantic', 'alicant', 'antical'], + 'anticaste': ['anticaste', 'ataentsic'], + 'anticlea': ['analcite', 'anticlea', 'laitance'], + 'anticlinorium': ['anticlinorium', 'inclinatorium'], + 'anticly': ['anticly', 'cantily'], + 'anticness': ['anticness', 'cantiness', 'incessant'], + 'anticor': ['anticor', 'carotin', 'cortina', 'ontaric'], + 'anticouncil': ['anticouncil', 'inculcation'], + 'anticourt': ['anticourt', 'curtation', 'ructation'], + 'anticous': ['acontius', 'anticous'], + 'anticreative': ['anticreative', 'antireactive'], + 'anticreep': ['anticreep', 'apenteric', 'increpate'], + 'antidote': ['antidote', 'tetanoid'], + 'antidotical': ['antidotical', 'dictational'], + 'antietam': ['antietam', 'manettia'], + 'antiextreme': ['antiextreme', 'exterminate'], + 'antifouler': ['antifouler', 'fluorinate', 'uniflorate'], + 'antifriction': ['antifriction', 'nitrifaction'], + 'antifungin': ['antifungin', 'unfainting'], + 'antigen': ['antigen', 'gentian'], + 'antigenic': ['antigenic', 'gentianic'], + 'antiglare': ['antiglare', 'raglanite'], + 'antigod': ['antigod', 'doating'], + 'antigone': ['antigone', 'negation'], + 'antiheroic': ['antiheroic', 'theorician'], + 'antilemic': ['alimentic', 'antilemic', 'melanitic', 'metanilic'], + 'antilia': ['antilia', 'italian'], + 'antilipase': ['antilipase', 'sapiential'], + 'antilope': ['antilope', 'antipole'], + 'antimallein': ['antimallein', 'inalimental'], + 'antimasque': ['antimasque', 'squamatine'], + 'antimeric': ['antimeric', 'carminite', 'criminate', 'metrician'], + 'antimerina': ['antimerina', 'maintainer', 'remaintain'], + 'antimeter': ['antimeter', 'attermine', 'interteam', 'terminate', 'tetramine'], + 'antimodel': ['antimodel', 'maldonite', 'monilated'], + 'antimodern': ['antimodern', 'ordainment'], + 'antimonial': ['antimonial', 'lamination'], + 'antimonic': ['antimonic', 'antinomic'], + 'antimonium': ['ammunition', 'antimonium'], + 'antimony': ['antimony', 'antinomy'], + 'antimoral': ['antimoral', 'tailorman'], + 'antimosquito': ['antimosquito', 'misquotation'], + 'antinegro': ['antinegro', 'argentino', 'argention'], + 'antinepotic': ['antinepotic', 'pectination'], + 'antineutral': ['antineutral', 'triannulate'], + 'antinial': ['antinial', 'latinian'], + 'antinome': ['antinome', 'nominate'], + 'antinomian': ['antinomian', 'innominata'], + 'antinomic': ['antimonic', 'antinomic'], + 'antinomy': ['antimony', 'antinomy'], + 'antinormal': ['antinormal', 'nonmarital', 'nonmartial'], + 'antiphonetic': ['antiphonetic', 'pentathionic'], + 'antiphonic': ['antiphonic', 'napthionic'], + 'antiphony': ['antiphony', 'typhonian'], + 'antiphrasis': ['antiphrasis', 'artisanship'], + 'antipodic': ['antipodic', 'diapnotic'], + 'antipole': ['antilope', 'antipole'], + 'antipolo': ['antipolo', 'antipool', 'optional'], + 'antipool': ['antipolo', 'antipool', 'optional'], + 'antipope': ['antipope', 'appointe'], + 'antiprotease': ['antiprotease', 'entoparasite'], + 'antipsoric': ['antipsoric', 'ascription', 'crispation'], + 'antiptosis': ['antiptosis', 'panostitis'], + 'antiputrid': ['antiputrid', 'tripudiant'], + 'antipyretic': ['antipyretic', 'pertinacity'], + 'antique': ['antique', 'quinate'], + 'antiquer': ['antiquer', 'quartine'], + 'antirabies': ['antirabies', 'bestiarian'], + 'antiracer': ['antiracer', 'tarriance'], + 'antireactive': ['anticreative', 'antireactive'], + 'antired': ['antired', 'detrain', 'randite', 'trained'], + 'antireducer': ['antireducer', 'reincrudate', 'untraceried'], + 'antiroyalist': ['antiroyalist', 'stationarily'], + 'antirumor': ['antirumor', 'ruminator'], + 'antirun': ['antirun', 'untrain', 'urinant'], + 'antirust': ['antirust', 'naturist'], + 'antiscion': ['anconitis', 'antiscion', 'onanistic'], + 'antisepsin': ['antisepsin', 'paintiness'], + 'antisepsis': ['antisepsis', 'inspissate'], + 'antiseptic': ['antiseptic', 'psittacine'], + 'antiserum': ['antiserum', 'misaunter'], + 'antisi': ['antisi', 'isatin'], + 'antislip': ['alpinist', 'antislip'], + 'antisoporific': ['antisoporific', 'prosification', 'sporification'], + 'antispace': ['antispace', 'panaceist'], + 'antistes': ['antistes', 'titaness'], + 'antisun': ['antisun', 'unsaint', 'unsatin', 'unstain'], + 'antitheism': ['antitheism', 'themistian'], + 'antitonic': ['antitonic', 'nictation'], + 'antitorpedo': ['antitorpedo', 'deportation'], + 'antitrade': ['antitrade', 'attainder'], + 'antitrope': ['antitrope', 'patronite', 'tritanope'], + 'antitropic': ['antitropic', 'tritanopic'], + 'antitropical': ['antitropical', 'practitional'], + 'antivice': ['antivice', 'inactive', 'vineatic'], + 'antler': ['altern', 'antler', 'learnt', 'rental', 'ternal'], + 'antlia': ['antlia', 'latian', 'nalita'], + 'antliate': ['antliate', 'latinate'], + 'antlid': ['antlid', 'tindal'], + 'antling': ['antling', 'tanling'], + 'antoeci': ['acetoin', 'aconite', 'anoetic', 'antoeci', 'cetonia'], + 'antoecian': ['acetanion', 'antoecian'], + 'anton': ['anton', 'notan', 'tonna'], + 'antproof': ['antproof', 'tanproof'], + 'antra': ['antar', 'antra'], + 'antral': ['antral', 'tarnal'], + 'antre': ['antre', 'arent', 'retan', 'terna'], + 'antrocele': ['antrocele', 'coeternal', 'tolerance'], + 'antronasal': ['antronasal', 'nasoantral'], + 'antroscope': ['antroscope', 'contrapose'], + 'antroscopy': ['antroscopy', 'syncopator'], + 'antrotome': ['antrotome', 'nototrema'], + 'antrustion': ['antrustion', 'nasturtion'], + 'antu': ['antu', 'aunt', 'naut', 'taun', 'tuan', 'tuna'], + 'anubis': ['anubis', 'unbias'], + 'anura': ['anura', 'ruana'], + 'anuresis': ['anuresis', 'senarius'], + 'anuretic': ['anuretic', 'centauri', 'centuria', 'teucrian'], + 'anuria': ['anuria', 'urania'], + 'anuric': ['anuric', 'cinura', 'uranic'], + 'anurous': ['anurous', 'uranous'], + 'anury': ['anury', 'unary', 'unray'], + 'anus': ['ansu', 'anus'], + 'anusim': ['animus', 'anisum', 'anusim', 'manius'], + 'anvil': ['alvin', 'anvil', 'nival', 'vinal'], + 'any': ['any', 'nay', 'yan'], + 'aonach': ['aonach', 'choana'], + 'aoristic': ['aoristic', 'iscariot'], + 'aortal': ['aortal', 'rotala'], + 'aortectasis': ['aerostatics', 'aortectasis'], + 'aortism': ['amorist', 'aortism', 'miastor'], + 'aosmic': ['aosmic', 'mosaic'], + 'apachite': ['apachite', 'hepatica'], + 'apalachee': ['acalephae', 'apalachee'], + 'apama': ['amapa', 'apama'], + 'apanthropy': ['apanthropy', 'panatrophy'], + 'apar': ['apar', 'paar', 'para'], + 'apart': ['apart', 'trapa'], + 'apatetic': ['apatetic', 'capitate'], + 'ape': ['ape', 'pea'], + 'apedom': ['apedom', 'pomade'], + 'apeiron': ['apeiron', 'peorian'], + 'apelet': ['apelet', 'ptelea'], + 'apelike': ['apelike', 'pealike'], + 'apeling': ['apeling', 'leaping'], + 'apenteric': ['anticreep', 'apenteric', 'increpate'], + 'apeptic': ['apeptic', 'catpipe'], + 'aper': ['aper', 'pare', 'pear', 'rape', 'reap'], + 'aperch': ['aperch', 'eparch', 'percha', 'preach'], + 'aperitive': ['aperitive', 'petiveria'], + 'apert': ['apert', 'pater', 'peart', 'prate', 'taper', 'terap'], + 'apertly': ['apertly', 'peartly', 'platery', 'pteryla', 'taperly'], + 'apertness': ['apertness', 'peartness', 'taperness'], + 'apertured': ['apertured', 'departure'], + 'apery': ['apery', 'payer', 'repay'], + 'aphanes': ['aphanes', 'saphena'], + 'aphasia': ['aphasia', 'asaphia'], + 'aphasic': ['aphasic', 'asaphic'], + 'aphemic': ['aphemic', 'impeach'], + 'aphetic': ['aphetic', 'caphite', 'hepatic'], + 'aphetism': ['aphetism', 'mateship', 'shipmate', 'spithame'], + 'aphetize': ['aphetize', 'hepatize'], + 'aphides': ['aphides', 'diphase'], + 'aphidicolous': ['acidophilous', 'aphidicolous'], + 'aphis': ['aphis', 'apish', 'hispa', 'saiph', 'spahi'], + 'aphodian': ['adiaphon', 'aphodian'], + 'aphonic': ['aphonic', 'phocian'], + 'aphorismical': ['aphorismical', 'parochialism'], + 'aphotic': ['aphotic', 'picotah'], + 'aphra': ['aphra', 'harpa', 'parah'], + 'aphrodistic': ['aphrodistic', 'diastrophic'], + 'aphrodite': ['aphrodite', 'atrophied', 'diaporthe'], + 'apian': ['apian', 'apina'], + 'apiator': ['apiator', 'atropia', 'parotia'], + 'apical': ['apical', 'palaic'], + 'apicular': ['apicular', 'piacular'], + 'apina': ['apian', 'apina'], + 'apinae': ['anepia', 'apinae'], + 'apinage': ['aegipan', 'apinage'], + 'apinch': ['apinch', 'chapin', 'phanic'], + 'aping': ['aping', 'ngapi', 'pangi'], + 'apiole': ['apiole', 'leipoa'], + 'apiolin': ['apiolin', 'pinolia'], + 'apionol': ['apionol', 'polonia'], + 'apiose': ['apiose', 'apoise'], + 'apis': ['apis', 'pais', 'pasi', 'saip'], + 'apish': ['aphis', 'apish', 'hispa', 'saiph', 'spahi'], + 'apishly': ['apishly', 'layship'], + 'apism': ['apism', 'sampi'], + 'apitpat': ['apitpat', 'pitapat'], + 'apivorous': ['apivorous', 'oviparous'], + 'aplenty': ['aplenty', 'penalty'], + 'aplite': ['aplite', 'pilate'], + 'aplitic': ['aliptic', 'aplitic'], + 'aplodontia': ['adoptional', 'aplodontia'], + 'aplome': ['aplome', 'malope'], + 'apnea': ['apnea', 'paean'], + 'apneal': ['apneal', 'panela'], + 'apochromat': ['apochromat', 'archoptoma'], + 'apocrita': ['apocrita', 'aproctia'], + 'apocryph': ['apocryph', 'hypocarp'], + 'apod': ['apod', 'dopa'], + 'apoda': ['adpao', 'apoda'], + 'apogon': ['apogon', 'poonga'], + 'apoise': ['apiose', 'apoise'], + 'apolaustic': ['apolaustic', 'autopsical'], + 'apolistan': ['apolistan', 'lapsation'], + 'apollo': ['apollo', 'palolo'], + 'aponia': ['anopia', 'aponia', 'poiana'], + 'aponic': ['aponic', 'ponica'], + 'aporetic': ['aporetic', 'capriote', 'operatic'], + 'aporetical': ['aporetical', 'operatical'], + 'aporia': ['aporia', 'piaroa'], + 'aport': ['aport', 'parto', 'porta'], + 'aportoise': ['aportoise', 'esotropia'], + 'aposporous': ['aposporous', 'aprosopous'], + 'apostil': ['apostil', 'topsail'], + 'apostle': ['apostle', 'aseptol'], + 'apostrophus': ['apostrophus', 'pastophorus'], + 'apothesine': ['apothesine', 'isoheptane'], + 'apout': ['apout', 'taupo'], + 'appall': ['appall', 'palpal'], + 'apparent': ['apparent', 'trappean'], + 'appealer': ['appealer', 'reappeal'], + 'appealing': ['appealing', 'lagniappe', 'panplegia'], + 'appearer': ['appearer', 'rapparee', 'reappear'], + 'append': ['append', 'napped'], + 'applauder': ['applauder', 'reapplaud'], + 'applicator': ['applicator', 'procapital'], + 'applier': ['applier', 'aripple'], + 'appointe': ['antipope', 'appointe'], + 'appointer': ['appointer', 'reappoint'], + 'appointor': ['appointor', 'apportion'], + 'apportion': ['appointor', 'apportion'], + 'apportioner': ['apportioner', 'reapportion'], + 'appraisable': ['appraisable', 'parablepsia'], + 'apprehender': ['apprehender', 'reapprehend'], + 'approacher': ['approacher', 'reapproach'], + 'apricot': ['apricot', 'atropic', 'parotic', 'patrico'], + 'april': ['april', 'pilar', 'ripal'], + 'aprilis': ['aprilis', 'liparis'], + 'aproctia': ['apocrita', 'aproctia'], + 'apronless': ['apronless', 'responsal'], + 'aprosopous': ['aposporous', 'aprosopous'], + 'apse': ['apse', 'pesa', 'spae'], + 'apsidiole': ['apsidiole', 'episodial'], + 'apt': ['apt', 'pat', 'tap'], + 'aptal': ['aptal', 'palta', 'talpa'], + 'aptera': ['aptera', 'parate', 'patera'], + 'apterial': ['apterial', 'parietal'], + 'apteroid': ['apteroid', 'proteida'], + 'aptian': ['aptian', 'patina', 'taipan'], + 'aptly': ['aptly', 'patly', 'platy', 'typal'], + 'aptness': ['aptness', 'patness'], + 'aptote': ['aptote', 'optate', 'potate', 'teapot'], + 'apulian': ['apulian', 'paulian', 'paulina'], + 'apulse': ['apulse', 'upseal'], + 'apus': ['apus', 'supa', 'upas'], + 'aquabelle': ['aquabelle', 'equalable'], + 'aqueoigneous': ['aqueoigneous', 'igneoaqueous'], + 'aquicolous': ['aquicolous', 'loquacious'], + 'ar': ['ar', 'ra'], + 'arab': ['arab', 'arba', 'baar', 'bara'], + 'arabic': ['arabic', 'cairba'], + 'arabinic': ['arabinic', 'cabirian', 'carabini', 'cibarian'], + 'arabis': ['abaris', 'arabis'], + 'arabism': ['abramis', 'arabism'], + 'arabist': ['arabist', 'bartsia'], + 'arabit': ['arabit', 'tabira'], + 'arable': ['ablare', 'arable', 'arbela'], + 'araca': ['acara', 'araca'], + 'aracana': ['anacara', 'aracana'], + 'aracanga': ['aracanga', 'caragana'], + 'arachic': ['arachic', 'archaic'], + 'arachidonic': ['arachidonic', 'characinoid'], + 'arachis': ['arachis', 'asiarch', 'saharic'], + 'arachne': ['arachne', 'archean'], + 'arachnism': ['anarchism', 'arachnism'], + 'arachnitis': ['arachnitis', 'christiana'], + 'arad': ['adar', 'arad', 'raad', 'rada'], + 'arain': ['airan', 'arain', 'arian'], + 'arales': ['alares', 'arales'], + 'aralia': ['alaria', 'aralia'], + 'aralie': ['aerial', 'aralie'], + 'aramaic': ['aramaic', 'cariama'], + 'aramina': ['aramina', 'mariana'], + 'araminta': ['anamirta', 'araminta'], + 'aramus': ['aramus', 'asarum'], + 'araneid': ['araneid', 'ariadne', 'ranidae'], + 'aranein': ['aranein', 'raninae'], + 'aranga': ['angara', 'aranga', 'nagara'], + 'arango': ['agroan', 'angora', 'anogra', 'arango', 'argoan', 'onagra'], + 'arati': ['arati', 'atria', 'riata', 'tarai', 'tiara'], + 'aration': ['aration', 'otarian'], + 'arauan': ['arauan', 'arauna'], + 'arauna': ['arauan', 'arauna'], + 'arba': ['arab', 'arba', 'baar', 'bara'], + 'arbacin': ['arbacin', 'carabin', 'cariban'], + 'arbalester': ['arbalester', 'arbalestre', 'arrestable'], + 'arbalestre': ['arbalester', 'arbalestre', 'arrestable'], + 'arbalister': ['arbalister', 'breastrail'], + 'arbalo': ['aboral', 'arbalo'], + 'arbela': ['ablare', 'arable', 'arbela'], + 'arbiter': ['arbiter', 'rarebit'], + 'arbored': ['arbored', 'boarder', 'reboard'], + 'arboret': ['arboret', 'roberta', 'taborer'], + 'arboretum': ['arboretum', 'tambourer'], + 'arborist': ['arborist', 'ribroast'], + 'arbuscle': ['arbuscle', 'buscarle'], + 'arbutin': ['arbutin', 'tribuna'], + 'arc': ['arc', 'car'], + 'arca': ['arca', 'cara'], + 'arcadia': ['acardia', 'acarida', 'arcadia'], + 'arcadic': ['arcadic', 'cardiac'], + 'arcane': ['arcane', 'carane'], + 'arcanite': ['anaretic', 'arcanite', 'carinate', 'craniate'], + 'arcate': ['arcate', 'cerata'], + 'arch': ['arch', 'char', 'rach'], + 'archae': ['archae', 'areach'], + 'archaic': ['arachic', 'archaic'], + 'archaism': ['archaism', 'charisma'], + 'archapostle': ['archapostle', 'thecasporal'], + 'archcount': ['archcount', 'crouchant'], + 'arche': ['acher', 'arche', 'chare', 'chera', 'rache', 'reach'], + 'archeal': ['alchera', 'archeal'], + 'archean': ['arachne', 'archean'], + 'archer': ['archer', 'charer', 'rechar'], + 'arches': ['arches', 'chaser', 'eschar', 'recash', 'search'], + 'archidome': ['archidome', 'chromidae'], + 'archil': ['archil', 'chiral'], + 'arching': ['arching', 'chagrin'], + 'architis': ['architis', 'rachitis'], + 'archocele': ['archocele', 'cochleare'], + 'archon': ['anchor', 'archon', 'charon', 'rancho'], + 'archontia': ['archontia', 'tocharian'], + 'archoptoma': ['apochromat', 'archoptoma'], + 'archpoet': ['archpoet', 'protheca'], + 'archprelate': ['archprelate', 'pretracheal'], + 'archsaint': ['anarchist', 'archsaint', 'cantharis'], + 'archsee': ['archsee', 'rechase'], + 'archsin': ['archsin', 'incrash'], + 'archy': ['archy', 'chary'], + 'arcidae': ['arcidae', 'caridea'], + 'arcing': ['arcing', 'racing'], + 'arcite': ['acrite', 'arcite', 'tercia', 'triace', 'tricae'], + 'arcked': ['arcked', 'dacker'], + 'arcking': ['arcking', 'carking', 'racking'], + 'arcos': ['arcos', 'crosa', 'oscar', 'sacro'], + 'arctia': ['acrita', 'arctia'], + 'arctian': ['acritan', 'arctian'], + 'arcticize': ['arcticize', 'cicatrize'], + 'arctiid': ['arctiid', 'triacid', 'triadic'], + 'arctoid': ['arctoid', 'carotid', 'dartoic'], + 'arctoidean': ['arctoidean', 'carotidean', 'cordaitean', 'dinocerata'], + 'arctomys': ['arctomys', 'costmary', 'mascotry'], + 'arctos': ['arctos', 'castor', 'costar', 'scrota'], + 'arcual': ['arcual', 'arcula'], + 'arcuale': ['arcuale', 'caurale'], + 'arcubalist': ['arcubalist', 'ultrabasic'], + 'arcula': ['arcual', 'arcula'], + 'arculite': ['arculite', 'cutleria', 'lucretia', 'reticula', 'treculia'], + 'ardea': ['ardea', 'aread'], + 'ardeb': ['ardeb', 'beard', 'bread', 'debar'], + 'ardelia': ['ardelia', 'laridae', 'radiale'], + 'ardella': ['ardella', 'dareall'], + 'ardency': ['ardency', 'dancery'], + 'ardish': ['ardish', 'radish'], + 'ardoise': ['ardoise', 'aroides', 'soredia'], + 'ardu': ['ardu', 'daur', 'dura'], + 'are': ['aer', 'are', 'ear', 'era', 'rea'], + 'areach': ['archae', 'areach'], + 'aread': ['ardea', 'aread'], + 'areal': ['areal', 'reaal'], + 'arean': ['anear', 'arean', 'arena'], + 'arecaceae': ['aceraceae', 'arecaceae'], + 'arecaceous': ['aceraceous', 'arecaceous'], + 'arecain': ['acarine', 'acraein', 'arecain'], + 'arecolin': ['acrolein', + 'arecolin', + 'caroline', + 'colinear', + 'cornelia', + 'creolian', + 'lonicera'], + 'arecoline': ['arecoline', 'arenicole'], + 'arecuna': ['arecuna', 'aucaner'], + 'ared': ['ared', 'daer', 'dare', 'dear', 'read'], + 'areel': ['areel', 'earle'], + 'arena': ['anear', 'arean', 'arena'], + 'arenaria': ['aerarian', 'arenaria'], + 'arend': ['andre', 'arend', 'daren', 'redan'], + 'areng': ['anger', 'areng', 'grane', 'range'], + 'arenga': ['arenga', 'argean'], + 'arenicole': ['arecoline', 'arenicole'], + 'arenicolite': ['arenicolite', 'ricinoleate'], + 'arenig': ['arenig', 'earing', 'gainer', 'reagin', 'regain'], + 'arenoid': ['aneroid', 'arenoid'], + 'arenose': ['arenose', 'serenoa'], + 'arent': ['antre', 'arent', 'retan', 'terna'], + 'areographer': ['aerographer', 'areographer'], + 'areographic': ['aerographic', 'areographic'], + 'areographical': ['aerographical', 'areographical'], + 'areography': ['aerography', 'areography'], + 'areologic': ['aerologic', 'areologic'], + 'areological': ['aerological', 'areological'], + 'areologist': ['aerologist', 'areologist'], + 'areology': ['aerology', 'areology'], + 'areometer': ['aerometer', 'areometer'], + 'areometric': ['aerometric', 'areometric'], + 'areometry': ['aerometry', 'areometry'], + 'arete': ['arete', 'eater', 'teaer'], + 'argal': ['agral', 'argal'], + 'argali': ['argali', 'garial'], + 'argans': ['argans', 'sangar'], + 'argante': ['argante', 'granate', 'tanager'], + 'argas': ['argas', 'sagra'], + 'argean': ['arenga', 'argean'], + 'argeers': ['argeers', 'greaser', 'serrage'], + 'argel': ['argel', 'ergal', 'garle', 'glare', 'lager', 'large', 'regal'], + 'argenol': ['argenol', 'longear'], + 'argent': ['argent', 'garnet', 'garten', 'tanger'], + 'argentamid': ['argentamid', 'marginated'], + 'argenter': ['argenter', 'garneter'], + 'argenteum': ['argenteum', 'augmenter'], + 'argentic': ['argentic', 'citrange'], + 'argentide': ['argentide', 'denigrate', 'dinergate'], + 'argentiferous': ['argentiferous', 'garnetiferous'], + 'argentina': ['argentina', 'tanagrine'], + 'argentine': ['argentine', 'tangerine'], + 'argentino': ['antinegro', 'argentino', 'argention'], + 'argention': ['antinegro', 'argentino', 'argention'], + 'argentite': ['argentite', 'integrate'], + 'argentol': ['argentol', 'gerontal'], + 'argenton': ['argenton', 'negatron'], + 'argentous': ['argentous', 'neotragus'], + 'argentum': ['argentum', 'argument'], + 'arghan': ['arghan', 'hangar'], + 'argil': ['argil', 'glair', 'grail'], + 'arginine': ['arginine', 'nigerian'], + 'argive': ['argive', 'rivage'], + 'argo': ['argo', 'garo', 'gora'], + 'argoan': ['agroan', 'angora', 'anogra', 'arango', 'argoan', 'onagra'], + 'argol': ['algor', 'argol', 'goral', 'largo'], + 'argolet': ['argolet', 'gloater', 'legator'], + 'argolian': ['argolian', 'gloriana'], + 'argolic': ['argolic', 'cograil'], + 'argolid': ['argolid', 'goliard'], + 'argon': ['angor', + 'argon', + 'goran', + 'grano', + 'groan', + 'nagor', + 'orang', + 'organ', + 'rogan', + 'ronga'], + 'argot': ['argot', 'gator', 'gotra', 'groat'], + 'argue': ['argue', 'auger'], + 'argulus': ['argulus', 'lagurus'], + 'argument': ['argentum', 'argument'], + 'argus': ['argus', 'sugar'], + 'arguslike': ['arguslike', 'sugarlike'], + 'argute': ['argute', 'guetar', 'rugate', 'tuareg'], + 'argyle': ['argyle', 'gleary'], + 'arhar': ['arhar', 'arrah'], + 'arhat': ['arhat', 'artha', 'athar'], + 'aria': ['aira', 'aria', 'raia'], + 'ariadne': ['araneid', 'ariadne', 'ranidae'], + 'arian': ['airan', 'arain', 'arian'], + 'arianrhod': ['arianrhod', 'hordarian'], + 'aribine': ['aribine', 'bairnie', 'iberian'], + 'arician': ['arician', 'icarian'], + 'arid': ['arid', 'dari', 'raid'], + 'aridian': ['aridian', 'diarian'], + 'aridly': ['aridly', 'lyraid'], + 'ariegite': ['aegirite', 'ariegite'], + 'aries': ['aries', 'arise', 'raise', 'serai'], + 'arietid': ['arietid', 'iridate'], + 'arietta': ['arietta', 'ratitae'], + 'aright': ['aright', 'graith'], + 'arightly': ['alrighty', 'arightly'], + 'ariidae': ['ariidae', 'raiidae'], + 'aril': ['aril', 'lair', 'lari', 'liar', 'lira', 'rail', 'rial'], + 'ariled': ['ariled', 'derail', 'dialer'], + 'arillate': ['arillate', 'tiarella'], + 'arion': ['arion', 'noria'], + 'ariot': ['ariot', 'ratio'], + 'aripple': ['applier', 'aripple'], + 'arise': ['aries', 'arise', 'raise', 'serai'], + 'arisen': ['arisen', 'arsine', 'resina', 'serian'], + 'arist': ['arist', + 'astir', + 'sitar', + 'stair', + 'stria', + 'tarsi', + 'tisar', + 'trias'], + 'arista': ['arista', 'tarsia'], + 'aristeas': ['aristeas', 'asterias'], + 'aristol': ['aristol', 'oralist', 'ortalis', 'striola'], + 'aristulate': ['aristulate', 'australite'], + 'arite': ['arite', 'artie', 'irate', 'retia', 'tarie'], + 'arithmic': ['arithmic', 'mithraic', 'mithriac'], + 'arius': ['arius', 'asuri'], + 'arizona': ['arizona', 'azorian', 'zonaria'], + 'ark': ['ark', 'kra'], + 'arkab': ['abkar', 'arkab'], + 'arkite': ['arkite', 'karite'], + 'arkose': ['arkose', 'resoak', 'soaker'], + 'arlene': ['arlene', 'leaner'], + 'arleng': ['angler', 'arleng', 'garnel', 'largen', 'rangle', 'regnal'], + 'arles': ['arles', 'arsle', 'laser', 'seral', 'slare'], + 'arline': ['arline', 'larine', 'linear', 'nailer', 'renail'], + 'arm': ['arm', 'mar', 'ram'], + 'armada': ['armada', 'damara', 'ramada'], + 'armangite': ['armangite', 'marginate'], + 'armata': ['armata', 'matara', 'tamara'], + 'armed': ['armed', 'derma', 'dream', 'ramed'], + 'armenian': ['armenian', 'marianne'], + 'armenic': ['armenic', 'carmine', 'ceriman', 'crimean', 'mercian'], + 'armer': ['armer', 'rearm'], + 'armeria': ['armeria', 'mararie'], + 'armet': ['armet', + 'mater', + 'merat', + 'metra', + 'ramet', + 'tamer', + 'terma', + 'trame', + 'trema'], + 'armful': ['armful', 'fulmar'], + 'armgaunt': ['armgaunt', 'granatum'], + 'armied': ['admire', 'armied', 'damier', 'dimera', 'merida'], + 'armiferous': ['armiferous', 'ramiferous'], + 'armigerous': ['armigerous', 'ramigerous'], + 'armil': ['armil', 'marli', 'rimal'], + 'armilla': ['armilla', 'marilla'], + 'armillated': ['armillated', 'malladrite', 'mallardite'], + 'arming': ['arming', 'ingram', 'margin'], + 'armistice': ['ameristic', 'armistice', 'artemisic'], + 'armlet': ['armlet', 'malter', 'martel'], + 'armonica': ['armonica', 'macaroni', 'marocain'], + 'armoried': ['airdrome', 'armoried'], + 'armpit': ['armpit', 'impart'], + 'armplate': ['armplate', 'malapert'], + 'arms': ['arms', 'mars'], + 'armscye': ['armscye', 'screamy'], + 'army': ['army', 'mary', 'myra', 'yarm'], + 'arn': ['arn', 'nar', 'ran'], + 'arna': ['arna', 'rana'], + 'arnaut': ['arnaut', 'arunta'], + 'arne': ['arne', 'earn', 'rane'], + 'arneb': ['abner', 'arneb', 'reban'], + 'arni': ['arni', 'iran', 'nair', 'rain', 'rani'], + 'arnica': ['acinar', + 'arnica', + 'canari', + 'carian', + 'carina', + 'crania', + 'narica'], + 'arnold': ['androl', 'arnold', 'lardon', 'roland', 'ronald'], + 'arnotta': ['arnotta', 'natator'], + 'arnotto': ['arnotto', 'notator'], + 'arnut': ['arnut', 'tuarn', 'untar'], + 'aro': ['aro', 'oar', 'ora'], + 'aroast': ['aroast', 'ostara'], + 'arock': ['arock', 'croak'], + 'aroid': ['aroid', 'doria', 'radio'], + 'aroides': ['ardoise', 'aroides', 'soredia'], + 'aroint': ['aroint', 'ration'], + 'aromatic': ['aromatic', 'macrotia'], + 'aroon': ['aroon', 'oraon'], + 'arose': ['arose', 'oreas'], + 'around': ['around', 'arundo'], + 'arpen': ['arpen', 'paren'], + 'arpent': ['arpent', + 'enrapt', + 'entrap', + 'panter', + 'parent', + 'pretan', + 'trepan'], + 'arrah': ['arhar', 'arrah'], + 'arras': ['arras', 'sarra'], + 'arrau': ['arrau', 'aurar'], + 'arrayer': ['arrayer', 'rearray'], + 'arrect': ['arrect', 'carter', 'crater', 'recart', 'tracer'], + 'arrector': ['arrector', 'carroter'], + 'arrent': ['arrent', 'errant', 'ranter', 'ternar'], + 'arrest': ['arrest', 'astrer', 'raster', 'starer'], + 'arrestable': ['arbalester', 'arbalestre', 'arrestable'], + 'arrester': ['arrester', 'rearrest'], + 'arresting': ['arresting', 'astringer'], + 'arretine': ['arretine', 'eretrian', 'eritrean', 'retainer'], + 'arride': ['arride', 'raider'], + 'arrie': ['airer', 'arrie'], + 'arriet': ['arriet', 'tarrie'], + 'arrish': ['arrish', 'harris', 'rarish', 'sirrah'], + 'arrive': ['arrive', 'varier'], + 'arrogance': ['arrogance', 'coarrange'], + 'arrogant': ['arrogant', 'tarragon'], + 'arrogative': ['arrogative', 'variegator'], + 'arrowy': ['arrowy', 'yarrow'], + 'arry': ['arry', 'yarr'], + 'arsacid': ['arsacid', 'ascarid'], + 'arse': ['arse', 'rase', 'sare', 'sear', 'sera'], + 'arsedine': ['arsedine', 'arsenide', 'sedanier', 'siderean'], + 'arsenal': ['arsenal', 'ranales'], + 'arsenate': ['arsenate', 'serenata'], + 'arsenation': ['arsenation', 'senatorian', 'sonneratia'], + 'arseniate': ['arseniate', 'saernaite'], + 'arsenic': ['arsenic', 'cerasin', 'sarcine'], + 'arsenide': ['arsedine', 'arsenide', 'sedanier', 'siderean'], + 'arsenite': ['arsenite', 'resinate', 'teresian', 'teresina'], + 'arsenium': ['aneurism', 'arsenium', 'sumerian'], + 'arseniuret': ['arseniuret', 'uniserrate'], + 'arseno': ['arseno', 'reason'], + 'arsenopyrite': ['arsenopyrite', 'pyroarsenite'], + 'arsenous': ['anserous', 'arsenous'], + 'arses': ['arses', 'rasse'], + 'arshine': ['arshine', 'nearish', 'rhesian', 'sherani'], + 'arsine': ['arisen', 'arsine', 'resina', 'serian'], + 'arsino': ['arsino', 'rasion', 'sonrai'], + 'arsis': ['arsis', 'sarsi'], + 'arsle': ['arles', 'arsle', 'laser', 'seral', 'slare'], + 'arson': ['arson', 'saron', 'sonar'], + 'arsonic': ['arsonic', 'saronic'], + 'arsonite': ['arsonite', 'asterion', 'oestrian', 'rosinate', 'serotina'], + 'art': ['art', 'rat', 'tar', 'tra'], + 'artaba': ['artaba', 'batara'], + 'artabe': ['abater', 'artabe', 'eartab', 'trabea'], + 'artal': ['altar', 'artal', 'ratal', 'talar'], + 'artamus': ['artamus', 'sumatra'], + 'artarine': ['artarine', 'errantia'], + 'artefact': ['afteract', 'artefact', 'farcetta', 'farctate'], + 'artel': ['alert', 'alter', 'artel', 'later', 'ratel', 'taler', 'telar'], + 'artemas': ['artemas', 'astream'], + 'artemia': ['ametria', 'artemia', 'meratia', 'ramaite'], + 'artemis': ['artemis', 'maestri', 'misrate'], + 'artemisic': ['ameristic', 'armistice', 'artemisic'], + 'arterial': ['arterial', 'triareal'], + 'arterin': ['arterin', 'retrain', 'terrain', 'trainer'], + 'arterious': ['arterious', 'autoriser'], + 'artesian': ['artesian', 'asterina', 'asternia', 'erastian', 'seatrain'], + 'artgum': ['artgum', 'targum'], + 'artha': ['arhat', 'artha', 'athar'], + 'arthel': ['arthel', 'halter', 'lather', 'thaler'], + 'arthemis': ['arthemis', 'marshite', 'meharist'], + 'arthrochondritis': ['arthrochondritis', 'chondroarthritis'], + 'arthromere': ['arthromere', 'metrorrhea'], + 'arthropodan': ['anarthropod', 'arthropodan'], + 'arthrosteitis': ['arthrosteitis', 'ostearthritis'], + 'article': ['article', 'recital'], + 'articled': ['articled', 'lacertid'], + 'artie': ['arite', 'artie', 'irate', 'retia', 'tarie'], + 'artifice': ['actifier', 'artifice'], + 'artisan': ['artisan', 'astrain', 'sartain', 'tsarina'], + 'artisanship': ['antiphrasis', 'artisanship'], + 'artist': ['artist', 'strait', 'strati'], + 'artiste': ['artiste', 'striate'], + 'artlet': ['artlet', 'latter', 'rattle', 'tartle', 'tatler'], + 'artlike': ['artlike', 'ratlike', 'tarlike'], + 'arty': ['arty', 'atry', 'tray'], + 'aru': ['aru', 'rua', 'ura'], + 'aruac': ['aruac', 'carua'], + 'arui': ['arui', 'uria'], + 'arum': ['arum', 'maru', 'mura'], + 'arundo': ['around', 'arundo'], + 'arunta': ['arnaut', 'arunta'], + 'arusa': ['arusa', 'saura', 'usara'], + 'arusha': ['arusha', 'aushar'], + 'arustle': ['arustle', 'estrual', 'saluter', 'saulter'], + 'arval': ['alvar', 'arval', 'larva'], + 'arvel': ['arvel', 'larve', 'laver', 'ravel', 'velar'], + 'arx': ['arx', 'rax'], + 'ary': ['ary', 'ray', 'yar'], + 'arya': ['arya', 'raya'], + 'aryan': ['aryan', 'nayar', 'rayan'], + 'aryl': ['aryl', 'lyra', 'ryal', 'yarl'], + 'as': ['as', 'sa'], + 'asa': ['asa', 'saa'], + 'asak': ['asak', 'kasa', 'saka'], + 'asana': ['anasa', 'asana'], + 'asaph': ['asaph', 'pasha'], + 'asaphia': ['aphasia', 'asaphia'], + 'asaphic': ['aphasic', 'asaphic'], + 'asaprol': ['asaprol', 'parasol'], + 'asarh': ['asarh', 'raash', 'sarah'], + 'asarite': ['asarite', 'asteria', 'atresia', 'setaria'], + 'asarum': ['aramus', 'asarum'], + 'asbest': ['asbest', 'basset'], + 'ascanius': ['anacusis', 'ascanius'], + 'ascare': ['ascare', 'caesar', 'resaca'], + 'ascarid': ['arsacid', 'ascarid'], + 'ascaris': ['ascaris', 'carissa'], + 'ascendance': ['adnascence', 'ascendance'], + 'ascendant': ['adnascent', 'ascendant'], + 'ascender': ['ascender', 'reascend'], + 'ascent': ['ascent', 'secant', 'stance'], + 'ascertain': ['ascertain', 'cartesian', 'cartisane', 'sectarian'], + 'ascertainer': ['ascertainer', 'reascertain', 'secretarian'], + 'ascetic': ['ascetic', 'castice', 'siccate'], + 'ascham': ['ascham', 'chasma'], + 'asci': ['acis', 'asci', 'saic'], + 'ascian': ['ascian', 'sacian', 'scania', 'sicana'], + 'ascidia': ['ascidia', 'diascia'], + 'ascii': ['ascii', 'isiac'], + 'ascites': ['ascites', 'ectasis'], + 'ascitic': ['ascitic', 'sciatic'], + 'ascitical': ['ascitical', 'sciatical'], + 'asclent': ['asclent', 'scantle'], + 'asclepian': ['asclepian', 'spalacine'], + 'ascolichen': ['ascolichen', 'chalcosine'], + 'ascon': ['ascon', 'canso', 'oscan'], + 'ascot': ['ascot', 'coast', 'costa', 'tacso', 'tasco'], + 'ascription': ['antipsoric', 'ascription', 'crispation'], + 'ascry': ['ascry', 'scary', 'scray'], + 'ascula': ['ascula', 'calusa', 'casual', 'casula', 'causal'], + 'asdic': ['asdic', 'sadic'], + 'ase': ['aes', 'ase', 'sea'], + 'asearch': ['asearch', 'eschara'], + 'aselli': ['allies', 'aselli'], + 'asem': ['asem', 'mesa', 'same', 'seam'], + 'asemia': ['asemia', 'saeima'], + 'aseptic': ['aseptic', 'spicate'], + 'aseptol': ['apostle', 'aseptol'], + 'ash': ['ash', 'sah', 'sha'], + 'ashanti': ['ashanti', 'sanhita', 'shaitan', 'thasian'], + 'ashen': ['ashen', 'hanse', 'shane', 'shean'], + 'asher': ['asher', 'share', 'shear'], + 'ashet': ['ashet', 'haste', 'sheat'], + 'ashimmer': ['ashimmer', 'haremism'], + 'ashir': ['ashir', 'shari'], + 'ashling': ['anglish', 'ashling'], + 'ashman': ['ashman', 'shaman'], + 'ashore': ['ahorse', 'ashore', 'hoarse', 'shorea'], + 'ashraf': ['afshar', 'ashraf'], + 'ashur': ['ashur', 'surah'], + 'ashy': ['ashy', 'shay'], + 'asian': ['asian', 'naias', 'sanai'], + 'asiarch': ['arachis', 'asiarch', 'saharic'], + 'aside': ['aides', 'aside', 'sadie'], + 'asideu': ['asideu', 'suidae'], + 'asiento': ['aeonist', 'asiento', 'satieno'], + 'asilid': ['asilid', 'sialid'], + 'asilidae': ['asilidae', 'sialidae'], + 'asilus': ['asilus', 'lasius'], + 'asimen': ['asimen', 'inseam', 'mesian'], + 'asimmer': ['amerism', 'asimmer', 'sammier'], + 'asiphonate': ['asiphonate', 'asthenopia'], + 'ask': ['ask', 'sak'], + 'asker': ['asker', 'reask', 'saker', 'sekar'], + 'askew': ['askew', 'wakes'], + 'askip': ['askip', 'spaik'], + 'askr': ['askr', 'kras', 'sark'], + 'aslant': ['aslant', 'lansat', 'natals', 'santal'], + 'asleep': ['asleep', 'elapse', 'please'], + 'aslope': ['aslope', 'poales'], + 'asmalte': ['asmalte', 'maltase'], + 'asmile': ['amiles', 'asmile', 'mesail', 'mesial', 'samiel'], + 'asnort': ['asnort', 'satron'], + 'asoak': ['asoak', 'asoka'], + 'asok': ['asok', 'soak', 'soka'], + 'asoka': ['asoak', 'asoka'], + 'asonia': ['anosia', 'asonia'], + 'asop': ['asop', 'sapo', 'soap'], + 'asor': ['asor', 'rosa', 'soar', 'sora'], + 'asp': ['asp', 'sap', 'spa'], + 'aspartic': ['aspartic', 'satrapic'], + 'aspection': ['aspection', 'stenopaic'], + 'aspectual': ['aspectual', 'capsulate'], + 'aspen': ['aspen', 'panse', 'snape', 'sneap', 'spane', 'spean'], + 'asper': ['asper', 'parse', 'prase', 'spaer', 'spare', 'spear'], + 'asperate': ['asperate', 'separate'], + 'asperation': ['anisoptera', 'asperation', 'separation'], + 'asperge': ['asperge', 'presage'], + 'asperger': ['asperger', 'presager'], + 'aspergil': ['aspergil', 'splairge'], + 'asperite': ['asperite', 'parietes'], + 'aspermia': ['aspermia', 'sapremia'], + 'aspermic': ['aspermic', 'sapremic'], + 'asperser': ['asperser', 'repasser'], + 'asperulous': ['asperulous', 'pleasurous'], + 'asphalt': ['asphalt', 'spathal', 'taplash'], + 'aspic': ['aspic', 'spica'], + 'aspidinol': ['aspidinol', 'diplasion'], + 'aspirant': ['aspirant', 'partisan', 'spartina'], + 'aspirata': ['aspirata', 'parasita'], + 'aspirate': ['aspirate', 'parasite'], + 'aspire': ['aspire', 'paries', 'praise', 'sirpea', 'spirea'], + 'aspirer': ['aspirer', 'praiser', 'serpari'], + 'aspiring': ['aspiring', 'praising', 'singarip'], + 'aspiringly': ['aspiringly', 'praisingly'], + 'aspish': ['aspish', 'phasis'], + 'asporous': ['asporous', 'saporous'], + 'asport': ['asport', 'pastor', 'sproat'], + 'aspread': ['aspread', 'saperda'], + 'aspring': ['aspring', 'rasping', 'sparing'], + 'asquirm': ['asquirm', 'marquis'], + 'assagai': ['assagai', 'gaiassa'], + 'assailer': ['assailer', 'reassail'], + 'assam': ['amass', 'assam', 'massa', 'samas'], + 'assaulter': ['assaulter', 'reassault', 'saleratus'], + 'assayer': ['assayer', 'reassay'], + 'assemble': ['assemble', 'beamless'], + 'assent': ['assent', 'snaste'], + 'assenter': ['assenter', 'reassent', 'sarsenet'], + 'assentor': ['assentor', 'essorant', 'starnose'], + 'assert': ['assert', 'tasser'], + 'asserter': ['asserter', 'reassert'], + 'assertible': ['assertible', 'resistable'], + 'assertional': ['assertional', 'sensatorial'], + 'assertor': ['assertor', 'assorter', 'oratress', 'reassort'], + 'asset': ['asset', 'tasse'], + 'assets': ['assets', 'stases'], + 'assidean': ['assidean', 'nassidae'], + 'assiento': ['assiento', 'ossetian'], + 'assignee': ['agenesis', 'assignee'], + 'assigner': ['assigner', 'reassign'], + 'assist': ['assist', 'stasis'], + 'assister': ['assister', 'reassist'], + 'associationism': ['associationism', 'misassociation'], + 'assoilment': ['assoilment', 'salmonsite'], + 'assorter': ['assertor', 'assorter', 'oratress', 'reassort'], + 'assuage': ['assuage', 'sausage'], + 'assume': ['assume', 'seamus'], + 'assumer': ['assumer', 'erasmus', 'masseur'], + 'ast': ['ast', 'sat'], + 'astacus': ['acastus', 'astacus'], + 'astare': ['astare', 'satrae'], + 'astart': ['astart', 'strata'], + 'astartian': ['astartian', 'astrantia'], + 'astatine': ['astatine', 'sanitate'], + 'asteep': ['asteep', 'peseta'], + 'asteer': ['asteer', + 'easter', + 'eastre', + 'reseat', + 'saeter', + 'seater', + 'staree', + 'teaser', + 'teresa'], + 'astelic': ['astelic', 'elastic', 'latices'], + 'astely': ['alytes', 'astely', 'lysate', 'stealy'], + 'aster': ['aster', 'serta', 'stare', 'strae', 'tarse', 'teras'], + 'asteria': ['asarite', 'asteria', 'atresia', 'setaria'], + 'asterias': ['aristeas', 'asterias'], + 'asterikos': ['asterikos', 'keratosis'], + 'asterin': ['asterin', 'eranist', 'restain', 'stainer', 'starnie', 'stearin'], + 'asterina': ['artesian', 'asterina', 'asternia', 'erastian', 'seatrain'], + 'asterion': ['arsonite', 'asterion', 'oestrian', 'rosinate', 'serotina'], + 'astern': ['astern', 'enstar', 'stenar', 'sterna'], + 'asternia': ['artesian', 'asterina', 'asternia', 'erastian', 'seatrain'], + 'asteroid': ['asteroid', 'troiades'], + 'asterope': ['asterope', 'protease'], + 'asthenopia': ['asiphonate', 'asthenopia'], + 'asthma': ['amsath', 'asthma'], + 'asthmogenic': ['asthmogenic', 'mesognathic'], + 'asthore': ['asthore', 'earshot'], + 'astian': ['astian', 'tasian'], + 'astigmism': ['astigmism', 'sigmatism'], + 'astilbe': ['astilbe', 'bestial', 'blastie', 'stabile'], + 'astint': ['astint', 'tanist'], + 'astir': ['arist', + 'astir', + 'sitar', + 'stair', + 'stria', + 'tarsi', + 'tisar', + 'trias'], + 'astomous': ['astomous', 'somatous'], + 'astonied': ['astonied', 'sedation'], + 'astonisher': ['astonisher', 'reastonish', 'treasonish'], + 'astor': ['astor', 'roast'], + 'astragali': ['astragali', 'tarsalgia'], + 'astrain': ['artisan', 'astrain', 'sartain', 'tsarina'], + 'astral': ['astral', 'tarsal'], + 'astrantia': ['astartian', 'astrantia'], + 'astream': ['artemas', 'astream'], + 'astrer': ['arrest', 'astrer', 'raster', 'starer'], + 'astrict': ['astrict', 'cartist', 'stratic'], + 'astride': ['astride', 'diaster', 'disrate', 'restiad', 'staired'], + 'astrier': ['astrier', 'tarsier'], + 'astringe': ['astringe', 'ganister', 'gantries'], + 'astringent': ['astringent', 'transigent'], + 'astringer': ['arresting', 'astringer'], + 'astrodome': ['astrodome', 'roomstead'], + 'astrofel': ['astrofel', 'forestal'], + 'astroite': ['astroite', 'ostraite', 'storiate'], + 'astrolabe': ['astrolabe', 'roastable'], + 'astrut': ['astrut', 'rattus', 'stuart'], + 'astur': ['astur', 'surat', 'sutra'], + 'asturian': ['asturian', 'austrian', 'saturnia'], + 'astute': ['astute', 'statue'], + 'astylar': ['astylar', 'saltary'], + 'asunder': ['asunder', 'drusean'], + 'asuri': ['arius', 'asuri'], + 'aswail': ['aswail', 'sawali'], + 'asweat': ['asweat', 'awaste'], + 'aswim': ['aswim', 'swami'], + 'aswing': ['aswing', 'sawing'], + 'asyla': ['asyla', 'salay', 'sayal'], + 'asyllabic': ['asyllabic', 'basically'], + 'asyndetic': ['asyndetic', 'cystidean', 'syndicate'], + 'asynergia': ['asynergia', 'gainsayer'], + 'at': ['at', 'ta'], + 'ata': ['ata', 'taa'], + 'atabal': ['albata', 'atabal', 'balata'], + 'atabrine': ['atabrine', 'rabatine'], + 'atacaman': ['atacaman', 'tamanaca'], + 'ataentsic': ['anticaste', 'ataentsic'], + 'atalan': ['atalan', 'tanala'], + 'atap': ['atap', 'pata', 'tapa'], + 'atazir': ['atazir', 'ziarat'], + 'atchison': ['atchison', 'chitosan'], + 'ate': ['ate', 'eat', 'eta', 'tae', 'tea'], + 'ateba': ['abate', 'ateba', 'batea', 'beata'], + 'atebrin': ['atebrin', 'rabinet'], + 'atechnic': ['atechnic', 'catechin', 'technica'], + 'atechny': ['atechny', 'chantey'], + 'ateeter': ['ateeter', 'treatee'], + 'atef': ['atef', 'fate', 'feat'], + 'ateles': ['ateles', 'saltee', 'sealet', 'stelae', 'teasel'], + 'atelets': ['atelets', 'tsatlee'], + 'atelier': ['atelier', 'tiralee'], + 'aten': ['ante', 'aten', 'etna', 'nate', 'neat', 'taen', 'tane', 'tean'], + 'atenism': ['atenism', 'inmeats', 'insteam', 'samnite'], + 'atenist': ['atenist', 'instate', 'satient', 'steatin'], + 'ates': ['ates', 'east', 'eats', 'sate', 'seat', 'seta'], + 'atestine': ['anisette', 'atestine', 'settaine'], + 'athar': ['arhat', 'artha', 'athar'], + 'atheism': ['atheism', 'hamites'], + 'athena': ['ahtena', 'aneath', 'athena'], + 'athenian': ['anthinae', 'athenian'], + 'athenor': ['another', 'athenor', 'rheotan'], + 'athens': ['athens', 'hasten', 'snathe', 'sneath'], + 'atherine': ['atherine', 'herniate'], + 'atheris': ['atheris', 'sheriat'], + 'athermic': ['athermic', 'marchite', 'rhematic'], + 'athing': ['anight', 'athing'], + 'athirst': ['athirst', 'rattish', 'tartish'], + 'athletic': ['athletic', 'thetical'], + 'athletics': ['athletics', 'statelich'], + 'athort': ['athort', 'throat'], + 'athrive': ['athrive', 'hervati'], + 'ati': ['ait', 'ati', 'ita', 'tai'], + 'atik': ['atik', 'ikat'], + 'atimon': ['atimon', 'manito', 'montia'], + 'atingle': ['atingle', 'gelatin', 'genital', 'langite', 'telinga'], + 'atip': ['atip', 'pita'], + 'atis': ['atis', 'sita', 'tsia'], + 'atlantean': ['antenatal', 'atlantean', 'tantalean'], + 'atlantic': ['atlantic', 'tantalic'], + 'atlantid': ['atlantid', 'dilatant'], + 'atlantite': ['atlantite', 'tantalite'], + 'atlas': ['atlas', 'salat', 'salta'], + 'atle': ['atle', 'laet', 'late', 'leat', 'tael', 'tale', 'teal'], + 'atlee': ['atlee', 'elate'], + 'atloidean': ['atloidean', 'dealation'], + 'atma': ['atma', 'tama'], + 'atman': ['atman', 'manta'], + 'atmid': ['admit', 'atmid'], + 'atmo': ['atmo', 'atom', 'moat', 'toma'], + 'atmogenic': ['atmogenic', 'geomantic'], + 'atmos': ['atmos', 'stoma', 'tomas'], + 'atmosphere': ['atmosphere', 'shapometer'], + 'atmostea': ['atmostea', 'steatoma'], + 'atnah': ['atnah', 'tanha', 'thana'], + 'atocia': ['atocia', 'coaita'], + 'atokal': ['atokal', 'lakota'], + 'atoll': ['allot', 'atoll'], + 'atom': ['atmo', 'atom', 'moat', 'toma'], + 'atomic': ['atomic', 'matico'], + 'atomics': ['atomics', 'catoism', 'cosmati', 'osmatic', 'somatic'], + 'atomize': ['atomize', 'miaotze'], + 'atomizer': ['amortize', 'atomizer'], + 'atonal': ['atonal', 'latona'], + 'atonalism': ['anomalist', 'atonalism'], + 'atone': ['atone', 'oaten'], + 'atoner': ['atoner', 'norate', 'ornate'], + 'atonia': ['anotia', 'atonia'], + 'atonic': ['action', 'atonic', 'cation'], + 'atony': ['atony', 'ayont'], + 'atop': ['atop', 'pato'], + 'atopic': ['atopic', 'capito', 'copita'], + 'atorai': ['atorai', 'otaria'], + 'atrail': ['altair', 'atrail', 'atrial', 'lariat', 'latria', 'talari'], + 'atrepsy': ['atrepsy', 'yapster'], + 'atresia': ['asarite', 'asteria', 'atresia', 'setaria'], + 'atresic': ['atresic', 'stearic'], + 'atresy': ['atresy', 'estray', 'reasty', 'stayer'], + 'atretic': ['atretic', 'citrate'], + 'atria': ['arati', 'atria', 'riata', 'tarai', 'tiara'], + 'atrial': ['altair', 'atrail', 'atrial', 'lariat', 'latria', 'talari'], + 'atridean': ['anteriad', 'atridean', 'dentaria'], + 'atrip': ['atrip', 'tapir'], + 'atrocity': ['atrocity', 'citatory'], + 'atrophied': ['aphrodite', 'atrophied', 'diaporthe'], + 'atropia': ['apiator', 'atropia', 'parotia'], + 'atropic': ['apricot', 'atropic', 'parotic', 'patrico'], + 'atroscine': ['atroscine', 'certosina', 'ostracine', 'tinoceras', 'tricosane'], + 'atry': ['arty', 'atry', 'tray'], + 'attacco': ['attacco', 'toccata'], + 'attach': ['attach', 'chatta'], + 'attache': ['attache', 'thecata'], + 'attacher': ['attacher', 'reattach'], + 'attacker': ['attacker', 'reattack'], + 'attain': ['attain', 'tatian'], + 'attainder': ['antitrade', 'attainder'], + 'attainer': ['attainer', 'reattain', 'tertiana'], + 'attar': ['attar', 'tatar'], + 'attempter': ['attempter', 'reattempt'], + 'attender': ['attender', 'nattered', 'reattend'], + 'attention': ['attention', 'tentation'], + 'attentive': ['attentive', 'tentative'], + 'attentively': ['attentively', 'tentatively'], + 'attentiveness': ['attentiveness', 'tentativeness'], + 'atter': ['atter', 'tater', 'teart', 'tetra', 'treat'], + 'attermine': ['antimeter', 'attermine', 'interteam', 'terminate', 'tetramine'], + 'attern': ['attern', 'natter', 'ratten', 'tarten'], + 'attery': ['attery', 'treaty', 'yatter'], + 'attester': ['attester', 'reattest'], + 'attic': ['attic', 'catti', 'tacit'], + 'attical': ['attical', 'cattail'], + 'attinge': ['attinge', 'tintage'], + 'attire': ['attire', 'ratite', 'tertia'], + 'attired': ['attired', 'tradite'], + 'attorn': ['attorn', 'ratton', 'rottan'], + 'attracter': ['attracter', 'reattract'], + 'attractor': ['attractor', 'tractator'], + 'attrite': ['attrite', 'titrate'], + 'attrition': ['attrition', 'titration'], + 'attune': ['attune', 'nutate', 'tauten'], + 'atule': ['aleut', 'atule'], + 'atumble': ['atumble', 'mutable'], + 'atwin': ['atwin', 'twain', 'witan'], + 'atypic': ['atypic', 'typica'], + 'aube': ['aube', 'beau'], + 'aubrite': ['abiuret', 'aubrite', 'biurate', 'rubiate'], + 'aucan': ['acuan', 'aucan'], + 'aucaner': ['arecuna', 'aucaner'], + 'auchlet': ['auchlet', 'cutheal', 'taluche'], + 'auction': ['auction', 'caution'], + 'auctionary': ['auctionary', 'cautionary'], + 'audiencier': ['audiencier', 'enicuridae'], + 'auge': ['ague', 'auge'], + 'augen': ['augen', 'genua'], + 'augend': ['augend', 'engaud', 'unaged'], + 'auger': ['argue', 'auger'], + 'augerer': ['augerer', 'reargue'], + 'augh': ['augh', 'guha'], + 'augmenter': ['argenteum', 'augmenter'], + 'augustan': ['augustan', 'guatusan'], + 'auh': ['ahu', 'auh', 'hau'], + 'auk': ['aku', 'auk', 'kua'], + 'auld': ['auld', 'dual', 'laud', 'udal'], + 'aulete': ['aulete', 'eluate'], + 'auletic': ['aleutic', 'auletic', 'caulite', 'lutecia'], + 'auletris': ['auletris', 'lisuarte'], + 'aulic': ['aulic', 'lucia'], + 'aulostoma': ['aulostoma', 'autosomal'], + 'aulu': ['aulu', 'ulua'], + 'aum': ['aum', 'mau'], + 'aumbry': ['ambury', 'aumbry'], + 'aumil': ['aumil', 'miaul'], + 'aumrie': ['aumrie', 'uremia'], + 'auncel': ['auncel', 'cuneal', 'lacune', 'launce', 'unlace'], + 'aunt': ['antu', 'aunt', 'naut', 'taun', 'tuan', 'tuna'], + 'auntie': ['auntie', 'uniate'], + 'auntish': ['auntish', 'inhaust'], + 'auntly': ['auntly', 'lutany'], + 'auntsary': ['auntsary', 'unastray'], + 'aura': ['aaru', 'aura'], + 'aural': ['aural', 'laura'], + 'aurar': ['arrau', 'aurar'], + 'auresca': ['auresca', 'caesura'], + 'aureus': ['aureus', 'uraeus'], + 'auricle': ['auricle', 'ciruela'], + 'auricled': ['auricled', 'radicule'], + 'auride': ['auride', 'rideau'], + 'aurin': ['aurin', 'urian'], + 'aurir': ['aurir', 'urari'], + 'auriscalp': ['auriscalp', 'spiracula'], + 'auscult': ['auscult', 'scutula'], + 'aushar': ['arusha', 'aushar'], + 'auster': ['auster', 'reatus'], + 'austere': ['austere', 'euaster'], + 'australian': ['australian', 'saturnalia'], + 'australic': ['australic', 'lactarius'], + 'australite': ['aristulate', 'australite'], + 'austrian': ['asturian', 'austrian', 'saturnia'], + 'aute': ['aute', 'etua'], + 'autecism': ['autecism', 'musicate'], + 'authotype': ['authotype', 'autophyte'], + 'autoclave': ['autoclave', 'vacuolate'], + 'autocrat': ['actuator', 'autocrat'], + 'autoheterosis': ['autoheterosis', 'heteroousiast'], + 'autometric': ['autometric', 'tautomeric'], + 'autometry': ['autometry', 'tautomery'], + 'autophyte': ['authotype', 'autophyte'], + 'autoplast': ['autoplast', 'postulata'], + 'autopsic': ['autopsic', 'captious'], + 'autopsical': ['apolaustic', 'autopsical'], + 'autoradiograph': ['autoradiograph', 'radioautograph'], + 'autoradiographic': ['autoradiographic', 'radioautographic'], + 'autoradiography': ['autoradiography', 'radioautography'], + 'autoriser': ['arterious', 'autoriser'], + 'autosomal': ['aulostoma', 'autosomal'], + 'auxetic': ['auxetic', 'eutaxic'], + 'aval': ['aval', 'lava'], + 'avanti': ['avanti', 'vinata'], + 'avar': ['avar', 'vara'], + 'ave': ['ave', 'eva'], + 'avenge': ['avenge', 'geneva', 'vangee'], + 'avenger': ['avenger', 'engrave'], + 'avenin': ['avenin', 'vienna'], + 'aventine': ['aventine', 'venetian'], + 'aventurine': ['aventurine', 'uninervate'], + 'aver': ['aver', 'rave', 'vare', 'vera'], + 'avera': ['avera', 'erava'], + 'averil': ['averil', 'elvira'], + 'averin': ['averin', 'ravine'], + 'avert': ['avert', 'tarve', 'taver', 'trave'], + 'avertible': ['avertible', 'veritable'], + 'avertin': ['avertin', 'vitrean'], + 'aves': ['aves', 'save', 'vase'], + 'aviatic': ['aviatic', 'viatica'], + 'aviator': ['aviator', 'tovaria'], + 'avicular': ['avicular', 'varicula'], + 'avid': ['avid', 'diva'], + 'avidous': ['avidous', 'vaudois'], + 'avignonese': ['avignonese', 'ingaevones'], + 'avine': ['avine', 'naive', 'vinea'], + 'avirulence': ['acervuline', 'avirulence'], + 'avis': ['avis', 'siva', 'visa'], + 'avitic': ['avitic', 'viatic'], + 'avo': ['avo', 'ova'], + 'avocet': ['avocet', 'octave', 'vocate'], + 'avodire': ['avodire', 'avoider', 'reavoid'], + 'avoider': ['avodire', 'avoider', 'reavoid'], + 'avolation': ['avolation', 'ovational'], + 'avolitional': ['avolitional', 'violational'], + 'avoucher': ['avoucher', 'reavouch'], + 'avower': ['avower', 'reavow'], + 'avshar': ['avshar', 'varsha'], + 'avulse': ['alveus', 'avulse'], + 'aw': ['aw', 'wa'], + 'awag': ['awag', 'waag'], + 'awaiter': ['awaiter', 'reawait'], + 'awakener': ['awakener', 'reawaken'], + 'awarder': ['awarder', 'reaward'], + 'awash': ['awash', 'sawah'], + 'awaste': ['asweat', 'awaste'], + 'awat': ['awat', 'tawa'], + 'awd': ['awd', 'daw', 'wad'], + 'awe': ['awe', 'wae', 'wea'], + 'aweather': ['aweather', 'wheatear'], + 'aweek': ['aweek', 'keawe'], + 'awesome': ['awesome', 'waesome'], + 'awest': ['awest', 'sweat', 'tawse', 'waste'], + 'awfu': ['awfu', 'wauf'], + 'awful': ['awful', 'fulwa'], + 'awhet': ['awhet', 'wheat'], + 'awin': ['awin', 'wain'], + 'awing': ['awing', 'wigan'], + 'awl': ['awl', 'law'], + 'awn': ['awn', 'naw', 'wan'], + 'awned': ['awned', 'dewan', 'waned'], + 'awner': ['awner', 'newar'], + 'awning': ['awning', 'waning'], + 'awny': ['awny', 'wany', 'yawn'], + 'awol': ['alow', 'awol', 'lowa'], + 'awork': ['awork', 'korwa'], + 'awreck': ['awreck', 'wacker'], + 'awrong': ['awrong', 'growan'], + 'awry': ['awry', 'wary'], + 'axel': ['alex', 'axel', 'axle'], + 'axes': ['axes', 'saxe', 'seax'], + 'axil': ['alix', 'axil'], + 'axile': ['axile', 'lexia'], + 'axine': ['axine', 'xenia'], + 'axle': ['alex', 'axel', 'axle'], + 'axon': ['axon', 'noxa', 'oxan'], + 'axonal': ['axonal', 'oxalan'], + 'axonia': ['anoxia', 'axonia'], + 'ay': ['ay', 'ya'], + 'ayah': ['ayah', 'haya'], + 'aye': ['aye', 'yea'], + 'ayont': ['atony', 'ayont'], + 'azimine': ['aminize', 'animize', 'azimine'], + 'azo': ['azo', 'zoa'], + 'azole': ['azole', 'zoeal'], + 'azon': ['azon', 'onza', 'ozan'], + 'azorian': ['arizona', 'azorian', 'zonaria'], + 'azorite': ['azorite', 'zoarite'], + 'azoxine': ['azoxine', 'oxazine'], + 'azteca': ['azteca', 'zacate'], + 'azurine': ['azurine', 'urazine'], + 'ba': ['ab', 'ba'], + 'baa': ['aba', 'baa'], + 'baal': ['alba', 'baal', 'bala'], + 'baalath': ['baalath', 'bathala'], + 'baalite': ['baalite', 'bialate', 'labiate'], + 'baalshem': ['baalshem', 'shamable'], + 'baar': ['arab', 'arba', 'baar', 'bara'], + 'bab': ['abb', 'bab'], + 'baba': ['abba', 'baba'], + 'babbler': ['babbler', 'blabber', 'brabble'], + 'babery': ['babery', 'yabber'], + 'babhan': ['babhan', 'habnab'], + 'babishly': ['babishly', 'shabbily'], + 'babishness': ['babishness', 'shabbiness'], + 'babite': ['babite', 'bebait'], + 'babu': ['babu', 'buba'], + 'babul': ['babul', 'bubal'], + 'baby': ['abby', 'baby'], + 'babylonish': ['babylonish', 'nabobishly'], + 'bac': ['bac', 'cab'], + 'bacao': ['bacao', 'caoba'], + 'bach': ['bach', 'chab'], + 'bache': ['bache', 'beach'], + 'bachel': ['bachel', 'bleach'], + 'bachelor': ['bachelor', 'crabhole'], + 'bacillar': ['bacillar', 'cabrilla'], + 'bacis': ['bacis', 'basic'], + 'backblow': ['backblow', 'blowback'], + 'backen': ['backen', 'neback'], + 'backer': ['backer', 'reback'], + 'backfall': ['backfall', 'fallback'], + 'backfire': ['backfire', 'fireback'], + 'backlog': ['backlog', 'gablock'], + 'backrun': ['backrun', 'runback'], + 'backsaw': ['backsaw', 'sawback'], + 'backset': ['backset', 'setback'], + 'backstop': ['backstop', 'stopback'], + 'backswing': ['backswing', 'swingback'], + 'backward': ['backward', 'drawback'], + 'backway': ['backway', 'wayback'], + 'bacon': ['bacon', 'banco'], + 'bacterial': ['bacterial', 'calibrate'], + 'bacteriform': ['bacteriform', 'bracteiform'], + 'bacterin': ['bacterin', 'centibar'], + 'bacterioid': ['aborticide', 'bacterioid'], + 'bacterium': ['bacterium', 'cumbraite'], + 'bactrian': ['bactrian', 'cantabri'], + 'bacula': ['albuca', 'bacula'], + 'baculi': ['abulic', 'baculi'], + 'baculite': ['baculite', 'cubitale'], + 'baculites': ['baculites', 'bisulcate'], + 'baculoid': ['baculoid', 'cuboidal'], + 'bad': ['bad', 'dab'], + 'badaga': ['badaga', 'dagaba', 'gadaba'], + 'badan': ['badan', 'banda'], + 'bade': ['abed', 'bade', 'bead'], + 'badge': ['badge', 'begad'], + 'badian': ['badian', 'indaba'], + 'badigeon': ['badigeon', 'gabioned'], + 'badly': ['badly', 'baldy', 'blady'], + 'badon': ['badon', 'bando'], + 'bae': ['abe', 'bae', 'bea'], + 'baeria': ['aberia', 'baeria', 'baiera'], + 'baetulus': ['baetulus', 'subulate'], + 'baetyl': ['baetyl', 'baylet', 'bleaty'], + 'baetylic': ['baetylic', 'biacetyl'], + 'bafta': ['abaft', 'bafta'], + 'bag': ['bag', 'gab'], + 'bagani': ['bagani', 'bangia', 'ibanag'], + 'bagel': ['bagel', 'belga', 'gable', 'gleba'], + 'bagger': ['bagger', 'beggar'], + 'bagnio': ['bagnio', 'gabion', 'gobian'], + 'bago': ['bago', 'boga'], + 'bagre': ['bagre', 'barge', 'begar', 'rebag'], + 'bahar': ['bahar', 'bhara'], + 'bahoe': ['bahoe', 'bohea', 'obeah'], + 'baht': ['baht', 'bath', 'bhat'], + 'baiera': ['aberia', 'baeria', 'baiera'], + 'baignet': ['baignet', 'beating'], + 'bail': ['albi', 'bail', 'bali'], + 'bailage': ['algieba', 'bailage'], + 'bailer': ['bailer', 'barile'], + 'baillone': ['baillone', 'bonellia'], + 'bailment': ['bailment', 'libament'], + 'bailor': ['bailor', 'bioral'], + 'bailsman': ['bailsman', 'balanism', 'nabalism'], + 'bain': ['bain', 'bani', 'iban'], + 'baioc': ['baioc', 'cabio', 'cobia'], + 'bairam': ['bairam', 'bramia'], + 'bairn': ['abrin', 'bairn', 'brain', 'brian', 'rabin'], + 'bairnie': ['aribine', 'bairnie', 'iberian'], + 'bairnish': ['bairnish', 'bisharin'], + 'bais': ['absi', 'bais', 'bias', 'isba'], + 'baister': ['baister', 'tribase'], + 'baiter': ['baiter', 'barite', 'rebait', 'terbia'], + 'baith': ['baith', 'habit'], + 'bajocian': ['bajocian', 'jacobian'], + 'bakal': ['bakal', 'balak'], + 'bakatan': ['bakatan', 'batakan'], + 'bake': ['bake', 'beak'], + 'baker': ['baker', 'brake', 'break'], + 'bakerless': ['bakerless', 'brakeless', 'breakless'], + 'bakery': ['bakery', 'barkey'], + 'bakie': ['akebi', 'bakie'], + 'baku': ['baku', 'kuba'], + 'bal': ['alb', 'bal', 'lab'], + 'bala': ['alba', 'baal', 'bala'], + 'baladine': ['baladine', 'balaenid'], + 'balaenid': ['baladine', 'balaenid'], + 'balagan': ['balagan', 'bangala'], + 'balai': ['balai', 'labia'], + 'balak': ['bakal', 'balak'], + 'balan': ['alban', 'balan', 'banal', 'laban', 'nabal', 'nabla'], + 'balancer': ['balancer', 'barnacle'], + 'balangay': ['balangay', 'bangalay'], + 'balanic': ['balanic', 'caliban'], + 'balanid': ['balanid', 'banilad'], + 'balanism': ['bailsman', 'balanism', 'nabalism'], + 'balanite': ['albanite', 'balanite', 'nabalite'], + 'balanites': ['balanites', 'basaltine', 'stainable'], + 'balantidium': ['antialbumid', 'balantidium'], + 'balanus': ['balanus', 'nabalus', 'subanal'], + 'balas': ['balas', 'balsa', 'basal', 'sabal'], + 'balata': ['albata', 'atabal', 'balata'], + 'balatron': ['balatron', 'laborant'], + 'balaustine': ['balaustine', 'unsatiable'], + 'balaustre': ['balaustre', 'saturable'], + 'bald': ['bald', 'blad'], + 'balden': ['balden', 'bandle'], + 'balder': ['balder', 'bardel', 'bedlar', 'bedral', 'belard', 'blader'], + 'baldie': ['abdiel', 'baldie'], + 'baldish': ['baldish', 'bladish'], + 'baldmoney': ['baldmoney', 'molybdena'], + 'baldness': ['baldness', 'bandless'], + 'baldy': ['badly', 'baldy', 'blady'], + 'bale': ['abel', 'able', 'albe', 'bale', 'beal', 'bela', 'blae'], + 'balearic': ['balearic', 'cebalrai'], + 'baleen': ['baleen', 'enable'], + 'balefire': ['afebrile', 'balefire', 'fireable'], + 'baleise': ['baleise', 'besaiel'], + 'baler': ['abler', 'baler', 'belar', 'blare', 'blear'], + 'balete': ['balete', 'belate'], + 'bali': ['albi', 'bail', 'bali'], + 'baline': ['baline', 'blaine'], + 'balinger': ['balinger', 'ringable'], + 'balker': ['balker', 'barkle'], + 'ballaster': ['ballaster', 'reballast'], + 'ballate': ['ballate', 'tabella'], + 'balli': ['balli', 'billa'], + 'balloter': ['balloter', 'reballot'], + 'ballplayer': ['ballplayer', 'preallably'], + 'ballroom': ['ballroom', 'moorball'], + 'ballweed': ['ballweed', 'weldable'], + 'balm': ['balm', 'lamb'], + 'balminess': ['balminess', 'lambiness'], + 'balmlike': ['balmlike', 'lamblike'], + 'balmy': ['balmy', 'lamby'], + 'balolo': ['balolo', 'lobola'], + 'balonea': ['abalone', 'balonea'], + 'balor': ['balor', 'bolar', 'boral', 'labor', 'lobar'], + 'balow': ['ablow', 'balow', 'bowla'], + 'balsa': ['balas', 'balsa', 'basal', 'sabal'], + 'balsam': ['balsam', 'sambal'], + 'balsamic': ['balsamic', 'cabalism'], + 'balsamo': ['absalom', 'balsamo'], + 'balsamy': ['abysmal', 'balsamy'], + 'balt': ['balt', 'blat'], + 'baltei': ['albeit', + 'albite', + 'baltei', + 'belait', + 'betail', + 'bletia', + 'libate'], + 'balter': ['albert', 'balter', 'labret', 'tabler'], + 'balteus': ['balteus', 'sublate'], + 'baltis': ['baltis', 'bisalt'], + 'balu': ['balu', 'baul', 'bual', 'luba'], + 'balunda': ['balunda', 'bulanda'], + 'baluster': ['baluster', 'rustable'], + 'balut': ['balut', 'tubal'], + 'bam': ['bam', 'mab'], + 'ban': ['ban', 'nab'], + 'bana': ['anba', 'bana'], + 'banak': ['banak', 'nabak'], + 'banal': ['alban', 'balan', 'banal', 'laban', 'nabal', 'nabla'], + 'banat': ['banat', 'batan'], + 'banca': ['banca', 'caban'], + 'bancal': ['bancal', 'blanca'], + 'banco': ['bacon', 'banco'], + 'banda': ['badan', 'banda'], + 'bandage': ['bandage', 'dagbane'], + 'bandar': ['bandar', 'raband'], + 'bandarlog': ['bandarlog', 'langobard'], + 'bande': ['bande', 'benda'], + 'bander': ['bander', 'brenda'], + 'banderma': ['banderma', 'breadman'], + 'banderole': ['banderole', 'bandoleer'], + 'bandhook': ['bandhook', 'handbook'], + 'bandle': ['balden', 'bandle'], + 'bandless': ['baldness', 'bandless'], + 'bando': ['badon', 'bando'], + 'bandoleer': ['banderole', 'bandoleer'], + 'bandor': ['bandor', 'bondar', 'roband'], + 'bandore': ['bandore', 'broaden'], + 'bane': ['bane', 'bean', 'bena'], + 'bangala': ['balagan', 'bangala'], + 'bangalay': ['balangay', 'bangalay'], + 'bangash': ['bangash', 'nashgab'], + 'banger': ['banger', 'engarb', 'graben'], + 'banghy': ['banghy', 'hangby'], + 'bangia': ['bagani', 'bangia', 'ibanag'], + 'bangle': ['bangle', 'bengal'], + 'bani': ['bain', 'bani', 'iban'], + 'banilad': ['balanid', 'banilad'], + 'banisher': ['banisher', 'rebanish'], + 'baniva': ['baniva', 'bavian'], + 'baniya': ['baniya', 'banyai'], + 'banjoist': ['banjoist', 'bostanji'], + 'bank': ['bank', 'knab', 'nabk'], + 'banker': ['banker', 'barken'], + 'banshee': ['banshee', 'benshea'], + 'bantam': ['bantam', 'batman'], + 'banteng': ['banteng', 'bentang'], + 'banyai': ['baniya', 'banyai'], + 'banzai': ['banzai', 'zabian'], + 'bar': ['bar', 'bra', 'rab'], + 'bara': ['arab', 'arba', 'baar', 'bara'], + 'barabra': ['barabra', 'barbara'], + 'barad': ['barad', 'draba'], + 'barb': ['barb', 'brab'], + 'barbara': ['barabra', 'barbara'], + 'barbe': ['barbe', 'bebar', 'breba', 'rebab'], + 'barbed': ['barbed', 'dabber'], + 'barbel': ['barbel', 'labber', 'rabble'], + 'barbet': ['barbet', 'rabbet', 'tabber'], + 'barbette': ['barbette', 'bebatter'], + 'barbion': ['barbion', 'rabboni'], + 'barbitone': ['barbitone', 'barbotine'], + 'barbone': ['barbone', 'bebaron'], + 'barbotine': ['barbitone', 'barbotine'], + 'barcella': ['barcella', 'caballer'], + 'barcoo': ['barcoo', 'baroco'], + 'bard': ['bard', 'brad', 'drab'], + 'bardel': ['balder', 'bardel', 'bedlar', 'bedral', 'belard', 'blader'], + 'bardie': ['abider', 'bardie'], + 'bardily': ['bardily', 'rabidly', 'ridably'], + 'bardiness': ['bardiness', 'rabidness'], + 'barding': ['barding', 'brigand'], + 'bardo': ['abord', 'bardo', 'board', 'broad', 'dobra', 'dorab'], + 'bardy': ['bardy', 'darby'], + 'bare': ['bare', 'bear', 'brae'], + 'barefaced': ['barefaced', 'facebread'], + 'barefoot': ['barefoot', 'bearfoot'], + 'barehanded': ['barehanded', 'bradenhead', 'headbander'], + 'barehead': ['barehead', 'braehead'], + 'barely': ['barely', 'barley', 'bleary'], + 'barer': ['barer', 'rebar'], + 'baretta': ['baretta', 'rabatte', 'tabaret'], + 'bargainer': ['bargainer', 'rebargain'], + 'barge': ['bagre', 'barge', 'begar', 'rebag'], + 'bargeer': ['bargeer', 'gerbera'], + 'bargeese': ['bargeese', 'begrease'], + 'bari': ['abir', 'bari', 'rabi'], + 'baric': ['baric', 'carib', 'rabic'], + 'barid': ['barid', 'bidar', 'braid', 'rabid'], + 'barie': ['barie', 'beira', 'erbia', 'rebia'], + 'barile': ['bailer', 'barile'], + 'baris': ['baris', 'sabir'], + 'barish': ['barish', 'shibar'], + 'barit': ['barit', 'ribat'], + 'barite': ['baiter', 'barite', 'rebait', 'terbia'], + 'baritone': ['abrotine', 'baritone', 'obtainer', 'reobtain'], + 'barken': ['banker', 'barken'], + 'barker': ['barker', 'braker'], + 'barkey': ['bakery', 'barkey'], + 'barkle': ['balker', 'barkle'], + 'barky': ['barky', 'braky'], + 'barley': ['barely', 'barley', 'bleary'], + 'barling': ['barling', 'bringal'], + 'barm': ['barm', 'bram'], + 'barmbrack': ['barmbrack', 'brambrack'], + 'barmote': ['barmote', 'bromate'], + 'barmy': ['ambry', 'barmy'], + 'barn': ['barn', 'bran'], + 'barnabite': ['barnabite', 'rabbanite', 'rabbinate'], + 'barnacle': ['balancer', 'barnacle'], + 'barney': ['barney', 'nearby'], + 'barny': ['barny', 'bryan'], + 'baroco': ['barcoo', 'baroco'], + 'barolo': ['barolo', 'robalo'], + 'baron': ['baron', 'boran'], + 'baronet': ['baronet', 'reboant'], + 'barong': ['barong', 'brogan'], + 'barosmin': ['ambrosin', 'barosmin', 'sabromin'], + 'barothermograph': ['barothermograph', 'thermobarograph'], + 'barotse': ['barotse', 'boaster', 'reboast', 'sorbate'], + 'barpost': ['absorpt', 'barpost'], + 'barracan': ['barracan', 'barranca'], + 'barranca': ['barracan', 'barranca'], + 'barrelet': ['barrelet', 'terebral'], + 'barret': ['barret', 'barter'], + 'barrette': ['barrette', 'batterer'], + 'barrio': ['barrio', 'brairo'], + 'barsac': ['barsac', 'scarab'], + 'barse': ['barse', 'besra', 'saber', 'serab'], + 'bart': ['bart', 'brat'], + 'barter': ['barret', 'barter'], + 'barton': ['barton', 'brotan'], + 'bartsia': ['arabist', 'bartsia'], + 'barundi': ['barundi', 'unbraid'], + 'barvel': ['barvel', 'blaver', 'verbal'], + 'barwise': ['barwise', 'swarbie'], + 'barye': ['barye', 'beray', 'yerba'], + 'baryta': ['baryta', 'taryba'], + 'barytine': ['barytine', 'bryanite'], + 'baryton': ['baryton', 'brotany'], + 'bas': ['bas', 'sab'], + 'basal': ['balas', 'balsa', 'basal', 'sabal'], + 'basally': ['basally', 'salably'], + 'basaltic': ['basaltic', 'cabalist'], + 'basaltine': ['balanites', 'basaltine', 'stainable'], + 'base': ['base', 'besa', 'sabe', 'seba'], + 'basella': ['basella', 'sabella', 'salable'], + 'bash': ['bash', 'shab'], + 'basial': ['basial', 'blasia'], + 'basic': ['bacis', 'basic'], + 'basically': ['asyllabic', 'basically'], + 'basidium': ['basidium', 'diiambus'], + 'basil': ['basil', 'labis'], + 'basileus': ['basileus', 'issuable', 'suasible'], + 'basilweed': ['basilweed', 'bladewise'], + 'basinasal': ['basinasal', 'bassalian'], + 'basinet': ['basinet', 'besaint', 'bestain'], + 'basion': ['basion', 'bonsai', 'sabino'], + 'basiparachromatin': ['basiparachromatin', 'marsipobranchiata'], + 'basket': ['basket', 'betask'], + 'basketwork': ['basketwork', 'workbasket'], + 'basos': ['basos', 'basso'], + 'bassalian': ['basinasal', 'bassalian'], + 'bassanite': ['bassanite', 'sebastian'], + 'basset': ['asbest', 'basset'], + 'basso': ['basos', 'basso'], + 'bast': ['bast', 'bats', 'stab'], + 'basta': ['basta', 'staab'], + 'baste': ['baste', 'beast', 'tabes'], + 'basten': ['absent', 'basten'], + 'baster': ['baster', 'bestar', 'breast'], + 'bastille': ['bastille', 'listable'], + 'bastion': ['abiston', 'bastion'], + 'bastionet': ['bastionet', 'obstinate'], + 'bastite': ['bastite', 'batiste', 'bistate'], + 'basto': ['basto', 'boast', 'sabot'], + 'basuto': ['abouts', 'basuto'], + 'bat': ['bat', 'tab'], + 'batad': ['abdat', 'batad'], + 'batakan': ['bakatan', 'batakan'], + 'bataleur': ['bataleur', 'tabulare'], + 'batan': ['banat', 'batan'], + 'batara': ['artaba', 'batara'], + 'batcher': ['batcher', 'berchta', 'brachet'], + 'bate': ['abet', 'bate', 'beat', 'beta'], + 'batea': ['abate', 'ateba', 'batea', 'beata'], + 'batel': ['batel', 'blate', 'bleat', 'table'], + 'batement': ['abetment', 'batement'], + 'bater': ['abret', 'bater', 'berat'], + 'batfowler': ['afterblow', 'batfowler'], + 'bath': ['baht', 'bath', 'bhat'], + 'bathala': ['baalath', 'bathala'], + 'bathe': ['bathe', 'beath'], + 'bather': ['bather', 'bertha', 'breath'], + 'bathonian': ['bathonian', 'nabothian'], + 'batik': ['batik', 'kitab'], + 'batino': ['batino', 'oatbin', 'obtain'], + 'batis': ['absit', 'batis'], + 'batiste': ['bastite', 'batiste', 'bistate'], + 'batling': ['batling', 'tabling'], + 'batman': ['bantam', 'batman'], + 'batophobia': ['batophobia', 'tabophobia'], + 'batrachia': ['batrachia', 'brachiata'], + 'batrachian': ['batrachian', 'branchiata'], + 'bats': ['bast', 'bats', 'stab'], + 'battel': ['battel', 'battle', 'tablet'], + 'batteler': ['batteler', 'berattle'], + 'battening': ['battening', 'bitangent'], + 'batter': ['batter', 'bertat', 'tabret', 'tarbet'], + 'batterer': ['barrette', 'batterer'], + 'battle': ['battel', 'battle', 'tablet'], + 'battler': ['battler', 'blatter', 'brattle'], + 'battue': ['battue', 'tubate'], + 'batule': ['batule', 'betula', 'tabule'], + 'batyphone': ['batyphone', 'hypnobate'], + 'batzen': ['batzen', 'bezant', 'tanzeb'], + 'baud': ['baud', 'buda', 'daub'], + 'baul': ['balu', 'baul', 'bual', 'luba'], + 'baun': ['baun', 'buna', 'nabu', 'nuba'], + 'bauta': ['abuta', 'bauta'], + 'bavian': ['baniva', 'bavian'], + 'baw': ['baw', 'wab'], + 'bawl': ['bawl', 'blaw'], + 'bawler': ['bawler', 'brelaw', 'rebawl', 'warble'], + 'bay': ['aby', 'bay'], + 'baya': ['baya', 'yaba'], + 'bayed': ['bayed', 'beady', 'beday'], + 'baylet': ['baetyl', 'baylet', 'bleaty'], + 'bayonet': ['bayonet', 'betoyan'], + 'baze': ['baze', 'ezba'], + 'bea': ['abe', 'bae', 'bea'], + 'beach': ['bache', 'beach'], + 'bead': ['abed', 'bade', 'bead'], + 'beaded': ['beaded', 'bedead'], + 'beader': ['beader', 'bedare'], + 'beadleism': ['beadleism', 'demisable'], + 'beadlet': ['beadlet', 'belated'], + 'beady': ['bayed', 'beady', 'beday'], + 'beagle': ['beagle', 'belage', 'belgae'], + 'beak': ['bake', 'beak'], + 'beaker': ['beaker', 'berake', 'rebake'], + 'beal': ['abel', 'able', 'albe', 'bale', 'beal', 'bela', 'blae'], + 'bealing': ['algenib', 'bealing', 'belgian', 'bengali'], + 'beam': ['beam', 'bema'], + 'beamer': ['ambeer', 'beamer'], + 'beamless': ['assemble', 'beamless'], + 'beamster': ['beamster', 'bemaster', 'bestream'], + 'beamwork': ['beamwork', 'bowmaker'], + 'beamy': ['beamy', 'embay', 'maybe'], + 'bean': ['bane', 'bean', 'bena'], + 'beanfield': ['beanfield', 'definable'], + 'beant': ['abnet', 'beant'], + 'bear': ['bare', 'bear', 'brae'], + 'bearance': ['bearance', 'carabeen'], + 'beard': ['ardeb', 'beard', 'bread', 'debar'], + 'beardless': ['beardless', 'breadless'], + 'beardlessness': ['beardlessness', 'breadlessness'], + 'bearer': ['bearer', 'rebear'], + 'bearess': ['bearess', 'bessera'], + 'bearfoot': ['barefoot', 'bearfoot'], + 'bearing': ['bearing', 'begrain', 'brainge', 'rigbane'], + 'bearlet': ['bearlet', 'bleater', 'elberta', 'retable'], + 'bearm': ['amber', 'bearm', 'bemar', 'bream', 'embar'], + 'beast': ['baste', 'beast', 'tabes'], + 'beastlily': ['beastlily', 'bestially'], + 'beat': ['abet', 'bate', 'beat', 'beta'], + 'beata': ['abate', 'ateba', 'batea', 'beata'], + 'beater': ['beater', 'berate', 'betear', 'rebate', 'rebeat'], + 'beath': ['bathe', 'beath'], + 'beating': ['baignet', 'beating'], + 'beau': ['aube', 'beau'], + 'bebait': ['babite', 'bebait'], + 'bebar': ['barbe', 'bebar', 'breba', 'rebab'], + 'bebaron': ['barbone', 'bebaron'], + 'bebaste': ['bebaste', 'bebeast'], + 'bebatter': ['barbette', 'bebatter'], + 'bebay': ['abbey', 'bebay'], + 'bebeast': ['bebaste', 'bebeast'], + 'bebog': ['bebog', 'begob', 'gobbe'], + 'becard': ['becard', 'braced'], + 'becater': ['becater', 'betrace'], + 'because': ['because', 'besauce'], + 'becharm': ['becharm', 'brecham', 'chamber'], + 'becher': ['becher', 'breech'], + 'bechern': ['bechern', 'bencher'], + 'bechirp': ['bechirp', 'brephic'], + 'becker': ['becker', 'rebeck'], + 'beclad': ['beclad', 'cabled'], + 'beclart': ['beclart', 'crablet'], + 'becloud': ['becloud', 'obclude'], + 'becram': ['becram', 'camber', 'crambe'], + 'becrimson': ['becrimson', 'scombrine'], + 'becry': ['becry', 'bryce'], + 'bed': ['bed', 'deb'], + 'bedamn': ['bedamn', 'bedman'], + 'bedare': ['beader', 'bedare'], + 'bedark': ['bedark', 'debark'], + 'beday': ['bayed', 'beady', 'beday'], + 'bedead': ['beaded', 'bedead'], + 'bedel': ['bedel', 'bleed'], + 'beden': ['beden', 'deben', 'deneb'], + 'bedim': ['bedim', 'imbed'], + 'bedip': ['bedip', 'biped'], + 'bedismal': ['bedismal', 'semibald'], + 'bedlam': ['bedlam', 'beldam', 'blamed'], + 'bedlar': ['balder', 'bardel', 'bedlar', 'bedral', 'belard', 'blader'], + 'bedless': ['bedless', 'blessed'], + 'bedman': ['bedamn', 'bedman'], + 'bedoctor': ['bedoctor', 'codebtor'], + 'bedog': ['bedog', 'bodge'], + 'bedrail': ['bedrail', 'bridale', 'ridable'], + 'bedral': ['balder', 'bardel', 'bedlar', 'bedral', 'belard', 'blader'], + 'bedrid': ['bedrid', 'bidder'], + 'bedrip': ['bedrip', 'prebid'], + 'bedrock': ['bedrock', 'brocked'], + 'bedroom': ['bedroom', 'boerdom', 'boredom'], + 'bedrown': ['bedrown', 'browden'], + 'bedrug': ['bedrug', 'budger'], + 'bedsick': ['bedsick', 'sickbed'], + 'beduck': ['beduck', 'bucked'], + 'bedur': ['bedur', 'rebud', 'redub'], + 'bedusk': ['bedusk', 'busked'], + 'bedust': ['bedust', 'bestud', 'busted'], + 'beearn': ['beearn', 'berean'], + 'beeman': ['beeman', 'bemean', 'bename'], + 'been': ['been', 'bene', 'eben'], + 'beer': ['beer', 'bere', 'bree'], + 'beest': ['beest', 'beset'], + 'beeswing': ['beeswing', 'beswinge'], + 'befathered': ['befathered', 'featherbed'], + 'befile': ['befile', 'belief'], + 'befinger': ['befinger', 'befringe'], + 'beflea': ['beflea', 'beleaf'], + 'beflour': ['beflour', 'fourble'], + 'beflum': ['beflum', 'fumble'], + 'befret': ['befret', 'bereft'], + 'befringe': ['befinger', 'befringe'], + 'begad': ['badge', 'begad'], + 'begall': ['begall', 'glebal'], + 'begar': ['bagre', 'barge', 'begar', 'rebag'], + 'begash': ['begash', 'beshag'], + 'begat': ['begat', 'betag'], + 'begettal': ['begettal', 'gettable'], + 'beggar': ['bagger', 'beggar'], + 'beggarer': ['beggarer', 'rebeggar'], + 'begin': ['begin', 'being', 'binge'], + 'begird': ['begird', 'bridge'], + 'beglic': ['beglic', 'belgic'], + 'bego': ['bego', 'egbo'], + 'begob': ['bebog', 'begob', 'gobbe'], + 'begone': ['begone', 'engobe'], + 'begrain': ['bearing', 'begrain', 'brainge', 'rigbane'], + 'begrease': ['bargeese', 'begrease'], + 'behaviorism': ['behaviorism', 'misbehavior'], + 'behears': ['behears', 'beshear'], + 'behint': ['behint', 'henbit'], + 'beholder': ['beholder', 'rebehold'], + 'behorn': ['behorn', 'brehon'], + 'beid': ['beid', 'bide', 'debi', 'dieb'], + 'being': ['begin', 'being', 'binge'], + 'beira': ['barie', 'beira', 'erbia', 'rebia'], + 'beisa': ['abies', 'beisa'], + 'bel': ['bel', 'elb'], + 'bela': ['abel', 'able', 'albe', 'bale', 'beal', 'bela', 'blae'], + 'belabor': ['belabor', 'borable'], + 'belaced': ['belaced', 'debacle'], + 'belage': ['beagle', 'belage', 'belgae'], + 'belait': ['albeit', + 'albite', + 'baltei', + 'belait', + 'betail', + 'bletia', + 'libate'], + 'belam': ['amble', 'belam', 'blame', 'mabel'], + 'belar': ['abler', 'baler', 'belar', 'blare', 'blear'], + 'belard': ['balder', 'bardel', 'bedlar', 'bedral', 'belard', 'blader'], + 'belate': ['balete', 'belate'], + 'belated': ['beadlet', 'belated'], + 'belaud': ['ablude', 'belaud'], + 'beldam': ['bedlam', 'beldam', 'blamed'], + 'beleaf': ['beflea', 'beleaf'], + 'beleap': ['beleap', 'bepale'], + 'belga': ['bagel', 'belga', 'gable', 'gleba'], + 'belgae': ['beagle', 'belage', 'belgae'], + 'belgian': ['algenib', 'bealing', 'belgian', 'bengali'], + 'belgic': ['beglic', 'belgic'], + 'belial': ['alible', 'belial', 'labile', 'liable'], + 'belief': ['befile', 'belief'], + 'belili': ['belili', 'billie'], + 'belite': ['belite', 'beltie', 'bietle'], + 'belitter': ['belitter', 'tribelet'], + 'belive': ['belive', 'beveil'], + 'bella': ['bella', 'label'], + 'bellied': ['bellied', 'delible'], + 'bellona': ['allbone', 'bellona'], + 'bellonian': ['bellonian', 'nonliable'], + 'bellote': ['bellote', 'lobelet'], + 'bellower': ['bellower', 'rebellow'], + 'belltail': ['belltail', 'bletilla', 'tillable'], + 'bellyer': ['bellyer', 'rebelly'], + 'bellypinch': ['bellypinch', 'pinchbelly'], + 'beloid': ['beloid', 'boiled', 'bolide'], + 'belonger': ['belonger', 'rebelong'], + 'belonid': ['belonid', 'boldine'], + 'belord': ['belord', 'bordel', 'rebold'], + 'below': ['below', 'bowel', 'elbow'], + 'belt': ['belt', 'blet'], + 'beltane': ['beltane', 'tenable'], + 'belter': ['belter', 'elbert', 'treble'], + 'beltie': ['belite', 'beltie', 'bietle'], + 'beltine': ['beltine', 'tenible'], + 'beltir': ['beltir', 'riblet'], + 'beltman': ['beltman', 'lambent'], + 'belve': ['belve', 'bevel'], + 'bema': ['beam', 'bema'], + 'bemail': ['bemail', 'lambie'], + 'beman': ['beman', 'nambe'], + 'bemar': ['amber', 'bearm', 'bemar', 'bream', 'embar'], + 'bemaster': ['beamster', 'bemaster', 'bestream'], + 'bemaul': ['bemaul', 'blumea'], + 'bemeal': ['bemeal', 'meable'], + 'bemean': ['beeman', 'bemean', 'bename'], + 'bemire': ['bemire', 'bireme'], + 'bemitred': ['bemitred', 'timbered'], + 'bemoil': ['bemoil', 'mobile'], + 'bemole': ['bemole', 'embole'], + 'bemusk': ['bemusk', 'embusk'], + 'ben': ['ben', 'neb'], + 'bena': ['bane', 'bean', 'bena'], + 'benacus': ['acubens', 'benacus'], + 'bename': ['beeman', 'bemean', 'bename'], + 'benami': ['benami', 'bimane'], + 'bencher': ['bechern', 'bencher'], + 'benchwork': ['benchwork', 'workbench'], + 'benda': ['bande', 'benda'], + 'bender': ['bender', 'berend', 'rebend'], + 'bene': ['been', 'bene', 'eben'], + 'benedight': ['benedight', 'benighted'], + 'benefiter': ['benefiter', 'rebenefit'], + 'bengal': ['bangle', 'bengal'], + 'bengali': ['algenib', 'bealing', 'belgian', 'bengali'], + 'beni': ['beni', 'bien', 'bine', 'inbe'], + 'benighted': ['benedight', 'benighted'], + 'beno': ['beno', 'bone', 'ebon'], + 'benote': ['benote', 'betone'], + 'benshea': ['banshee', 'benshea'], + 'benshee': ['benshee', 'shebeen'], + 'bentang': ['banteng', 'bentang'], + 'benton': ['benton', 'bonnet'], + 'benu': ['benu', 'unbe'], + 'benward': ['benward', 'brawned'], + 'benzantialdoxime': ['antibenzaldoxime', 'benzantialdoxime'], + 'benzein': ['benzein', 'benzine'], + 'benzine': ['benzein', 'benzine'], + 'benzo': ['benzo', 'bonze'], + 'benzofluorene': ['benzofluorene', 'fluorobenzene'], + 'benzonitrol': ['benzonitrol', 'nitrobenzol'], + 'bepale': ['beleap', 'bepale'], + 'bepart': ['bepart', 'berapt', 'betrap'], + 'bepaste': ['bepaste', 'bespate'], + 'bepester': ['bepester', 'prebeset'], + 'beplaster': ['beplaster', 'prestable'], + 'ber': ['ber', 'reb'], + 'berake': ['beaker', 'berake', 'rebake'], + 'berapt': ['bepart', 'berapt', 'betrap'], + 'berat': ['abret', 'bater', 'berat'], + 'berate': ['beater', 'berate', 'betear', 'rebate', 'rebeat'], + 'berattle': ['batteler', 'berattle'], + 'beraunite': ['beraunite', 'unebriate'], + 'beray': ['barye', 'beray', 'yerba'], + 'berberi': ['berberi', 'rebribe'], + 'berchta': ['batcher', 'berchta', 'brachet'], + 'bere': ['beer', 'bere', 'bree'], + 'berean': ['beearn', 'berean'], + 'bereft': ['befret', 'bereft'], + 'berend': ['bender', 'berend', 'rebend'], + 'berg': ['berg', 'gerb'], + 'bergama': ['bergama', 'megabar'], + 'bergamo': ['bergamo', 'embargo'], + 'beri': ['beri', 'bier', 'brei', 'ribe'], + 'beringed': ['beringed', 'breeding'], + 'berinse': ['berinse', 'besiren'], + 'berley': ['berley', 'bleery'], + 'berlinite': ['berlinite', 'libertine'], + 'bermudite': ['bermudite', 'demibrute'], + 'bernard': ['bernard', 'brander', 'rebrand'], + 'bernese': ['bernese', 'besneer'], + 'beroe': ['beroe', 'boree'], + 'beroida': ['beroida', 'boreiad'], + 'beroll': ['beroll', 'boller'], + 'berossos': ['berossos', 'obsessor'], + 'beround': ['beround', 'bounder', 'rebound', 'unbored', 'unorbed', 'unrobed'], + 'berri': ['berri', 'brier'], + 'berried': ['berried', 'briered'], + 'berrybush': ['berrybush', 'shrubbery'], + 'bersil': ['bersil', 'birsle'], + 'bert': ['bert', 'bret'], + 'bertat': ['batter', 'bertat', 'tabret', 'tarbet'], + 'berth': ['berth', 'breth'], + 'bertha': ['bather', 'bertha', 'breath'], + 'berther': ['berther', 'herbert'], + 'berthing': ['berthing', 'brighten'], + 'bertie': ['bertie', 'betire', 'rebite'], + 'bertolonia': ['bertolonia', 'borolanite'], + 'berust': ['berust', 'buster', 'stuber'], + 'bervie': ['bervie', 'brieve'], + 'beryllia': ['beryllia', 'reliably'], + 'besa': ['base', 'besa', 'sabe', 'seba'], + 'besaiel': ['baleise', 'besaiel'], + 'besaint': ['basinet', 'besaint', 'bestain'], + 'besauce': ['because', 'besauce'], + 'bescour': ['bescour', 'buceros', 'obscure'], + 'beset': ['beest', 'beset'], + 'beshadow': ['beshadow', 'bodewash'], + 'beshag': ['begash', 'beshag'], + 'beshear': ['behears', 'beshear'], + 'beshod': ['beshod', 'debosh'], + 'besiren': ['berinse', 'besiren'], + 'besit': ['besit', 'betis'], + 'beslaver': ['beslaver', 'servable', 'versable'], + 'beslime': ['beslime', 'besmile'], + 'beslings': ['beslings', 'blessing', 'glibness'], + 'beslow': ['beslow', 'bowels'], + 'besmile': ['beslime', 'besmile'], + 'besneer': ['bernese', 'besneer'], + 'besoot': ['besoot', 'bootes'], + 'besot': ['besot', 'betso'], + 'besoul': ['besoul', 'blouse', 'obelus'], + 'besour': ['besour', 'boreus', 'bourse', 'bouser'], + 'bespate': ['bepaste', 'bespate'], + 'besra': ['barse', 'besra', 'saber', 'serab'], + 'bessera': ['bearess', 'bessera'], + 'bestain': ['basinet', 'besaint', 'bestain'], + 'bestar': ['baster', 'bestar', 'breast'], + 'besteer': ['besteer', 'rebeset'], + 'bestial': ['astilbe', 'bestial', 'blastie', 'stabile'], + 'bestially': ['beastlily', 'bestially'], + 'bestiarian': ['antirabies', 'bestiarian'], + 'bestiary': ['bestiary', 'sybarite'], + 'bestir': ['bestir', 'bister'], + 'bestorm': ['bestorm', 'mobster'], + 'bestowal': ['bestowal', 'stowable'], + 'bestower': ['bestower', 'rebestow'], + 'bestraw': ['bestraw', 'wabster'], + 'bestream': ['beamster', 'bemaster', 'bestream'], + 'bestrew': ['bestrew', 'webster'], + 'bestride': ['bestride', 'bistered'], + 'bestud': ['bedust', 'bestud', 'busted'], + 'beswinge': ['beeswing', 'beswinge'], + 'beta': ['abet', 'bate', 'beat', 'beta'], + 'betag': ['begat', 'betag'], + 'betail': ['albeit', + 'albite', + 'baltei', + 'belait', + 'betail', + 'bletia', + 'libate'], + 'betailor': ['betailor', 'laborite', 'orbitale'], + 'betask': ['basket', 'betask'], + 'betear': ['beater', 'berate', 'betear', 'rebate', 'rebeat'], + 'beth': ['beth', 'theb'], + 'betire': ['bertie', 'betire', 'rebite'], + 'betis': ['besit', 'betis'], + 'betone': ['benote', 'betone'], + 'betoss': ['betoss', 'bosset'], + 'betoya': ['betoya', 'teaboy'], + 'betoyan': ['bayonet', 'betoyan'], + 'betrace': ['becater', 'betrace'], + 'betrail': ['betrail', 'librate', 'triable', 'trilabe'], + 'betrap': ['bepart', 'berapt', 'betrap'], + 'betrayal': ['betrayal', 'tearably'], + 'betrayer': ['betrayer', 'eatberry', 'rebetray', 'teaberry'], + 'betread': ['betread', 'debater'], + 'betrim': ['betrim', 'timber', 'timbre'], + 'betso': ['besot', 'betso'], + 'betta': ['betta', 'tabet'], + 'bettina': ['bettina', 'tabinet', 'tibetan'], + 'betula': ['batule', 'betula', 'tabule'], + 'betulin': ['betulin', 'bluntie'], + 'beturbaned': ['beturbaned', 'unrabbeted'], + 'beveil': ['belive', 'beveil'], + 'bevel': ['belve', 'bevel'], + 'bever': ['bever', 'breve'], + 'bewailer': ['bewailer', 'rebewail'], + 'bework': ['bework', 'bowker'], + 'bey': ['bey', 'bye'], + 'beydom': ['beydom', 'embody'], + 'bezant': ['batzen', 'bezant', 'tanzeb'], + 'bezzo': ['bezzo', 'bozze'], + 'bhakti': ['bhakti', 'khatib'], + 'bhandari': ['bhandari', 'hairband'], + 'bhar': ['bhar', 'harb'], + 'bhara': ['bahar', 'bhara'], + 'bhat': ['baht', 'bath', 'bhat'], + 'bhima': ['bhima', 'biham'], + 'bhotia': ['bhotia', 'tobiah'], + 'bhutani': ['bhutani', 'unhabit'], + 'biacetyl': ['baetylic', 'biacetyl'], + 'bialate': ['baalite', 'bialate', 'labiate'], + 'bialveolar': ['bialveolar', 'labiovelar'], + 'bianca': ['abanic', 'bianca'], + 'bianco': ['bianco', 'bonaci'], + 'biangular': ['biangular', 'bulgarian'], + 'bias': ['absi', 'bais', 'bias', 'isba'], + 'biatomic': ['biatomic', 'moabitic'], + 'bible': ['bible', 'blibe'], + 'bicarpellary': ['bicarpellary', 'prebacillary'], + 'bickern': ['bickern', 'bricken'], + 'biclavate': ['activable', 'biclavate'], + 'bicorn': ['bicorn', 'bicron'], + 'bicornate': ['bicornate', 'carbonite', 'reboantic'], + 'bicrenate': ['abenteric', 'bicrenate'], + 'bicron': ['bicorn', 'bicron'], + 'bicrural': ['bicrural', 'rubrical'], + 'bid': ['bid', 'dib'], + 'bidar': ['barid', 'bidar', 'braid', 'rabid'], + 'bidder': ['bedrid', 'bidder'], + 'bide': ['beid', 'bide', 'debi', 'dieb'], + 'bident': ['bident', 'indebt'], + 'bidented': ['bidented', 'indebted'], + 'bider': ['bider', 'bredi', 'bride', 'rebid'], + 'bidet': ['bidet', 'debit'], + 'biduous': ['biduous', 'dubious'], + 'bien': ['beni', 'bien', 'bine', 'inbe'], + 'bier': ['beri', 'bier', 'brei', 'ribe'], + 'bietle': ['belite', 'beltie', 'bietle'], + 'bifer': ['bifer', 'brief', 'fiber'], + 'big': ['big', 'gib'], + 'biga': ['agib', 'biga', 'gabi'], + 'bigamous': ['bigamous', 'subimago'], + 'bigener': ['bigener', 'rebegin'], + 'bigential': ['bigential', 'tangibile'], + 'biggin': ['biggin', 'gibing'], + 'bigoted': ['bigoted', 'dogbite'], + 'biham': ['bhima', 'biham'], + 'bihari': ['bihari', 'habiri'], + 'bike': ['bike', 'kibe'], + 'bikram': ['bikram', 'imbark'], + 'bilaan': ['albian', 'bilaan'], + 'bilaterality': ['alterability', 'bilaterality', 'relatability'], + 'bilati': ['bilati', 'tibial'], + 'bilby': ['bilby', 'libby'], + 'bildar': ['bildar', 'bridal', 'ribald'], + 'bilge': ['bilge', 'gibel'], + 'biliate': ['biliate', 'tibiale'], + 'bilinear': ['bilinear', 'liberian'], + 'billa': ['balli', 'billa'], + 'billboard': ['billboard', 'broadbill'], + 'biller': ['biller', 'rebill'], + 'billeter': ['billeter', 'rebillet'], + 'billie': ['belili', 'billie'], + 'bilo': ['bilo', 'boil'], + 'bilobated': ['bilobated', 'bobtailed'], + 'biltong': ['biltong', 'bolting'], + 'bim': ['bim', 'mib'], + 'bimane': ['benami', 'bimane'], + 'bimodality': ['bimodality', 'myliobatid'], + 'bimotors': ['bimotors', 'robotism'], + 'bin': ['bin', 'nib'], + 'binal': ['albin', 'binal', 'blain'], + 'binary': ['binary', 'brainy'], + 'binder': ['binder', 'inbred', 'rebind'], + 'bindwood': ['bindwood', 'woodbind'], + 'bine': ['beni', 'bien', 'bine', 'inbe'], + 'binge': ['begin', 'being', 'binge'], + 'bino': ['bino', 'bion', 'boni'], + 'binocular': ['binocular', 'caliburno', 'colubrina'], + 'binomial': ['binomial', 'mobilian'], + 'binuclear': ['binuclear', 'incurable'], + 'biod': ['biod', 'boid'], + 'bion': ['bino', 'bion', 'boni'], + 'biopsychological': ['biopsychological', 'psychobiological'], + 'biopsychology': ['biopsychology', 'psychobiology'], + 'bioral': ['bailor', 'bioral'], + 'biorgan': ['biorgan', 'grobian'], + 'bios': ['bios', 'bois'], + 'biosociological': ['biosociological', 'sociobiological'], + 'biota': ['biota', 'ibota'], + 'biotics': ['biotics', 'cobitis'], + 'bipartile': ['bipartile', 'pretibial'], + 'biped': ['bedip', 'biped'], + 'bipedal': ['bipedal', 'piebald'], + 'bipersonal': ['bipersonal', 'prisonable'], + 'bipolar': ['bipolar', 'parboil'], + 'biracial': ['biracial', 'cibarial'], + 'birchen': ['birchen', 'brichen'], + 'bird': ['bird', 'drib'], + 'birdeen': ['birdeen', 'inbreed'], + 'birdlet': ['birdlet', 'driblet'], + 'birdling': ['birdling', 'bridling', 'lingbird'], + 'birdman': ['birdman', 'manbird'], + 'birdseed': ['birdseed', 'seedbird'], + 'birdstone': ['birdstone', 'stonebird'], + 'bireme': ['bemire', 'bireme'], + 'biretta': ['biretta', 'brattie', 'ratbite'], + 'birle': ['birle', 'liber'], + 'birma': ['abrim', 'birma'], + 'birn': ['birn', 'brin'], + 'birny': ['birny', 'briny'], + 'biron': ['biron', 'inorb', 'robin'], + 'birse': ['birse', 'ribes'], + 'birsle': ['bersil', 'birsle'], + 'birth': ['birth', 'brith'], + 'bis': ['bis', 'sib'], + 'bisalt': ['baltis', 'bisalt'], + 'bisaltae': ['bisaltae', 'satiable'], + 'bisharin': ['bairnish', 'bisharin'], + 'bistate': ['bastite', 'batiste', 'bistate'], + 'bister': ['bestir', 'bister'], + 'bistered': ['bestride', 'bistered'], + 'bisti': ['bisti', 'bitis'], + 'bisulcate': ['baculites', 'bisulcate'], + 'bit': ['bit', 'tib'], + 'bitangent': ['battening', 'bitangent'], + 'bitemporal': ['bitemporal', 'importable'], + 'biter': ['biter', 'tribe'], + 'bitis': ['bisti', 'bitis'], + 'bito': ['bito', 'obit'], + 'bitonality': ['bitonality', 'notability'], + 'bittern': ['bittern', 'britten'], + 'bitumed': ['bitumed', 'budtime'], + 'biurate': ['abiuret', 'aubrite', 'biurate', 'rubiate'], + 'biwa': ['biwa', 'wabi'], + 'bizarre': ['bizarre', 'brazier'], + 'bizet': ['bizet', 'zibet'], + 'blabber': ['babbler', 'blabber', 'brabble'], + 'blackacre': ['blackacre', 'crackable'], + 'blad': ['bald', 'blad'], + 'blader': ['balder', 'bardel', 'bedlar', 'bedral', 'belard', 'blader'], + 'bladewise': ['basilweed', 'bladewise'], + 'bladish': ['baldish', 'bladish'], + 'blady': ['badly', 'baldy', 'blady'], + 'blae': ['abel', 'able', 'albe', 'bale', 'beal', 'bela', 'blae'], + 'blaeberry': ['blaeberry', 'bleaberry'], + 'blaeness': ['ableness', 'blaeness', 'sensable'], + 'blain': ['albin', 'binal', 'blain'], + 'blaine': ['baline', 'blaine'], + 'blair': ['blair', 'brail', 'libra'], + 'blake': ['blake', 'bleak', 'kabel'], + 'blame': ['amble', 'belam', 'blame', 'mabel'], + 'blamed': ['bedlam', 'beldam', 'blamed'], + 'blamer': ['ambler', 'blamer', 'lamber', 'marble', 'ramble'], + 'blaming': ['ambling', 'blaming'], + 'blamingly': ['amblingly', 'blamingly'], + 'blanca': ['bancal', 'blanca'], + 'blare': ['abler', 'baler', 'belar', 'blare', 'blear'], + 'blarina': ['blarina', 'branial'], + 'blarney': ['blarney', 'renably'], + 'blas': ['blas', 'slab'], + 'blase': ['blase', 'sable'], + 'blasia': ['basial', 'blasia'], + 'blastema': ['blastema', 'lambaste'], + 'blastemic': ['blastemic', 'cembalist'], + 'blaster': ['blaster', 'reblast', 'stabler'], + 'blastie': ['astilbe', 'bestial', 'blastie', 'stabile'], + 'blasting': ['blasting', 'stabling'], + 'blastoderm': ['blastoderm', 'dermoblast'], + 'blastogenic': ['blastogenic', 'genoblastic'], + 'blastomeric': ['blastomeric', 'meroblastic'], + 'blastomycetic': ['blastomycetic', 'cytoblastemic'], + 'blastomycetous': ['blastomycetous', 'cytoblastemous'], + 'blasty': ['blasty', 'stably'], + 'blat': ['balt', 'blat'], + 'blate': ['batel', 'blate', 'bleat', 'table'], + 'blather': ['blather', 'halbert'], + 'blatter': ['battler', 'blatter', 'brattle'], + 'blaver': ['barvel', 'blaver', 'verbal'], + 'blaw': ['bawl', 'blaw'], + 'blay': ['ably', 'blay', 'yalb'], + 'blazoner': ['albronze', 'blazoner'], + 'bleaberry': ['blaeberry', 'bleaberry'], + 'bleach': ['bachel', 'bleach'], + 'bleacher': ['bleacher', 'rebleach'], + 'bleak': ['blake', 'bleak', 'kabel'], + 'bleaky': ['bleaky', 'kabyle'], + 'blear': ['abler', 'baler', 'belar', 'blare', 'blear'], + 'bleared': ['bleared', 'reblade'], + 'bleary': ['barely', 'barley', 'bleary'], + 'bleat': ['batel', 'blate', 'bleat', 'table'], + 'bleater': ['bearlet', 'bleater', 'elberta', 'retable'], + 'bleating': ['bleating', 'tangible'], + 'bleaty': ['baetyl', 'baylet', 'bleaty'], + 'bleed': ['bedel', 'bleed'], + 'bleery': ['berley', 'bleery'], + 'blender': ['blender', 'reblend'], + 'blendure': ['blendure', 'rebundle'], + 'blennoid': ['blennoid', 'blondine'], + 'blennoma': ['blennoma', 'nobleman'], + 'bleo': ['bleo', 'bole', 'lobe'], + 'blepharocera': ['blepharocera', 'reproachable'], + 'blessed': ['bedless', 'blessed'], + 'blesser': ['blesser', 'rebless'], + 'blessing': ['beslings', 'blessing', 'glibness'], + 'blet': ['belt', 'blet'], + 'bletia': ['albeit', + 'albite', + 'baltei', + 'belait', + 'betail', + 'bletia', + 'libate'], + 'bletilla': ['belltail', 'bletilla', 'tillable'], + 'blibe': ['bible', 'blibe'], + 'blighter': ['blighter', 'therblig'], + 'blimy': ['blimy', 'limby'], + 'blister': ['blister', 'bristle'], + 'blisterwort': ['blisterwort', 'bristlewort'], + 'blitter': ['blitter', 'brittle', 'triblet'], + 'blo': ['blo', 'lob'], + 'bloated': ['bloated', 'lobated'], + 'bloater': ['alberto', 'bloater', 'latrobe'], + 'bloating': ['bloating', 'obligant'], + 'blocker': ['blocker', 'brockle', 'reblock'], + 'blonde': ['blonde', 'bolden'], + 'blondine': ['blennoid', 'blondine'], + 'blood': ['blood', 'boldo'], + 'bloodleaf': ['bloodleaf', 'floodable'], + 'bloomer': ['bloomer', 'rebloom'], + 'bloomy': ['bloomy', 'lomboy'], + 'blore': ['blore', 'roble'], + 'blosmy': ['blosmy', 'symbol'], + 'blot': ['blot', 'bolt'], + 'blotless': ['blotless', 'boltless'], + 'blotter': ['blotter', 'bottler'], + 'blotting': ['blotting', 'bottling'], + 'blouse': ['besoul', 'blouse', 'obelus'], + 'blow': ['blow', 'bowl'], + 'blowback': ['backblow', 'blowback'], + 'blower': ['blower', 'bowler', 'reblow', 'worble'], + 'blowfly': ['blowfly', 'flyblow'], + 'blowing': ['blowing', 'bowling'], + 'blowout': ['blowout', 'outblow', 'outbowl'], + 'blowup': ['blowup', 'upblow'], + 'blowy': ['blowy', 'bowly'], + 'blub': ['blub', 'bulb'], + 'blubber': ['blubber', 'bubbler'], + 'blue': ['blue', 'lube'], + 'bluegill': ['bluegill', 'gullible'], + 'bluenose': ['bluenose', 'nebulose'], + 'bluer': ['bluer', 'brule', 'burel', 'ruble'], + 'blues': ['blues', 'bulse'], + 'bluffer': ['bluffer', 'rebluff'], + 'bluishness': ['bluishness', 'blushiness'], + 'bluism': ['bluism', 'limbus'], + 'blumea': ['bemaul', 'blumea'], + 'blunder': ['blunder', 'bundler'], + 'blunderer': ['blunderer', 'reblunder'], + 'blunge': ['blunge', 'bungle'], + 'blunger': ['blunger', 'bungler'], + 'bluntie': ['betulin', 'bluntie'], + 'blur': ['blur', 'burl'], + 'blushiness': ['bluishness', 'blushiness'], + 'bluster': ['bluster', 'brustle', 'bustler'], + 'boa': ['abo', 'boa'], + 'boar': ['boar', 'bora'], + 'board': ['abord', 'bardo', 'board', 'broad', 'dobra', 'dorab'], + 'boarder': ['arbored', 'boarder', 'reboard'], + 'boardly': ['boardly', 'broadly'], + 'boardy': ['boardy', 'boyard', 'byroad'], + 'boast': ['basto', 'boast', 'sabot'], + 'boaster': ['barotse', 'boaster', 'reboast', 'sorbate'], + 'boasting': ['boasting', 'bostangi'], + 'boat': ['boat', 'bota', 'toba'], + 'boater': ['boater', 'borate', 'rebato'], + 'boathouse': ['boathouse', 'houseboat'], + 'bobac': ['bobac', 'cabob'], + 'bobfly': ['bobfly', 'flobby'], + 'bobo': ['bobo', 'boob'], + 'bobtailed': ['bilobated', 'bobtailed'], + 'bocardo': ['bocardo', 'cordoba'], + 'boccale': ['boccale', 'cabocle'], + 'bocher': ['bocher', 'broche'], + 'bocking': ['bocking', 'kingcob'], + 'bod': ['bod', 'dob'], + 'bode': ['bode', 'dobe'], + 'boden': ['boden', 'boned'], + 'boder': ['boder', 'orbed'], + 'bodewash': ['beshadow', 'bodewash'], + 'bodge': ['bedog', 'bodge'], + 'bodhi': ['bodhi', 'dhobi'], + 'bodice': ['bodice', 'ceboid'], + 'bodier': ['bodier', 'boride', 'brodie'], + 'bodle': ['bodle', 'boled', 'lobed'], + 'bodo': ['bodo', 'bood', 'doob'], + 'body': ['body', 'boyd', 'doby'], + 'boer': ['boer', 'bore', 'robe'], + 'boerdom': ['bedroom', 'boerdom', 'boredom'], + 'boethian': ['boethian', 'nebaioth'], + 'bog': ['bog', 'gob'], + 'boga': ['bago', 'boga'], + 'bogan': ['bogan', 'goban'], + 'bogeyman': ['bogeyman', 'moneybag'], + 'boggler': ['boggler', 'broggle'], + 'boglander': ['boglander', 'longbeard'], + 'bogle': ['bogle', 'globe'], + 'boglet': ['boglet', 'goblet'], + 'bogo': ['bogo', 'gobo'], + 'bogue': ['bogue', 'bouge'], + 'bogum': ['bogum', 'gumbo'], + 'bogy': ['bogy', 'bygo', 'goby'], + 'bohea': ['bahoe', 'bohea', 'obeah'], + 'boho': ['boho', 'hobo'], + 'bohor': ['bohor', 'rohob'], + 'boid': ['biod', 'boid'], + 'boil': ['bilo', 'boil'], + 'boiled': ['beloid', 'boiled', 'bolide'], + 'boiler': ['boiler', 'reboil'], + 'boilover': ['boilover', 'overboil'], + 'bois': ['bios', 'bois'], + 'bojo': ['bojo', 'jobo'], + 'bolar': ['balor', 'bolar', 'boral', 'labor', 'lobar'], + 'bolden': ['blonde', 'bolden'], + 'bolderian': ['bolderian', 'ordinable'], + 'boldine': ['belonid', 'boldine'], + 'boldness': ['boldness', 'bondless'], + 'boldo': ['blood', 'boldo'], + 'bole': ['bleo', 'bole', 'lobe'], + 'boled': ['bodle', 'boled', 'lobed'], + 'bolelia': ['bolelia', 'lobelia', 'obelial'], + 'bolide': ['beloid', 'boiled', 'bolide'], + 'boller': ['beroll', 'boller'], + 'bolo': ['bolo', 'bool', 'lobo', 'obol'], + 'bolster': ['bolster', 'lobster'], + 'bolt': ['blot', 'bolt'], + 'boltage': ['boltage', 'globate'], + 'bolter': ['bolter', 'orblet', 'reblot', 'rebolt'], + 'bolthead': ['bolthead', 'theobald'], + 'bolting': ['biltong', 'bolting'], + 'boltless': ['blotless', 'boltless'], + 'boltonia': ['boltonia', 'lobation', 'oblation'], + 'bom': ['bom', 'mob'], + 'boma': ['ambo', 'boma'], + 'bombable': ['bombable', 'mobbable'], + 'bombacaceae': ['bombacaceae', 'cabombaceae'], + 'bomber': ['bomber', 'mobber'], + 'bon': ['bon', 'nob'], + 'bonaci': ['bianco', 'bonaci'], + 'bonair': ['bonair', 'borani'], + 'bondage': ['bondage', 'dogbane'], + 'bondar': ['bandor', 'bondar', 'roband'], + 'bondless': ['boldness', 'bondless'], + 'bone': ['beno', 'bone', 'ebon'], + 'boned': ['boden', 'boned'], + 'bonefish': ['bonefish', 'fishbone'], + 'boneless': ['boneless', 'noblesse'], + 'bonellia': ['baillone', 'bonellia'], + 'boner': ['boner', 'borne'], + 'boney': ['boney', 'ebony'], + 'boni': ['bino', 'bion', 'boni'], + 'bonitary': ['bonitary', 'trainboy'], + 'bonk': ['bonk', 'knob'], + 'bonnet': ['benton', 'bonnet'], + 'bonsai': ['basion', 'bonsai', 'sabino'], + 'bonus': ['bonus', 'bosun'], + 'bony': ['bony', 'byon'], + 'bonze': ['benzo', 'bonze'], + 'bonzer': ['bonzer', 'bronze'], + 'boob': ['bobo', 'boob'], + 'bood': ['bodo', 'bood', 'doob'], + 'booger': ['booger', 'goober'], + 'bookcase': ['bookcase', 'casebook'], + 'booker': ['booker', 'brooke', 'rebook'], + 'bookland': ['bookland', 'landbook'], + 'bookshop': ['bookshop', 'shopbook'], + 'bookward': ['bookward', 'woodbark'], + 'bookwork': ['bookwork', 'workbook'], + 'bool': ['bolo', 'bool', 'lobo', 'obol'], + 'booly': ['booly', 'looby'], + 'boomingly': ['boomingly', 'myoglobin'], + 'boopis': ['boopis', 'obispo'], + 'boor': ['boor', 'boro', 'broo'], + 'boort': ['boort', 'robot'], + 'boost': ['boost', 'boots'], + 'bootes': ['besoot', 'bootes'], + 'boother': ['boother', 'theorbo'], + 'boots': ['boost', 'boots'], + 'bop': ['bop', 'pob'], + 'bor': ['bor', 'orb', 'rob'], + 'bora': ['boar', 'bora'], + 'borable': ['belabor', 'borable'], + 'boracic': ['boracic', 'braccio'], + 'boral': ['balor', 'bolar', 'boral', 'labor', 'lobar'], + 'boran': ['baron', 'boran'], + 'borani': ['bonair', 'borani'], + 'borate': ['boater', 'borate', 'rebato'], + 'bord': ['bord', 'brod'], + 'bordel': ['belord', 'bordel', 'rebold'], + 'bordello': ['bordello', 'doorbell'], + 'border': ['border', 'roberd'], + 'borderer': ['borderer', 'broderer'], + 'bordure': ['bordure', 'bourder'], + 'bore': ['boer', 'bore', 'robe'], + 'boredom': ['bedroom', 'boerdom', 'boredom'], + 'boree': ['beroe', 'boree'], + 'boreen': ['boreen', 'enrobe', 'neebor', 'rebone'], + 'boreiad': ['beroida', 'boreiad'], + 'boreism': ['boreism', 'semiorb'], + 'borer': ['borer', 'rerob', 'rober'], + 'boreus': ['besour', 'boreus', 'bourse', 'bouser'], + 'borg': ['borg', 'brog', 'gorb'], + 'boric': ['boric', 'cribo', 'orbic'], + 'boride': ['bodier', 'boride', 'brodie'], + 'boring': ['boring', 'robing'], + 'boringly': ['boringly', 'goblinry'], + 'borlase': ['borlase', 'labrose', 'rosabel'], + 'borne': ['boner', 'borne'], + 'borneo': ['borneo', 'oberon'], + 'bornite': ['bornite', 'robinet'], + 'boro': ['boor', 'boro', 'broo'], + 'borocaine': ['borocaine', 'coenobiar'], + 'borofluohydric': ['borofluohydric', 'hydrofluoboric'], + 'borolanite': ['bertolonia', 'borolanite'], + 'boron': ['boron', 'broon'], + 'boronic': ['boronic', 'cobiron'], + 'borrower': ['borrower', 'reborrow'], + 'borscht': ['borscht', 'bortsch'], + 'bort': ['bort', 'brot'], + 'bortsch': ['borscht', 'bortsch'], + 'bos': ['bos', 'sob'], + 'bosc': ['bosc', 'scob'], + 'boser': ['boser', 'brose', 'sober'], + 'bosn': ['bosn', 'nobs', 'snob'], + 'bosselation': ['bosselation', 'eosinoblast'], + 'bosset': ['betoss', 'bosset'], + 'bostangi': ['boasting', 'bostangi'], + 'bostanji': ['banjoist', 'bostanji'], + 'bosun': ['bonus', 'bosun'], + 'bota': ['boat', 'bota', 'toba'], + 'botanical': ['botanical', 'catabolin'], + 'botanophilist': ['botanophilist', 'philobotanist'], + 'bote': ['bote', 'tobe'], + 'botein': ['botein', 'tobine'], + 'both': ['both', 'thob'], + 'bottler': ['blotter', 'bottler'], + 'bottling': ['blotting', 'bottling'], + 'bouge': ['bogue', 'bouge'], + 'bouget': ['bouget', 'outbeg'], + 'bouk': ['bouk', 'kobu'], + 'boulder': ['boulder', 'doubler'], + 'bouldering': ['bouldering', 'redoubling'], + 'boulter': ['boulter', 'trouble'], + 'bounden': ['bounden', 'unboned'], + 'bounder': ['beround', 'bounder', 'rebound', 'unbored', 'unorbed', 'unrobed'], + 'bounding': ['bounding', 'unboding'], + 'bourder': ['bordure', 'bourder'], + 'bourn': ['bourn', 'bruno'], + 'bourse': ['besour', 'boreus', 'bourse', 'bouser'], + 'bouser': ['besour', 'boreus', 'bourse', 'bouser'], + 'bousy': ['bousy', 'byous'], + 'bow': ['bow', 'wob'], + 'bowel': ['below', 'bowel', 'elbow'], + 'boweled': ['boweled', 'elbowed'], + 'bowels': ['beslow', 'bowels'], + 'bowery': ['bowery', 'bowyer', 'owerby'], + 'bowie': ['bowie', 'woibe'], + 'bowker': ['bework', 'bowker'], + 'bowl': ['blow', 'bowl'], + 'bowla': ['ablow', 'balow', 'bowla'], + 'bowler': ['blower', 'bowler', 'reblow', 'worble'], + 'bowling': ['blowing', 'bowling'], + 'bowly': ['blowy', 'bowly'], + 'bowmaker': ['beamwork', 'bowmaker'], + 'bowyer': ['bowery', 'bowyer', 'owerby'], + 'boxer': ['boxer', 'rebox'], + 'boxwork': ['boxwork', 'workbox'], + 'boyang': ['boyang', 'yagnob'], + 'boyard': ['boardy', 'boyard', 'byroad'], + 'boyd': ['body', 'boyd', 'doby'], + 'boyship': ['boyship', 'shipboy'], + 'bozo': ['bozo', 'zobo'], + 'bozze': ['bezzo', 'bozze'], + 'bra': ['bar', 'bra', 'rab'], + 'brab': ['barb', 'brab'], + 'brabble': ['babbler', 'blabber', 'brabble'], + 'braca': ['acrab', 'braca'], + 'braccio': ['boracic', 'braccio'], + 'brace': ['acerb', 'brace', 'caber'], + 'braced': ['becard', 'braced'], + 'braceleted': ['braceleted', 'celebrated'], + 'bracer': ['bracer', 'craber'], + 'braces': ['braces', 'scrabe'], + 'brachet': ['batcher', 'berchta', 'brachet'], + 'brachiata': ['batrachia', 'brachiata'], + 'brachiofacial': ['brachiofacial', 'faciobrachial'], + 'brachiopode': ['brachiopode', 'cardiophobe'], + 'bracon': ['bracon', 'carbon', 'corban'], + 'bractea': ['abreact', 'bractea', 'cabaret'], + 'bracteal': ['bracteal', 'cartable'], + 'bracteiform': ['bacteriform', 'bracteiform'], + 'bracteose': ['bracteose', 'obsecrate'], + 'brad': ['bard', 'brad', 'drab'], + 'bradenhead': ['barehanded', 'bradenhead', 'headbander'], + 'brae': ['bare', 'bear', 'brae'], + 'braehead': ['barehead', 'braehead'], + 'brag': ['brag', 'garb', 'grab'], + 'bragi': ['bragi', 'girba'], + 'bragless': ['bragless', 'garbless'], + 'brahmi': ['brahmi', 'mihrab'], + 'brahui': ['brahui', 'habiru'], + 'braid': ['barid', 'bidar', 'braid', 'rabid'], + 'braider': ['braider', 'rebraid'], + 'brail': ['blair', 'brail', 'libra'], + 'braille': ['braille', 'liberal'], + 'brain': ['abrin', 'bairn', 'brain', 'brian', 'rabin'], + 'brainache': ['brainache', 'branchiae'], + 'brainge': ['bearing', 'begrain', 'brainge', 'rigbane'], + 'brainwater': ['brainwater', 'waterbrain'], + 'brainy': ['binary', 'brainy'], + 'braird': ['braird', 'briard'], + 'brairo': ['barrio', 'brairo'], + 'braise': ['braise', 'rabies', 'rebias'], + 'brake': ['baker', 'brake', 'break'], + 'brakeage': ['brakeage', 'breakage'], + 'brakeless': ['bakerless', 'brakeless', 'breakless'], + 'braker': ['barker', 'braker'], + 'braky': ['barky', 'braky'], + 'bram': ['barm', 'bram'], + 'brambrack': ['barmbrack', 'brambrack'], + 'bramia': ['bairam', 'bramia'], + 'bran': ['barn', 'bran'], + 'brancher': ['brancher', 'rebranch'], + 'branchiae': ['brainache', 'branchiae'], + 'branchiata': ['batrachian', 'branchiata'], + 'branchiopoda': ['branchiopoda', 'podobranchia'], + 'brander': ['bernard', 'brander', 'rebrand'], + 'brandi': ['brandi', 'riband'], + 'brandisher': ['brandisher', 'rebrandish'], + 'branial': ['blarina', 'branial'], + 'brankie': ['brankie', 'inbreak'], + 'brash': ['brash', 'shrab'], + 'brasiletto': ['brasiletto', 'strobilate'], + 'brassie': ['brassie', 'rebasis'], + 'brat': ['bart', 'brat'], + 'brattie': ['biretta', 'brattie', 'ratbite'], + 'brattle': ['battler', 'blatter', 'brattle'], + 'braunite': ['braunite', 'urbanite', 'urbinate'], + 'brave': ['brave', 'breva'], + 'bravoite': ['abortive', 'bravoite'], + 'brawler': ['brawler', 'warbler'], + 'brawling': ['brawling', 'warbling'], + 'brawlingly': ['brawlingly', 'warblingly'], + 'brawly': ['brawly', 'byrlaw', 'warbly'], + 'brawned': ['benward', 'brawned'], + 'bray': ['bray', 'yarb'], + 'braza': ['braza', 'zabra'], + 'braze': ['braze', 'zebra'], + 'brazier': ['bizarre', 'brazier'], + 'bread': ['ardeb', 'beard', 'bread', 'debar'], + 'breadless': ['beardless', 'breadless'], + 'breadlessness': ['beardlessness', 'breadlessness'], + 'breadman': ['banderma', 'breadman'], + 'breadnut': ['breadnut', 'turbaned'], + 'breaghe': ['breaghe', 'herbage'], + 'break': ['baker', 'brake', 'break'], + 'breakage': ['brakeage', 'breakage'], + 'breakless': ['bakerless', 'brakeless', 'breakless'], + 'breakout': ['breakout', 'outbreak'], + 'breakover': ['breakover', 'overbreak'], + 'breakstone': ['breakstone', 'stonebreak'], + 'breakup': ['breakup', 'upbreak'], + 'breakwind': ['breakwind', 'windbreak'], + 'bream': ['amber', 'bearm', 'bemar', 'bream', 'embar'], + 'breast': ['baster', 'bestar', 'breast'], + 'breasting': ['breasting', 'brigantes'], + 'breastpin': ['breastpin', 'stepbairn'], + 'breastrail': ['arbalister', 'breastrail'], + 'breastweed': ['breastweed', 'sweetbread'], + 'breath': ['bather', 'bertha', 'breath'], + 'breathe': ['breathe', 'rebathe'], + 'breba': ['barbe', 'bebar', 'breba', 'rebab'], + 'breccia': ['acerbic', 'breccia'], + 'brecham': ['becharm', 'brecham', 'chamber'], + 'brede': ['brede', 'breed', 'rebed'], + 'bredi': ['bider', 'bredi', 'bride', 'rebid'], + 'bree': ['beer', 'bere', 'bree'], + 'breech': ['becher', 'breech'], + 'breed': ['brede', 'breed', 'rebed'], + 'breeder': ['breeder', 'rebreed'], + 'breeding': ['beringed', 'breeding'], + 'brehon': ['behorn', 'brehon'], + 'brei': ['beri', 'bier', 'brei', 'ribe'], + 'brelaw': ['bawler', 'brelaw', 'rebawl', 'warble'], + 'breme': ['breme', 'ember'], + 'bremia': ['ambier', 'bremia', 'embira'], + 'brenda': ['bander', 'brenda'], + 'brephic': ['bechirp', 'brephic'], + 'bret': ['bert', 'bret'], + 'breth': ['berth', 'breth'], + 'breva': ['brave', 'breva'], + 'breve': ['bever', 'breve'], + 'brewer': ['brewer', 'rebrew'], + 'brey': ['brey', 'byre', 'yerb'], + 'brian': ['abrin', 'bairn', 'brain', 'brian', 'rabin'], + 'briard': ['braird', 'briard'], + 'briber': ['briber', 'ribber'], + 'brichen': ['birchen', 'brichen'], + 'brickel': ['brickel', 'brickle'], + 'bricken': ['bickern', 'bricken'], + 'brickle': ['brickel', 'brickle'], + 'bricole': ['bricole', 'corbeil', 'orbicle'], + 'bridal': ['bildar', 'bridal', 'ribald'], + 'bridale': ['bedrail', 'bridale', 'ridable'], + 'bridally': ['bridally', 'ribaldly'], + 'bride': ['bider', 'bredi', 'bride', 'rebid'], + 'bridelace': ['bridelace', 'calibered'], + 'bridge': ['begird', 'bridge'], + 'bridgeward': ['bridgeward', 'drawbridge'], + 'bridling': ['birdling', 'bridling', 'lingbird'], + 'brief': ['bifer', 'brief', 'fiber'], + 'briefless': ['briefless', 'fiberless', 'fibreless'], + 'brier': ['berri', 'brier'], + 'briered': ['berried', 'briered'], + 'brieve': ['bervie', 'brieve'], + 'brigade': ['abridge', 'brigade'], + 'brigand': ['barding', 'brigand'], + 'brigantes': ['breasting', 'brigantes'], + 'brighten': ['berthing', 'brighten'], + 'brin': ['birn', 'brin'], + 'brine': ['brine', 'enrib'], + 'bringal': ['barling', 'bringal'], + 'bringer': ['bringer', 'rebring'], + 'briny': ['birny', 'briny'], + 'bristle': ['blister', 'bristle'], + 'bristlewort': ['blisterwort', 'bristlewort'], + 'brisure': ['brisure', 'bruiser'], + 'britannia': ['antiabrin', 'britannia'], + 'brith': ['birth', 'brith'], + 'brither': ['brither', 'rebirth'], + 'britten': ['bittern', 'britten'], + 'brittle': ['blitter', 'brittle', 'triblet'], + 'broacher': ['broacher', 'rebroach'], + 'broad': ['abord', 'bardo', 'board', 'broad', 'dobra', 'dorab'], + 'broadbill': ['billboard', 'broadbill'], + 'broadcaster': ['broadcaster', 'rebroadcast'], + 'broaden': ['bandore', 'broaden'], + 'broadhead': ['broadhead', 'headboard'], + 'broadly': ['boardly', 'broadly'], + 'broadside': ['broadside', 'sideboard'], + 'broadspread': ['broadspread', 'spreadboard'], + 'broadtail': ['broadtail', 'tailboard'], + 'brochan': ['brochan', 'charbon'], + 'broche': ['bocher', 'broche'], + 'brocho': ['brocho', 'brooch'], + 'brocked': ['bedrock', 'brocked'], + 'brockle': ['blocker', 'brockle', 'reblock'], + 'brod': ['bord', 'brod'], + 'broderer': ['borderer', 'broderer'], + 'brodie': ['bodier', 'boride', 'brodie'], + 'brog': ['borg', 'brog', 'gorb'], + 'brogan': ['barong', 'brogan'], + 'broggle': ['boggler', 'broggle'], + 'brolga': ['brolga', 'gorbal'], + 'broma': ['broma', 'rambo'], + 'bromate': ['barmote', 'bromate'], + 'brome': ['brome', 'omber'], + 'brominate': ['brominate', 'tribonema'], + 'bromohydrate': ['bromohydrate', 'hydrobromate'], + 'bronze': ['bonzer', 'bronze'], + 'broo': ['boor', 'boro', 'broo'], + 'brooch': ['brocho', 'brooch'], + 'brooke': ['booker', 'brooke', 'rebook'], + 'broon': ['boron', 'broon'], + 'brose': ['boser', 'brose', 'sober'], + 'brot': ['bort', 'brot'], + 'brotan': ['barton', 'brotan'], + 'brotany': ['baryton', 'brotany'], + 'broth': ['broth', 'throb'], + 'brothelry': ['brothelry', 'brotherly'], + 'brotherly': ['brothelry', 'brotherly'], + 'browden': ['bedrown', 'browden'], + 'browner': ['browner', 'rebrown'], + 'browntail': ['browntail', 'wrainbolt'], + 'bruce': ['bruce', 'cebur', 'cuber'], + 'brucina': ['brucina', 'rubican'], + 'bruckle': ['bruckle', 'buckler'], + 'brugh': ['brugh', 'burgh'], + 'bruin': ['bruin', 'burin', 'inrub'], + 'bruiser': ['brisure', 'bruiser'], + 'bruke': ['bruke', 'burke'], + 'brule': ['bluer', 'brule', 'burel', 'ruble'], + 'brulee': ['brulee', 'burele', 'reblue'], + 'brumal': ['brumal', 'labrum', 'lumbar', 'umbral'], + 'brumalia': ['albarium', 'brumalia'], + 'brume': ['brume', 'umber'], + 'brumous': ['brumous', 'umbrous'], + 'brunellia': ['brunellia', 'unliberal'], + 'brunet': ['brunet', 'bunter', 'burnet'], + 'bruno': ['bourn', 'bruno'], + 'brunt': ['brunt', 'burnt'], + 'brush': ['brush', 'shrub'], + 'brushed': ['brushed', 'subherd'], + 'brusher': ['brusher', 'rebrush'], + 'brushland': ['brushland', 'shrubland'], + 'brushless': ['brushless', 'shrubless'], + 'brushlet': ['brushlet', 'shrublet'], + 'brushlike': ['brushlike', 'shrublike'], + 'brushwood': ['brushwood', 'shrubwood'], + 'brustle': ['bluster', 'brustle', 'bustler'], + 'brut': ['brut', 'burt', 'trub', 'turb'], + 'bruta': ['bruta', 'tubar'], + 'brute': ['brute', 'buret', 'rebut', 'tuber'], + 'brutely': ['brutely', 'butlery'], + 'bryan': ['barny', 'bryan'], + 'bryanite': ['barytine', 'bryanite'], + 'bryce': ['becry', 'bryce'], + 'bual': ['balu', 'baul', 'bual', 'luba'], + 'buba': ['babu', 'buba'], + 'bubal': ['babul', 'bubal'], + 'bubbler': ['blubber', 'bubbler'], + 'buccocervical': ['buccocervical', 'cervicobuccal'], + 'bucconasal': ['bucconasal', 'nasobuccal'], + 'buceros': ['bescour', 'buceros', 'obscure'], + 'buckbush': ['buckbush', 'bushbuck'], + 'bucked': ['beduck', 'bucked'], + 'buckler': ['bruckle', 'buckler'], + 'bucksaw': ['bucksaw', 'sawbuck'], + 'bucrane': ['bucrane', 'unbrace'], + 'bud': ['bud', 'dub'], + 'buda': ['baud', 'buda', 'daub'], + 'budder': ['budder', 'redbud'], + 'budger': ['bedrug', 'budger'], + 'budgeter': ['budgeter', 'rebudget'], + 'budtime': ['bitumed', 'budtime'], + 'buffer': ['buffer', 'rebuff'], + 'buffeter': ['buffeter', 'rebuffet'], + 'bugan': ['bugan', 'bunga', 'unbag'], + 'bughouse': ['bughouse', 'housebug'], + 'bugi': ['bugi', 'guib'], + 'bugle': ['bugle', 'bulge'], + 'bugler': ['bugler', 'bulger', 'burgle'], + 'bugre': ['bugre', 'gebur'], + 'builder': ['builder', 'rebuild'], + 'buildup': ['buildup', 'upbuild'], + 'buirdly': ['buirdly', 'ludibry'], + 'bulanda': ['balunda', 'bulanda'], + 'bulb': ['blub', 'bulb'], + 'bulgarian': ['biangular', 'bulgarian'], + 'bulge': ['bugle', 'bulge'], + 'bulger': ['bugler', 'bulger', 'burgle'], + 'bulimic': ['bulimic', 'umbilic'], + 'bulimiform': ['bulimiform', 'umbiliform'], + 'bulker': ['bulker', 'rebulk'], + 'bulla': ['bulla', 'lulab'], + 'bullace': ['bullace', 'cueball'], + 'bulletin': ['bulletin', 'unbillet'], + 'bullfeast': ['bullfeast', 'stableful'], + 'bulse': ['blues', 'bulse'], + 'bulter': ['bulter', 'burlet', 'butler'], + 'bummler': ['bummler', 'mumbler'], + 'bun': ['bun', 'nub'], + 'buna': ['baun', 'buna', 'nabu', 'nuba'], + 'buncal': ['buncal', 'lucban'], + 'buncher': ['buncher', 'rebunch'], + 'bunder': ['bunder', 'burden', 'burned', 'unbred'], + 'bundle': ['bundle', 'unbled'], + 'bundler': ['blunder', 'bundler'], + 'bundu': ['bundu', 'unbud', 'undub'], + 'bunga': ['bugan', 'bunga', 'unbag'], + 'bungle': ['blunge', 'bungle'], + 'bungler': ['blunger', 'bungler'], + 'bungo': ['bungo', 'unbog'], + 'bunk': ['bunk', 'knub'], + 'bunter': ['brunet', 'bunter', 'burnet'], + 'bunty': ['bunty', 'butyn'], + 'bunya': ['bunya', 'unbay'], + 'bur': ['bur', 'rub'], + 'buran': ['buran', 'unbar', 'urban'], + 'burble': ['burble', 'lubber', 'rubble'], + 'burbler': ['burbler', 'rubbler'], + 'burbly': ['burbly', 'rubbly'], + 'burd': ['burd', 'drub'], + 'burdalone': ['burdalone', 'unlabored'], + 'burden': ['bunder', 'burden', 'burned', 'unbred'], + 'burdener': ['burdener', 'reburden'], + 'burdie': ['burdie', 'buried', 'rubied'], + 'bure': ['bure', 'reub', 'rube'], + 'burel': ['bluer', 'brule', 'burel', 'ruble'], + 'burele': ['brulee', 'burele', 'reblue'], + 'buret': ['brute', 'buret', 'rebut', 'tuber'], + 'burfish': ['burfish', 'furbish'], + 'burg': ['burg', 'grub'], + 'burgh': ['brugh', 'burgh'], + 'burgle': ['bugler', 'bulger', 'burgle'], + 'burian': ['burian', 'urbian'], + 'buried': ['burdie', 'buried', 'rubied'], + 'burin': ['bruin', 'burin', 'inrub'], + 'burke': ['bruke', 'burke'], + 'burl': ['blur', 'burl'], + 'burler': ['burler', 'burrel'], + 'burlet': ['bulter', 'burlet', 'butler'], + 'burletta': ['burletta', 'rebuttal'], + 'burmite': ['burmite', 'imbrute', 'terbium'], + 'burned': ['bunder', 'burden', 'burned', 'unbred'], + 'burner': ['burner', 'reburn'], + 'burnet': ['brunet', 'bunter', 'burnet'], + 'burnfire': ['burnfire', 'fireburn'], + 'burnie': ['burnie', 'rubine'], + 'burnisher': ['burnisher', 'reburnish'], + 'burnout': ['burnout', 'outburn'], + 'burnover': ['burnover', 'overburn'], + 'burnsides': ['burnsides', 'sideburns'], + 'burnt': ['brunt', 'burnt'], + 'burny': ['burny', 'runby'], + 'buro': ['buro', 'roub'], + 'burrel': ['burler', 'burrel'], + 'burro': ['burro', 'robur', 'rubor'], + 'bursa': ['abrus', 'bursa', 'subra'], + 'bursal': ['bursal', 'labrus'], + 'bursate': ['bursate', 'surbate'], + 'burse': ['burse', 'rebus', 'suber'], + 'burst': ['burst', 'strub'], + 'burster': ['burster', 'reburst'], + 'burt': ['brut', 'burt', 'trub', 'turb'], + 'burut': ['burut', 'trubu'], + 'bury': ['bury', 'ruby'], + 'bus': ['bus', 'sub'], + 'buscarle': ['arbuscle', 'buscarle'], + 'bushbuck': ['buckbush', 'bushbuck'], + 'busher': ['busher', 'rebush'], + 'bushwood': ['bushwood', 'woodbush'], + 'busied': ['busied', 'subdie'], + 'busked': ['bedusk', 'busked'], + 'busman': ['busman', 'subman'], + 'bust': ['bust', 'stub'], + 'busted': ['bedust', 'bestud', 'busted'], + 'buster': ['berust', 'buster', 'stuber'], + 'bustic': ['bustic', 'cubist'], + 'bustle': ['bustle', 'sublet', 'subtle'], + 'bustler': ['bluster', 'brustle', 'bustler'], + 'but': ['but', 'tub'], + 'bute': ['bute', 'tebu', 'tube'], + 'butea': ['butea', 'taube', 'tubae'], + 'butein': ['butein', 'butine', 'intube'], + 'butic': ['butic', 'cubit'], + 'butine': ['butein', 'butine', 'intube'], + 'butler': ['bulter', 'burlet', 'butler'], + 'butleress': ['butleress', 'tuberless'], + 'butlery': ['brutely', 'butlery'], + 'buttle': ['buttle', 'tublet'], + 'buttoner': ['buttoner', 'rebutton'], + 'butyn': ['bunty', 'butyn'], + 'buyer': ['buyer', 'rebuy'], + 'bye': ['bey', 'bye'], + 'byeman': ['byeman', 'byname'], + 'byerite': ['byerite', 'ebriety'], + 'bygo': ['bogy', 'bygo', 'goby'], + 'byname': ['byeman', 'byname'], + 'byon': ['bony', 'byon'], + 'byous': ['bousy', 'byous'], + 'byre': ['brey', 'byre', 'yerb'], + 'byrlaw': ['brawly', 'byrlaw', 'warbly'], + 'byroad': ['boardy', 'boyard', 'byroad'], + 'cab': ['bac', 'cab'], + 'caba': ['abac', 'caba'], + 'cabaan': ['cabaan', 'cabana', 'canaba'], + 'cabala': ['cabala', 'calaba'], + 'cabaletta': ['ablactate', 'cabaletta'], + 'cabalism': ['balsamic', 'cabalism'], + 'cabalist': ['basaltic', 'cabalist'], + 'caballer': ['barcella', 'caballer'], + 'caban': ['banca', 'caban'], + 'cabana': ['cabaan', 'cabana', 'canaba'], + 'cabaret': ['abreact', 'bractea', 'cabaret'], + 'cabbler': ['cabbler', 'clabber'], + 'caber': ['acerb', 'brace', 'caber'], + 'cabio': ['baioc', 'cabio', 'cobia'], + 'cabiri': ['cabiri', 'caribi'], + 'cabirian': ['arabinic', 'cabirian', 'carabini', 'cibarian'], + 'cable': ['cable', 'caleb'], + 'cabled': ['beclad', 'cabled'], + 'cabob': ['bobac', 'cabob'], + 'cabocle': ['boccale', 'cabocle'], + 'cabombaceae': ['bombacaceae', 'cabombaceae'], + 'cabrilla': ['bacillar', 'cabrilla'], + 'caca': ['acca', 'caca'], + 'cachet': ['cachet', 'chacte'], + 'cachou': ['cachou', 'caucho'], + 'cackler': ['cackler', 'clacker', 'crackle'], + 'cacodaemonic': ['cacodaemonic', 'cacodemoniac'], + 'cacodemoniac': ['cacodaemonic', 'cacodemoniac'], + 'cacomistle': ['cacomistle', 'cosmetical'], + 'cacoxenite': ['cacoxenite', 'excecation'], + 'cactaceae': ['cactaceae', 'taccaceae'], + 'cactaceous': ['cactaceous', 'taccaceous'], + 'cacti': ['cacti', 'ticca'], + 'cactoid': ['cactoid', 'octadic'], + 'caddice': ['caddice', 'decadic'], + 'caddie': ['caddie', 'eddaic'], + 'cade': ['cade', 'dace', 'ecad'], + 'cadent': ['cadent', 'canted', 'decant'], + 'cadential': ['cadential', 'dancalite'], + 'cader': ['acred', 'cader', 'cadre', 'cedar'], + 'cadet': ['cadet', 'ectad'], + 'cadge': ['cadge', 'caged'], + 'cadger': ['cadger', 'cradge'], + 'cadi': ['acid', 'cadi', 'caid'], + 'cadinene': ['cadinene', 'decennia', 'enneadic'], + 'cadmia': ['adamic', 'cadmia'], + 'cados': ['cados', 'scoad'], + 'cadre': ['acred', 'cader', 'cadre', 'cedar'], + 'cadua': ['cadua', 'cauda'], + 'caduac': ['caduac', 'caduca'], + 'caduca': ['caduac', 'caduca'], + 'cadus': ['cadus', 'dacus'], + 'caeciliae': ['caeciliae', 'ilicaceae'], + 'caedmonian': ['caedmonian', 'macedonian'], + 'caedmonic': ['caedmonic', 'macedonic'], + 'caelum': ['almuce', 'caelum', 'macule'], + 'caelus': ['caelus', 'caules', 'clause'], + 'caesar': ['ascare', 'caesar', 'resaca'], + 'caesarist': ['caesarist', 'staircase'], + 'caesura': ['auresca', 'caesura'], + 'caffeina': ['affiance', 'caffeina'], + 'caged': ['cadge', 'caged'], + 'cageling': ['cageling', 'glaceing'], + 'cager': ['cager', 'garce', 'grace'], + 'cahill': ['achill', 'cahill', 'chilla'], + 'cahita': ['cahita', 'ithaca'], + 'cahnite': ['cahnite', 'cathine'], + 'caid': ['acid', 'cadi', 'caid'], + 'caiman': ['amniac', 'caiman', 'maniac'], + 'caimito': ['caimito', 'comitia'], + 'cain': ['cain', 'inca'], + 'cainism': ['cainism', 'misniac'], + 'cairba': ['arabic', 'cairba'], + 'caird': ['acrid', 'caird', 'carid', 'darci', 'daric', 'dirca'], + 'cairene': ['cairene', 'cinerea'], + 'cairn': ['cairn', 'crain', 'naric'], + 'cairned': ['cairned', 'candier'], + 'cairny': ['cairny', 'riancy'], + 'cairo': ['cairo', 'oaric'], + 'caisson': ['caisson', 'cassino'], + 'cajoler': ['cajoler', 'jecoral'], + 'caker': ['acker', 'caker', 'crake', 'creak'], + 'cakey': ['ackey', 'cakey'], + 'cal': ['cal', 'lac'], + 'calaba': ['cabala', 'calaba'], + 'calamine': ['alcamine', 'analcime', 'calamine', 'camelina'], + 'calamint': ['calamint', 'claimant'], + 'calamitean': ['calamitean', 'catamenial'], + 'calander': ['calander', 'calendar'], + 'calandrinae': ['calandrinae', 'calendarian'], + 'calas': ['calas', 'casal', 'scala'], + 'calash': ['calash', 'lachsa'], + 'calathian': ['acanthial', 'calathian'], + 'calaverite': ['calaverite', 'lacerative'], + 'calcareocorneous': ['calcareocorneous', 'corneocalcareous'], + 'calcareosiliceous': ['calcareosiliceous', 'siliceocalcareous'], + 'calciner': ['calciner', 'larcenic'], + 'calculary': ['calculary', 'calycular'], + 'calculative': ['calculative', 'claviculate'], + 'calden': ['calden', 'candle', 'lanced'], + 'calean': ['anlace', 'calean'], + 'caleb': ['cable', 'caleb'], + 'caledonia': ['caledonia', 'laodicean'], + 'caledonite': ['caledonite', 'celadonite'], + 'calendar': ['calander', 'calendar'], + 'calendarial': ['calendarial', 'dalecarlian'], + 'calendarian': ['calandrinae', 'calendarian'], + 'calender': ['calender', 'encradle'], + 'calenture': ['calenture', 'crenulate'], + 'calepin': ['calepin', 'capelin', 'panicle', 'pelican', 'pinacle'], + 'calfkill': ['calfkill', 'killcalf'], + 'caliban': ['balanic', 'caliban'], + 'caliber': ['caliber', 'calibre'], + 'calibered': ['bridelace', 'calibered'], + 'calibrate': ['bacterial', 'calibrate'], + 'calibre': ['caliber', 'calibre'], + 'caliburno': ['binocular', 'caliburno', 'colubrina'], + 'calico': ['accoil', 'calico'], + 'calidity': ['calidity', 'dialytic'], + 'caliga': ['caliga', 'cigala'], + 'calinago': ['analogic', 'calinago'], + 'calinut': ['calinut', 'lunatic'], + 'caliper': ['caliper', 'picarel', 'replica'], + 'calipers': ['calipers', 'spiracle'], + 'caliphate': ['caliphate', 'hepatical'], + 'calite': ['calite', 'laetic', 'tecali'], + 'caliver': ['caliver', 'caviler', 'claiver', 'clavier', 'valeric', 'velaric'], + 'calk': ['calk', 'lack'], + 'calker': ['calker', 'lacker', 'rackle', 'recalk', 'reckla'], + 'callboy': ['callboy', 'collyba'], + 'caller': ['caller', 'cellar', 'recall'], + 'calli': ['calli', 'lilac'], + 'calligraphy': ['calligraphy', 'graphically'], + 'calliopsis': ['calliopsis', 'lipoclasis'], + 'callisection': ['callisection', 'clinoclasite'], + 'callitype': ['callitype', 'plicately'], + 'callo': ['callo', 'colla', 'local'], + 'callosal': ['callosal', 'scallola'], + 'callose': ['callose', 'oscella'], + 'callosity': ['callosity', 'stoically'], + 'callosum': ['callosum', 'mollusca'], + 'calluna': ['calluna', 'lacunal'], + 'callus': ['callus', 'sulcal'], + 'calm': ['calm', 'clam'], + 'calmant': ['calmant', 'clamant'], + 'calmative': ['calmative', 'clamative'], + 'calmer': ['calmer', 'carmel', 'clamer', 'marcel', 'mercal'], + 'calmierer': ['calmierer', 'reclaimer'], + 'calomba': ['calomba', 'cambalo'], + 'calonectria': ['calonectria', 'ectocranial'], + 'calor': ['alcor', 'calor', 'carlo', 'carol', 'claro', 'coral'], + 'calorie': ['calorie', 'cariole'], + 'calorist': ['calorist', 'coralist'], + 'calorite': ['calorite', 'erotical', 'loricate'], + 'calorize': ['calorize', 'coalizer'], + 'calotermes': ['calotermes', 'mesorectal', 'metacresol'], + 'calotermitid': ['calotermitid', 'dilatometric'], + 'calp': ['calp', 'clap'], + 'caltha': ['caltha', 'chalta'], + 'caltrop': ['caltrop', 'proctal'], + 'calusa': ['ascula', 'calusa', 'casual', 'casula', 'causal'], + 'calvaria': ['calvaria', 'clavaria'], + 'calvary': ['calvary', 'cavalry'], + 'calve': ['calve', 'cavel', 'clave'], + 'calver': ['calver', 'carvel', 'claver'], + 'calves': ['calves', 'scavel'], + 'calycular': ['calculary', 'calycular'], + 'calyptratae': ['acalyptrate', 'calyptratae'], + 'cam': ['cam', 'mac'], + 'camaca': ['camaca', 'macaca'], + 'camail': ['amical', 'camail', 'lamaic'], + 'caman': ['caman', 'macan'], + 'camara': ['acamar', 'camara', 'maraca'], + 'cambalo': ['calomba', 'cambalo'], + 'camber': ['becram', 'camber', 'crambe'], + 'cambrel': ['cambrel', 'clamber', 'cramble'], + 'came': ['acme', 'came', 'mace'], + 'cameist': ['cameist', 'etacism', 'sematic'], + 'camel': ['camel', 'clame', 'cleam', 'macle'], + 'camelid': ['camelid', 'decimal', 'declaim', 'medical'], + 'camelina': ['alcamine', 'analcime', 'calamine', 'camelina'], + 'camelish': ['camelish', 'schalmei'], + 'camellus': ['camellus', 'sacellum'], + 'cameloid': ['cameloid', 'comedial', 'melodica'], + 'cameograph': ['cameograph', 'macrophage'], + 'camera': ['acream', 'camera', 'mareca'], + 'cameral': ['cameral', 'caramel', 'carmela', 'ceramal', 'reclama'], + 'camerate': ['camerate', 'macerate', 'racemate'], + 'camerated': ['camerated', 'demarcate'], + 'cameration': ['aeromantic', 'cameration', 'maceration', 'racemation'], + 'camerina': ['amacrine', 'american', 'camerina', 'cinerama'], + 'camerist': ['camerist', 'ceramist', 'matrices'], + 'camion': ['camion', 'conima', 'manioc', 'monica'], + 'camisado': ['camisado', 'caodaism'], + 'camise': ['camise', 'macies'], + 'campaign': ['campaign', 'pangamic'], + 'campaigner': ['campaigner', 'recampaign'], + 'camphire': ['camphire', 'hemicarp'], + 'campine': ['campine', 'pemican'], + 'campoo': ['campoo', 'capomo'], + 'camptonite': ['camptonite', 'pentatomic'], + 'camus': ['camus', 'musca', 'scaum', 'sumac'], + 'camused': ['camused', 'muscade'], + 'canaba': ['cabaan', 'cabana', 'canaba'], + 'canadol': ['acnodal', 'canadol', 'locanda'], + 'canaille': ['alliance', 'canaille'], + 'canape': ['canape', 'panace'], + 'canari': ['acinar', + 'arnica', + 'canari', + 'carian', + 'carina', + 'crania', + 'narica'], + 'canarin': ['canarin', 'cranian'], + 'canariote': ['canariote', 'ceratonia'], + 'canary': ['canary', 'cynara'], + 'canaut': ['canaut', 'tucana'], + 'canceler': ['canceler', 'clarence', 'recancel'], + 'cancer': ['cancer', 'crance'], + 'cancerate': ['cancerate', 'reactance'], + 'canceration': ['anacreontic', 'canceration'], + 'cancri': ['cancri', 'carnic', 'cranic'], + 'cancroid': ['cancroid', 'draconic'], + 'candela': ['candela', 'decanal'], + 'candier': ['cairned', 'candier'], + 'candiru': ['candiru', 'iracund'], + 'candle': ['calden', 'candle', 'lanced'], + 'candor': ['candor', 'cardon', 'conrad'], + 'candroy': ['candroy', 'dacryon'], + 'cane': ['acne', 'cane', 'nace'], + 'canel': ['canel', 'clean', 'lance', 'lenca'], + 'canelo': ['canelo', 'colane'], + 'canephor': ['canephor', 'chaperno', 'chaperon'], + 'canephore': ['canephore', 'chaperone'], + 'canephroi': ['canephroi', 'parochine'], + 'caner': ['caner', 'crane', 'crena', 'nacre', 'rance'], + 'canful': ['canful', 'flucan'], + 'cangle': ['cangle', 'glance'], + 'cangler': ['cangler', 'glancer', 'reclang'], + 'cangue': ['cangue', 'uncage'], + 'canicola': ['canicola', 'laconica'], + 'canid': ['canid', 'cnida', 'danic'], + 'canidae': ['aidance', 'canidae'], + 'canine': ['canine', 'encina', 'neanic'], + 'canis': ['canis', 'scian'], + 'canister': ['canister', 'cestrian', 'cisterna', 'irascent'], + 'canker': ['canker', 'neckar'], + 'cankerworm': ['cankerworm', 'crownmaker'], + 'cannel': ['cannel', 'lencan'], + 'cannot': ['cannot', 'canton', 'conant', 'nonact'], + 'cannulate': ['antelucan', 'cannulate'], + 'canny': ['canny', 'nancy'], + 'canoe': ['acone', 'canoe', 'ocean'], + 'canoeing': ['anogenic', 'canoeing'], + 'canoeist': ['canoeist', 'cotesian'], + 'canon': ['ancon', 'canon'], + 'canonist': ['canonist', 'sanction', 'sonantic'], + 'canoodler': ['canoodler', 'coronaled'], + 'canroy': ['canroy', 'crayon', 'cyrano', 'nyroca'], + 'canso': ['ascon', 'canso', 'oscan'], + 'cantabri': ['bactrian', 'cantabri'], + 'cantala': ['cantala', 'catalan', 'lantaca'], + 'cantalite': ['cantalite', 'lactinate', 'tetanical'], + 'cantara': ['cantara', 'nacarat'], + 'cantaro': ['cantaro', 'croatan'], + 'cantate': ['anteact', 'cantate'], + 'canted': ['cadent', 'canted', 'decant'], + 'canteen': ['canteen', 'centena'], + 'canter': ['canter', + 'creant', + 'cretan', + 'nectar', + 'recant', + 'tanrec', + 'trance'], + 'canterer': ['canterer', 'recanter', 'recreant', 'terrance'], + 'cantharidae': ['acidanthera', 'cantharidae'], + 'cantharis': ['anarchist', 'archsaint', 'cantharis'], + 'canthus': ['canthus', 'staunch'], + 'cantico': ['cantico', 'catonic', 'taconic'], + 'cantilena': ['cantilena', 'lancinate'], + 'cantilever': ['cantilever', 'trivalence'], + 'cantily': ['anticly', 'cantily'], + 'cantina': ['cantina', 'tannaic'], + 'cantiness': ['anticness', 'cantiness', 'incessant'], + 'cantion': ['actinon', 'cantion', 'contain'], + 'cantle': ['cantle', 'cental', 'lancet', 'tancel'], + 'canto': ['acton', 'canto', 'octan'], + 'canton': ['cannot', 'canton', 'conant', 'nonact'], + 'cantonal': ['cantonal', 'connatal'], + 'cantor': ['cantor', 'carton', 'contra'], + 'cantorian': ['anarcotin', 'cantorian', 'carnation', 'narcotina'], + 'cantoris': ['cantoris', 'castorin', 'corsaint'], + 'cantred': ['cantred', 'centrad', 'tranced'], + 'cantus': ['cantus', 'tuscan', 'uncast'], + 'canun': ['canun', 'cunan'], + 'cany': ['cany', 'cyan'], + 'canyon': ['ancony', 'canyon'], + 'caoba': ['bacao', 'caoba'], + 'caodaism': ['camisado', 'caodaism'], + 'cap': ['cap', 'pac'], + 'capable': ['capable', 'pacable'], + 'caparison': ['caparison', 'paranosic'], + 'cape': ['cape', 'cepa', 'pace'], + 'caped': ['caped', 'decap', 'paced'], + 'capel': ['capel', 'place'], + 'capelin': ['calepin', 'capelin', 'panicle', 'pelican', 'pinacle'], + 'capeline': ['capeline', 'pelecani'], + 'caper': ['caper', 'crape', 'pacer', 'perca', 'recap'], + 'capernaite': ['capernaite', 'paraenetic'], + 'capernoited': ['capernoited', 'deprecation'], + 'capernoity': ['acetopyrin', 'capernoity'], + 'capes': ['capes', 'scape', 'space'], + 'caph': ['caph', 'chap'], + 'caphite': ['aphetic', 'caphite', 'hepatic'], + 'caphtor': ['caphtor', 'toparch'], + 'capias': ['capias', 'pisaca'], + 'capillament': ['capillament', 'implacental'], + 'capillarity': ['capillarity', 'piratically'], + 'capital': ['capital', 'palatic'], + 'capitan': ['capitan', 'captain'], + 'capitate': ['apatetic', 'capitate'], + 'capitellar': ['capitellar', 'prelatical'], + 'capito': ['atopic', 'capito', 'copita'], + 'capitol': ['capitol', 'coalpit', 'optical', 'topical'], + 'capomo': ['campoo', 'capomo'], + 'capon': ['capon', 'ponca'], + 'caponier': ['caponier', 'coprinae', 'procaine'], + 'capot': ['capot', 'coapt'], + 'capote': ['capote', 'toecap'], + 'capreol': ['capreol', 'polacre'], + 'capri': ['capri', 'picra', 'rapic'], + 'caprid': ['caprid', 'carpid', 'picard'], + 'capriote': ['aporetic', 'capriote', 'operatic'], + 'capsian': ['capsian', 'caspian', 'nascapi', 'panisca'], + 'capstone': ['capstone', 'opencast'], + 'capsula': ['capsula', 'pascual', 'scapula'], + 'capsular': ['capsular', 'scapular'], + 'capsulate': ['aspectual', 'capsulate'], + 'capsulated': ['capsulated', 'scapulated'], + 'capsule': ['capsule', 'specula', 'upscale'], + 'capsulectomy': ['capsulectomy', 'scapulectomy'], + 'capsuler': ['capsuler', 'specular'], + 'captain': ['capitan', 'captain'], + 'captation': ['anaptotic', 'captation'], + 'caption': ['caption', 'paction'], + 'captious': ['autopsic', 'captious'], + 'captor': ['captor', 'copart'], + 'capture': ['capture', 'uptrace'], + 'car': ['arc', 'car'], + 'cara': ['arca', 'cara'], + 'carabeen': ['bearance', 'carabeen'], + 'carabin': ['arbacin', 'carabin', 'cariban'], + 'carabini': ['arabinic', 'cabirian', 'carabini', 'cibarian'], + 'caracoli': ['caracoli', 'coracial'], + 'caracore': ['acrocera', 'caracore'], + 'caragana': ['aracanga', 'caragana'], + 'caramel': ['cameral', 'caramel', 'carmela', 'ceramal', 'reclama'], + 'caranda': ['anacard', 'caranda'], + 'carandas': ['carandas', 'sandarac'], + 'carane': ['arcane', 'carane'], + 'carangid': ['carangid', 'cardigan'], + 'carapine': ['carapine', 'carpaine'], + 'caravel': ['caravel', 'lavacre'], + 'carbamide': ['carbamide', 'crambidae'], + 'carbamine': ['carbamine', 'crambinae'], + 'carbamino': ['carbamino', 'macrobian'], + 'carbeen': ['carbeen', 'carbene'], + 'carbene': ['carbeen', 'carbene'], + 'carbo': ['carbo', 'carob', 'coarb', 'cobra'], + 'carbohydride': ['carbohydride', 'hydrocarbide'], + 'carbon': ['bracon', 'carbon', 'corban'], + 'carbonite': ['bicornate', 'carbonite', 'reboantic'], + 'carcel': ['carcel', 'cercal'], + 'carcinoma': ['carcinoma', 'macaronic'], + 'carcinosarcoma': ['carcinosarcoma', 'sarcocarcinoma'], + 'carcoon': ['carcoon', 'raccoon'], + 'cardel': ['cardel', 'cradle'], + 'cardia': ['acarid', 'cardia', 'carida'], + 'cardiac': ['arcadic', 'cardiac'], + 'cardial': ['cardial', 'radical'], + 'cardiant': ['antacrid', 'cardiant', 'radicant', 'tridacna'], + 'cardigan': ['carangid', 'cardigan'], + 'cardiidae': ['acrididae', 'cardiidae', 'cidaridae'], + 'cardin': ['andric', 'cardin', 'rancid'], + 'cardinal': ['cardinal', 'clarinda'], + 'cardioid': ['cardioid', 'caridoid'], + 'cardiophobe': ['brachiopode', 'cardiophobe'], + 'cardo': ['cardo', 'draco'], + 'cardon': ['candor', 'cardon', 'conrad'], + 'cardoon': ['cardoon', 'coronad'], + 'care': ['acer', 'acre', 'care', 'crea', 'race'], + 'careen': ['careen', 'carene', 'enrace'], + 'carene': ['careen', 'carene', 'enrace'], + 'carer': ['carer', 'crare', 'racer'], + 'carest': ['carest', 'caster', 'recast'], + 'caret': ['caret', + 'carte', + 'cater', + 'crate', + 'creat', + 'creta', + 'react', + 'recta', + 'trace'], + 'caretta': ['caretta', 'teacart', 'tearcat'], + 'carful': ['carful', 'furcal'], + 'carhop': ['carhop', 'paroch'], + 'cariama': ['aramaic', 'cariama'], + 'carian': ['acinar', + 'arnica', + 'canari', + 'carian', + 'carina', + 'crania', + 'narica'], + 'carib': ['baric', 'carib', 'rabic'], + 'cariban': ['arbacin', 'carabin', 'cariban'], + 'caribi': ['cabiri', 'caribi'], + 'carid': ['acrid', 'caird', 'carid', 'darci', 'daric', 'dirca'], + 'carida': ['acarid', 'cardia', 'carida'], + 'caridea': ['arcidae', 'caridea'], + 'caridean': ['caridean', 'dircaean', 'radiance'], + 'caridoid': ['cardioid', 'caridoid'], + 'carina': ['acinar', + 'arnica', + 'canari', + 'carian', + 'carina', + 'crania', + 'narica'], + 'carinal': ['carinal', 'carlina', 'clarain', 'cranial'], + 'carinatae': ['acraniate', 'carinatae'], + 'carinate': ['anaretic', 'arcanite', 'carinate', 'craniate'], + 'carinated': ['carinated', 'eradicant'], + 'cariole': ['calorie', 'cariole'], + 'carious': ['carious', 'curiosa'], + 'carisa': ['carisa', 'sciara'], + 'carissa': ['ascaris', 'carissa'], + 'cark': ['cark', 'rack'], + 'carking': ['arcking', 'carking', 'racking'], + 'carkingly': ['carkingly', 'rackingly'], + 'carless': ['carless', 'classer', 'reclass'], + 'carlet': ['carlet', 'cartel', 'claret', 'rectal', 'talcer'], + 'carlie': ['carlie', 'claire', 'eclair', 'erical'], + 'carlin': ['carlin', 'clarin', 'crinal'], + 'carlina': ['carinal', 'carlina', 'clarain', 'cranial'], + 'carlist': ['carlist', 'clarist'], + 'carlo': ['alcor', 'calor', 'carlo', 'carol', 'claro', 'coral'], + 'carlot': ['carlot', 'crotal'], + 'carlylian': ['ancillary', 'carlylian', 'cranially'], + 'carman': ['carman', 'marcan'], + 'carmel': ['calmer', 'carmel', 'clamer', 'marcel', 'mercal'], + 'carmela': ['cameral', 'caramel', 'carmela', 'ceramal', 'reclama'], + 'carmele': ['carmele', 'cleamer'], + 'carmelite': ['carmelite', 'melicerta'], + 'carmeloite': ['carmeloite', 'ectromelia', 'meteorical'], + 'carmine': ['armenic', 'carmine', 'ceriman', 'crimean', 'mercian'], + 'carminette': ['carminette', 'remittance'], + 'carminite': ['antimeric', 'carminite', 'criminate', 'metrician'], + 'carmot': ['carmot', 'comart'], + 'carnage': ['carnage', 'cranage', 'garance'], + 'carnalite': ['carnalite', 'claretian', 'lacertian', 'nectarial'], + 'carnate': ['carnate', 'cateran'], + 'carnation': ['anarcotin', 'cantorian', 'carnation', 'narcotina'], + 'carnationed': ['carnationed', 'dinoceratan'], + 'carnelian': ['carnelian', 'encranial'], + 'carneol': ['carneol', 'corneal'], + 'carneous': ['carneous', 'nacreous'], + 'carney': ['carney', 'craney'], + 'carnic': ['cancri', 'carnic', 'cranic'], + 'carniolan': ['carniolan', 'nonracial'], + 'carnose': ['carnose', 'coarsen', 'narcose'], + 'carnosity': ['carnosity', 'crayonist'], + 'carnotite': ['carnotite', 'cortinate'], + 'carnous': ['carnous', 'nacrous', 'narcous'], + 'caro': ['acor', 'caro', 'cora', 'orca'], + 'caroa': ['acroa', 'caroa'], + 'carob': ['carbo', 'carob', 'coarb', 'cobra'], + 'caroche': ['caroche', 'coacher', 'recoach'], + 'caroid': ['caroid', 'cordia'], + 'carol': ['alcor', 'calor', 'carlo', 'carol', 'claro', 'coral'], + 'carolan': ['alcoran', 'ancoral', 'carolan'], + 'carole': ['carole', 'coaler', 'coelar', 'oracle', 'recoal'], + 'carolean': ['carolean', 'lecanora'], + 'caroler': ['caroler', 'correal'], + 'caroli': ['caroli', 'corial', 'lorica'], + 'carolin': ['carolin', 'clarion', 'colarin', 'locrian'], + 'carolina': ['carolina', 'conarial'], + 'caroline': ['acrolein', + 'arecolin', + 'caroline', + 'colinear', + 'cornelia', + 'creolian', + 'lonicera'], + 'carolingian': ['carolingian', 'inorganical'], + 'carolus': ['carolus', 'oscular'], + 'carom': ['carom', 'coram', 'macro', 'marco'], + 'carone': ['carone', 'cornea'], + 'caroon': ['caroon', 'corona', 'racoon'], + 'carotenoid': ['carotenoid', 'coronadite', 'decoration'], + 'carotic': ['acrotic', 'carotic'], + 'carotid': ['arctoid', 'carotid', 'dartoic'], + 'carotidean': ['arctoidean', 'carotidean', 'cordaitean', 'dinocerata'], + 'carotin': ['anticor', 'carotin', 'cortina', 'ontaric'], + 'carouse': ['acerous', 'carouse', 'euscaro'], + 'carp': ['carp', 'crap'], + 'carpaine': ['carapine', 'carpaine'], + 'carpel': ['carpel', 'parcel', 'placer'], + 'carpellary': ['carpellary', 'parcellary'], + 'carpellate': ['carpellate', 'parcellate', 'prelacteal'], + 'carpent': ['carpent', 'precant'], + 'carpet': ['carpet', 'peract', 'preact'], + 'carpholite': ['carpholite', 'proethical'], + 'carpid': ['caprid', 'carpid', 'picard'], + 'carpiodes': ['carpiodes', 'scorpidae'], + 'carpocerite': ['carpocerite', 'reciprocate'], + 'carpogonial': ['carpogonial', 'coprolagnia'], + 'carpolite': ['carpolite', 'petricola'], + 'carpolith': ['carpolith', 'politarch', 'trophical'], + 'carposperm': ['carposperm', 'spermocarp'], + 'carrot': ['carrot', 'trocar'], + 'carroter': ['arrector', 'carroter'], + 'carse': ['carse', 'caser', 'ceras', 'scare', 'scrae'], + 'carsmith': ['carsmith', 'chartism'], + 'cartable': ['bracteal', 'cartable'], + 'carte': ['caret', + 'carte', + 'cater', + 'crate', + 'creat', + 'creta', + 'react', + 'recta', + 'trace'], + 'cartel': ['carlet', 'cartel', 'claret', 'rectal', 'talcer'], + 'cartelize': ['cartelize', 'zelatrice'], + 'carter': ['arrect', 'carter', 'crater', 'recart', 'tracer'], + 'cartesian': ['ascertain', 'cartesian', 'cartisane', 'sectarian'], + 'cartesianism': ['cartesianism', 'sectarianism'], + 'cartier': ['cartier', 'cirrate', 'erratic'], + 'cartilage': ['cartilage', 'rectalgia'], + 'cartisane': ['ascertain', 'cartesian', 'cartisane', 'sectarian'], + 'cartist': ['astrict', 'cartist', 'stratic'], + 'carton': ['cantor', 'carton', 'contra'], + 'cartoon': ['cartoon', 'coranto'], + 'cartoonist': ['cartoonist', 'scortation'], + 'carty': ['carty', 'tracy'], + 'carua': ['aruac', 'carua'], + 'carucal': ['accrual', 'carucal'], + 'carucate': ['accurate', 'carucate'], + 'carum': ['carum', 'cumar'], + 'carve': ['carve', 'crave', 'varec'], + 'carvel': ['calver', 'carvel', 'claver'], + 'carven': ['carven', 'cavern', 'craven'], + 'carver': ['carver', 'craver'], + 'carving': ['carving', 'craving'], + 'cary': ['cary', 'racy'], + 'caryl': ['acryl', 'caryl', 'clary'], + 'casabe': ['casabe', 'sabeca'], + 'casal': ['calas', 'casal', 'scala'], + 'cascade': ['cascade', 'saccade'], + 'case': ['case', 'esca'], + 'casebook': ['bookcase', 'casebook'], + 'caseful': ['caseful', 'fucales'], + 'casein': ['casein', 'incase'], + 'casel': ['alces', 'casel', 'scale'], + 'caser': ['carse', 'caser', 'ceras', 'scare', 'scrae'], + 'casern': ['casern', 'rescan'], + 'cashable': ['cashable', 'chasable'], + 'cashel': ['cashel', 'laches', 'sealch'], + 'cask': ['cask', 'sack'], + 'casket': ['casket', 'tesack'], + 'casking': ['casking', 'sacking'], + 'casklike': ['casklike', 'sacklike'], + 'casper': ['casper', 'escarp', 'parsec', 'scrape', 'secpar', 'spacer'], + 'caspian': ['capsian', 'caspian', 'nascapi', 'panisca'], + 'casque': ['casque', 'sacque'], + 'casquet': ['acquest', 'casquet'], + 'casse': ['casse', 'scase'], + 'cassian': ['cassian', 'cassina'], + 'cassina': ['cassian', 'cassina'], + 'cassino': ['caisson', 'cassino'], + 'cassock': ['cassock', 'cossack'], + 'cast': ['acts', 'cast', 'scat'], + 'castalia': ['castalia', 'sacalait'], + 'castalian': ['castalian', 'satanical'], + 'caste': ['caste', 'sceat'], + 'castelet': ['castelet', 'telecast'], + 'caster': ['carest', 'caster', 'recast'], + 'castice': ['ascetic', 'castice', 'siccate'], + 'castle': ['castle', 'sclate'], + 'castoff': ['castoff', 'offcast'], + 'castor': ['arctos', 'castor', 'costar', 'scrota'], + 'castores': ['castores', 'coassert'], + 'castoreum': ['castoreum', 'outscream'], + 'castoridae': ['castoridae', 'cestodaria'], + 'castorin': ['cantoris', 'castorin', 'corsaint'], + 'castra': ['castra', 'tarasc'], + 'casual': ['ascula', 'calusa', 'casual', 'casula', 'causal'], + 'casuality': ['casuality', 'causality'], + 'casually': ['casually', 'causally'], + 'casula': ['ascula', 'calusa', 'casual', 'casula', 'causal'], + 'cat': ['act', 'cat'], + 'catabolin': ['botanical', 'catabolin'], + 'catalan': ['cantala', 'catalan', 'lantaca'], + 'catalanist': ['anastaltic', 'catalanist'], + 'catalase': ['catalase', 'salaceta'], + 'catalinite': ['analcitite', 'catalinite'], + 'catalogue': ['catalogue', 'coagulate'], + 'catalyte': ['catalyte', 'cattleya'], + 'catamenial': ['calamitean', 'catamenial'], + 'catapultier': ['catapultier', 'particulate'], + 'cataria': ['acratia', 'cataria'], + 'catcher': ['catcher', 'recatch'], + 'catchup': ['catchup', 'upcatch'], + 'cate': ['cate', 'teca'], + 'catechin': ['atechnic', 'catechin', 'technica'], + 'catechism': ['catechism', 'schematic'], + 'catechol': ['catechol', 'coachlet'], + 'categoric': ['categoric', 'geocratic'], + 'catella': ['catella', 'lacteal'], + 'catenated': ['catenated', 'decantate'], + 'cater': ['caret', + 'carte', + 'cater', + 'crate', + 'creat', + 'creta', + 'react', + 'recta', + 'trace'], + 'cateran': ['carnate', 'cateran'], + 'caterer': ['caterer', 'recrate', 'retrace', 'terrace'], + 'cateress': ['cateress', 'cerastes'], + 'catfish': ['catfish', 'factish'], + 'cathari': ['cathari', 'chirata', 'cithara'], + 'catharina': ['anthracia', 'antiarcha', 'catharina'], + 'cathartae': ['cathartae', 'tracheata'], + 'cathepsin': ['cathepsin', 'stephanic'], + 'catherine': ['catherine', 'heritance'], + 'catheter': ['catheter', 'charette'], + 'cathine': ['cahnite', 'cathine'], + 'cathinine': ['anchietin', 'cathinine'], + 'cathion': ['cathion', 'chatino'], + 'cathograph': ['cathograph', 'tachograph'], + 'cathole': ['cathole', 'cholate'], + 'cathro': ['cathro', 'orchat'], + 'cathryn': ['cathryn', 'chantry'], + 'cathy': ['cathy', 'cyath', 'yacht'], + 'cation': ['action', 'atonic', 'cation'], + 'cationic': ['aconitic', 'cationic', 'itaconic'], + 'catkin': ['catkin', 'natick'], + 'catlin': ['catlin', 'tincal'], + 'catlinite': ['catlinite', 'intactile'], + 'catmalison': ['catmalison', 'monastical'], + 'catoism': ['atomics', 'catoism', 'cosmati', 'osmatic', 'somatic'], + 'catonian': ['catonian', 'taconian'], + 'catonic': ['cantico', 'catonic', 'taconic'], + 'catonism': ['catonism', 'monastic'], + 'catoptric': ['catoptric', 'protactic'], + 'catpipe': ['apeptic', 'catpipe'], + 'catstone': ['catstone', 'constate'], + 'catsup': ['catsup', 'upcast'], + 'cattail': ['attical', 'cattail'], + 'catti': ['attic', 'catti', 'tacit'], + 'cattily': ['cattily', 'tacitly'], + 'cattiness': ['cattiness', 'tacitness'], + 'cattle': ['cattle', 'tectal'], + 'cattleya': ['catalyte', 'cattleya'], + 'catvine': ['catvine', 'venatic'], + 'caucho': ['cachou', 'caucho'], + 'cauda': ['cadua', 'cauda'], + 'caudle': ['caudle', 'cedula', 'claude'], + 'caudodorsal': ['caudodorsal', 'dorsocaudal'], + 'caudofemoral': ['caudofemoral', 'femorocaudal'], + 'caudolateral': ['caudolateral', 'laterocaudal'], + 'caul': ['caul', 'ucal'], + 'cauld': ['cauld', 'ducal'], + 'caules': ['caelus', 'caules', 'clause'], + 'cauliform': ['cauliform', 'formulaic', 'fumarolic'], + 'caulinar': ['anicular', 'caulinar'], + 'caulis': ['caulis', 'clusia', 'sicula'], + 'caulite': ['aleutic', 'auletic', 'caulite', 'lutecia'], + 'caulome': ['caulome', 'leucoma'], + 'caulomic': ['caulomic', 'coumalic'], + 'caulote': ['caulote', 'colutea', 'oculate'], + 'caunch': ['caunch', 'cuchan'], + 'caurale': ['arcuale', 'caurale'], + 'causal': ['ascula', 'calusa', 'casual', 'casula', 'causal'], + 'causality': ['casuality', 'causality'], + 'causally': ['casually', 'causally'], + 'cause': ['cause', 'sauce'], + 'causeless': ['causeless', 'sauceless'], + 'causer': ['causer', 'saucer'], + 'causey': ['causey', 'cayuse'], + 'cautelous': ['cautelous', 'lutaceous'], + 'cauter': ['acture', 'cauter', 'curate'], + 'caution': ['auction', 'caution'], + 'cautionary': ['auctionary', 'cautionary'], + 'cautioner': ['cautioner', 'cointreau'], + 'caval': ['caval', 'clava'], + 'cavalry': ['calvary', 'cavalry'], + 'cavate': ['cavate', 'caveat', 'vacate'], + 'caveat': ['cavate', 'caveat', 'vacate'], + 'cavel': ['calve', 'cavel', 'clave'], + 'cavern': ['carven', 'cavern', 'craven'], + 'cavil': ['cavil', 'lavic'], + 'caviler': ['caliver', 'caviler', 'claiver', 'clavier', 'valeric', 'velaric'], + 'cavillation': ['cavillation', 'vacillation'], + 'cavitate': ['activate', 'cavitate'], + 'cavitation': ['activation', 'cavitation'], + 'cavitied': ['cavitied', 'vaticide'], + 'caw': ['caw', 'wac'], + 'cawk': ['cawk', 'wack'], + 'cawky': ['cawky', 'wacky'], + 'cayapa': ['cayapa', 'pacaya'], + 'cayuse': ['causey', 'cayuse'], + 'ccoya': ['accoy', 'ccoya'], + 'ceanothus': ['ceanothus', 'oecanthus'], + 'cearin': ['acerin', 'cearin'], + 'cebalrai': ['balearic', 'cebalrai'], + 'ceboid': ['bodice', 'ceboid'], + 'cebur': ['bruce', 'cebur', 'cuber'], + 'cecily': ['cecily', 'cicely'], + 'cedar': ['acred', 'cader', 'cadre', 'cedar'], + 'cedarn': ['cedarn', 'dancer', 'nacred'], + 'cedent': ['cedent', 'decent'], + 'ceder': ['ceder', 'cedre', 'cered', 'creed'], + 'cedrat': ['cedrat', 'decart', 'redact'], + 'cedrate': ['cedrate', 'cerated'], + 'cedre': ['ceder', 'cedre', 'cered', 'creed'], + 'cedrela': ['cedrela', 'creedal', 'declare'], + 'cedrin': ['cedrin', 'cinder', 'crined'], + 'cedriret': ['cedriret', 'directer', 'recredit', 'redirect'], + 'cedrol': ['cedrol', 'colder', 'cordel'], + 'cedron': ['cedron', 'conred'], + 'cedrus': ['cedrus', 'cursed'], + 'cedry': ['cedry', 'decry'], + 'cedula': ['caudle', 'cedula', 'claude'], + 'ceilinged': ['ceilinged', 'diligence'], + 'celadonite': ['caledonite', 'celadonite'], + 'celandine': ['celandine', 'decennial'], + 'celarent': ['celarent', 'centrale', 'enclaret'], + 'celature': ['celature', 'ulcerate'], + 'celebrate': ['celebrate', 'erectable'], + 'celebrated': ['braceleted', 'celebrated'], + 'celemin': ['celemin', 'melenic'], + 'celia': ['alice', 'celia', 'ileac'], + 'cellar': ['caller', 'cellar', 'recall'], + 'cellaret': ['allecret', 'cellaret'], + 'celloid': ['celloid', 'codille', 'collide', 'collied'], + 'celloidin': ['celloidin', 'collidine', 'decillion'], + 'celsian': ['celsian', 'escalin', 'sanicle', 'secalin'], + 'celtiberi': ['celtiberi', 'terebilic'], + 'celtis': ['celtis', 'clites'], + 'cembalist': ['blastemic', 'cembalist'], + 'cementer': ['cementer', 'cerement', 'recement'], + 'cendre': ['cendre', 'decern'], + 'cenosity': ['cenosity', 'cytosine'], + 'cense': ['cense', 'scene', 'sence'], + 'censer': ['censer', 'scerne', 'screen', 'secern'], + 'censerless': ['censerless', 'screenless'], + 'censorial': ['censorial', 'sarcoline'], + 'censual': ['censual', 'unscale'], + 'censureless': ['censureless', 'recluseness'], + 'cental': ['cantle', 'cental', 'lancet', 'tancel'], + 'centare': ['centare', 'crenate'], + 'centaur': ['centaur', 'untrace'], + 'centauri': ['anuretic', 'centauri', 'centuria', 'teucrian'], + 'centaury': ['centaury', 'cyanuret'], + 'centena': ['canteen', 'centena'], + 'centenar': ['centenar', 'entrance'], + 'centenier': ['centenier', 'renitence'], + 'center': ['center', 'recent', 'tenrec'], + 'centered': ['centered', 'decenter', 'decentre', 'recedent'], + 'centerer': ['centerer', 'recenter', 'recentre', 'terrence'], + 'centermost': ['centermost', 'escortment'], + 'centesimal': ['centesimal', 'lemniscate'], + 'centiar': ['centiar', 'certain', 'citrean', 'nacrite', 'nectria'], + 'centiare': ['aneretic', 'centiare', 'creatine', 'increate', 'iterance'], + 'centibar': ['bacterin', 'centibar'], + 'centimeter': ['centimeter', 'recitement', 'remittence'], + 'centimo': ['centimo', 'entomic', 'tecomin'], + 'centimolar': ['centimolar', 'melicraton'], + 'centinormal': ['centinormal', 'conterminal', 'nonmetrical'], + 'cento': ['cento', 'conte', 'tecon'], + 'centrad': ['cantred', 'centrad', 'tranced'], + 'centrale': ['celarent', 'centrale', 'enclaret'], + 'centranth': ['centranth', 'trenchant'], + 'centraxonia': ['centraxonia', 'excarnation'], + 'centriole': ['centriole', 'electrion', 'relection'], + 'centrodorsal': ['centrodorsal', 'dorsocentral'], + 'centroid': ['centroid', 'doctrine'], + 'centrolineal': ['centrolineal', 'crenellation'], + 'centunculus': ['centunculus', 'unsucculent'], + 'centuria': ['anuretic', 'centauri', 'centuria', 'teucrian'], + 'centurial': ['centurial', 'lucretian', 'ultranice'], + 'centuried': ['centuried', 'unrecited'], + 'centurion': ['centurion', 'continuer', 'cornutine'], + 'cepa': ['cape', 'cepa', 'pace'], + 'cephalin': ['alphenic', 'cephalin'], + 'cephalina': ['cephalina', 'epilachna'], + 'cephaloid': ['cephaloid', 'pholcidae'], + 'cephalomeningitis': ['cephalomeningitis', 'meningocephalitis'], + 'cephalometric': ['cephalometric', 'petrochemical'], + 'cephalopodous': ['cephalopodous', 'podocephalous'], + 'cephas': ['cephas', 'pesach'], + 'cepolidae': ['adipocele', 'cepolidae', 'ploceidae'], + 'ceps': ['ceps', 'spec'], + 'ceptor': ['ceptor', 'copter'], + 'ceral': ['ceral', 'clare', 'clear', 'lacer'], + 'ceramal': ['cameral', 'caramel', 'carmela', 'ceramal', 'reclama'], + 'ceramic': ['ceramic', 'racemic'], + 'ceramist': ['camerist', 'ceramist', 'matrices'], + 'ceras': ['carse', 'caser', 'ceras', 'scare', 'scrae'], + 'cerasein': ['cerasein', 'increase'], + 'cerasin': ['arsenic', 'cerasin', 'sarcine'], + 'cerastes': ['cateress', 'cerastes'], + 'cerata': ['arcate', 'cerata'], + 'cerate': ['cerate', 'create', 'ecarte'], + 'cerated': ['cedrate', 'cerated'], + 'ceratiid': ['ceratiid', 'raticide'], + 'ceration': ['actioner', 'anerotic', 'ceration', 'creation', 'reaction'], + 'ceratium': ['ceratium', 'muricate'], + 'ceratonia': ['canariote', 'ceratonia'], + 'ceratosa': ['ceratosa', 'ostracea'], + 'ceratothecal': ['ceratothecal', 'chloracetate'], + 'cerberic': ['cerberic', 'cerebric'], + 'cercal': ['carcel', 'cercal'], + 'cerci': ['cerci', 'ceric', 'cicer', 'circe'], + 'cercus': ['cercus', 'cruces'], + 'cerdonian': ['cerdonian', 'ordinance'], + 'cere': ['cere', 'cree'], + 'cereal': ['alerce', 'cereal', 'relace'], + 'cerealin': ['cerealin', 'cinereal', 'reliance'], + 'cerebra': ['cerebra', 'rebrace'], + 'cerebric': ['cerberic', 'cerebric'], + 'cerebroma': ['cerebroma', 'embraceor'], + 'cerebromeningitis': ['cerebromeningitis', 'meningocerebritis'], + 'cerebrum': ['cerebrum', 'cumberer'], + 'cered': ['ceder', 'cedre', 'cered', 'creed'], + 'cerement': ['cementer', 'cerement', 'recement'], + 'ceremonial': ['ceremonial', 'neomiracle'], + 'ceresin': ['ceresin', 'sincere'], + 'cereus': ['cereus', 'ceruse', 'recuse', 'rescue', 'secure'], + 'cerevis': ['cerevis', 'scrieve', 'service'], + 'ceria': ['acier', 'aeric', 'ceria', 'erica'], + 'ceric': ['cerci', 'ceric', 'cicer', 'circe'], + 'ceride': ['ceride', 'deicer'], + 'cerillo': ['cerillo', 'colleri', 'collier'], + 'ceriman': ['armenic', 'carmine', 'ceriman', 'crimean', 'mercian'], + 'cerin': ['cerin', 'crine'], + 'cerion': ['cerion', 'coiner', 'neroic', 'orcein', 'recoin'], + 'ceriops': ['ceriops', 'persico'], + 'cerite': ['cerite', 'certie', 'recite', 'tierce'], + 'cerium': ['cerium', 'uremic'], + 'cernuous': ['cernuous', 'coenurus'], + 'cero': ['cero', 'core'], + 'ceroma': ['ceroma', 'corema'], + 'ceroplast': ['ceroplast', 'precostal'], + 'ceroplastic': ['ceroplastic', 'cleistocarp', 'coreplastic'], + 'ceroplasty': ['ceroplasty', 'coreplasty'], + 'cerotic': ['cerotic', 'orectic'], + 'cerotin': ['cerotin', 'cointer', 'cotrine', 'cretion', 'noticer', 'rection'], + 'cerous': ['cerous', 'course', 'crouse', 'source'], + 'certain': ['centiar', 'certain', 'citrean', 'nacrite', 'nectria'], + 'certhia': ['certhia', 'rhaetic', 'theriac'], + 'certie': ['cerite', 'certie', 'recite', 'tierce'], + 'certifiable': ['certifiable', 'rectifiable'], + 'certification': ['certification', 'cretification', 'rectification'], + 'certificative': ['certificative', 'rectificative'], + 'certificator': ['certificator', 'rectificator'], + 'certificatory': ['certificatory', 'rectificatory'], + 'certified': ['certified', 'rectified'], + 'certifier': ['certifier', 'rectifier'], + 'certify': ['certify', 'cretify', 'rectify'], + 'certis': ['certis', 'steric'], + 'certitude': ['certitude', 'rectitude'], + 'certosina': ['atroscine', 'certosina', 'ostracine', 'tinoceras', 'tricosane'], + 'certosino': ['certosino', 'cortisone', 'socotrine'], + 'cerulean': ['cerulean', 'laurence'], + 'ceruminal': ['ceruminal', 'melanuric', 'numerical'], + 'ceruse': ['cereus', 'ceruse', 'recuse', 'rescue', 'secure'], + 'cervicobuccal': ['buccocervical', 'cervicobuccal'], + 'cervicodorsal': ['cervicodorsal', 'dorsocervical'], + 'cervicodynia': ['cervicodynia', 'corycavidine'], + 'cervicofacial': ['cervicofacial', 'faciocervical'], + 'cervicolabial': ['cervicolabial', 'labiocervical'], + 'cervicovesical': ['cervicovesical', 'vesicocervical'], + 'cervoid': ['cervoid', 'divorce'], + 'cervuline': ['cervuline', 'virulence'], + 'ceryl': ['ceryl', 'clyer'], + 'cerynean': ['ancyrene', 'cerynean'], + 'cesare': ['cesare', 'crease', 'recase', 'searce'], + 'cesarolite': ['cesarolite', 'esoterical'], + 'cesium': ['cesium', 'miscue'], + 'cesser': ['cesser', 'recess'], + 'cession': ['cession', 'oscines'], + 'cessor': ['cessor', 'crosse', 'scorse'], + 'cest': ['cest', 'sect'], + 'cestodaria': ['castoridae', 'cestodaria'], + 'cestrian': ['canister', 'cestrian', 'cisterna', 'irascent'], + 'cetane': ['cetane', 'tenace'], + 'cetene': ['cetene', 'ectene'], + 'ceti': ['ceti', 'cite', 'tice'], + 'cetid': ['cetid', 'edict'], + 'cetomorphic': ['cetomorphic', 'chemotropic', 'ectomorphic'], + 'cetonia': ['acetoin', 'aconite', 'anoetic', 'antoeci', 'cetonia'], + 'cetonian': ['cetonian', 'enaction'], + 'cetorhinus': ['cetorhinus', 'urosthenic'], + 'cetus': ['cetus', 'scute'], + 'cevenol': ['cevenol', 'clovene'], + 'cevine': ['cevine', 'evince', 'venice'], + 'cha': ['ach', 'cha'], + 'chab': ['bach', 'chab'], + 'chabouk': ['chabouk', 'chakobu'], + 'chaco': ['chaco', 'choca', 'coach'], + 'chacte': ['cachet', 'chacte'], + 'chaenolobus': ['chaenolobus', 'unchoosable'], + 'chaeta': ['achate', 'chaeta'], + 'chaetites': ['aesthetic', 'chaetites'], + 'chaetognath': ['chaetognath', 'gnathotheca'], + 'chaetopod': ['chaetopod', 'podotheca'], + 'chafer': ['chafer', 'frache'], + 'chagan': ['chagan', 'changa'], + 'chagrin': ['arching', 'chagrin'], + 'chai': ['chai', 'chia'], + 'chain': ['chain', 'chian', 'china'], + 'chained': ['chained', 'echidna'], + 'chainer': ['chainer', 'enchair', 'rechain'], + 'chainlet': ['chainlet', 'ethnical'], + 'chainman': ['chainman', 'chinaman'], + 'chair': ['chair', 'chria'], + 'chairer': ['chairer', 'charier'], + 'chait': ['aitch', 'chait', 'chati', 'chita', 'taich', 'tchai'], + 'chakar': ['chakar', 'chakra', 'charka'], + 'chakari': ['chakari', 'chikara', 'kachari'], + 'chakobu': ['chabouk', 'chakobu'], + 'chakra': ['chakar', 'chakra', 'charka'], + 'chalcon': ['chalcon', 'clochan', 'conchal'], + 'chalcosine': ['ascolichen', 'chalcosine'], + 'chaldron': ['chaldron', 'chlordan', 'chondral'], + 'chalet': ['achtel', 'chalet', 'thecal', 'thecla'], + 'chalker': ['chalker', 'hackler'], + 'chalky': ['chalky', 'hackly'], + 'challie': ['alichel', 'challie', 'helical'], + 'chalmer': ['chalmer', 'charmel'], + 'chalon': ['chalon', 'lochan'], + 'chalone': ['chalone', 'cholane'], + 'chalta': ['caltha', 'chalta'], + 'chamal': ['almach', 'chamal'], + 'chamar': ['chamar', 'machar'], + 'chamber': ['becharm', 'brecham', 'chamber'], + 'chamberer': ['chamberer', 'rechamber'], + 'chamian': ['chamian', 'mahican'], + 'chamisal': ['chamisal', 'chiasmal'], + 'chamiso': ['chamiso', 'chamois'], + 'chamite': ['chamite', 'hematic'], + 'chamois': ['chamiso', 'chamois'], + 'champa': ['champa', 'mapach'], + 'champain': ['champain', 'chinampa'], + 'chancer': ['chancer', 'chancre'], + 'chanchito': ['chanchito', 'nachitoch'], + 'chanco': ['chanco', 'concha'], + 'chancre': ['chancer', 'chancre'], + 'chandu': ['chandu', 'daunch'], + 'chane': ['achen', 'chane', 'chena', 'hance'], + 'chang': ['chang', 'ganch'], + 'changa': ['chagan', 'changa'], + 'changer': ['changer', 'genarch'], + 'chanidae': ['chanidae', 'hacienda'], + 'channeler': ['channeler', 'encharnel'], + 'chanst': ['chanst', 'snatch', 'stanch'], + 'chant': ['chant', 'natch'], + 'chanter': ['chanter', 'rechant'], + 'chantey': ['atechny', 'chantey'], + 'chantry': ['cathryn', 'chantry'], + 'chaos': ['chaos', 'oshac'], + 'chaotical': ['acatholic', 'chaotical'], + 'chap': ['caph', 'chap'], + 'chaparro': ['chaparro', 'parachor'], + 'chape': ['chape', 'cheap', 'peach'], + 'chaped': ['chaped', 'phecda'], + 'chapel': ['chapel', 'lepcha', 'pleach'], + 'chapelet': ['chapelet', 'peachlet'], + 'chapelmaster': ['chapelmaster', 'spermathecal'], + 'chaperno': ['canephor', 'chaperno', 'chaperon'], + 'chaperon': ['canephor', 'chaperno', 'chaperon'], + 'chaperone': ['canephore', 'chaperone'], + 'chaperonless': ['chaperonless', 'proseneschal'], + 'chapin': ['apinch', 'chapin', 'phanic'], + 'chapiter': ['chapiter', 'phreatic'], + 'chaps': ['chaps', 'pasch'], + 'chapt': ['chapt', 'pacht', 'patch'], + 'chapter': ['chapter', 'patcher', 'repatch'], + 'char': ['arch', 'char', 'rach'], + 'chara': ['achar', 'chara'], + 'charac': ['charac', 'charca'], + 'characin': ['anarchic', 'characin'], + 'characinoid': ['arachidonic', 'characinoid'], + 'charadrii': ['charadrii', 'richardia'], + 'charas': ['achras', 'charas'], + 'charbon': ['brochan', 'charbon'], + 'charca': ['charac', 'charca'], + 'chare': ['acher', 'arche', 'chare', 'chera', 'rache', 'reach'], + 'charer': ['archer', 'charer', 'rechar'], + 'charette': ['catheter', 'charette'], + 'charge': ['charge', 'creagh'], + 'charier': ['chairer', 'charier'], + 'chariot': ['chariot', 'haricot'], + 'charioted': ['charioted', 'trochidae'], + 'chariotman': ['achromatin', 'chariotman', 'machinator'], + 'charism': ['charism', 'chrisma'], + 'charisma': ['archaism', 'charisma'], + 'chark': ['chark', 'karch'], + 'charka': ['chakar', 'chakra', 'charka'], + 'charlatanistic': ['antarchistical', 'charlatanistic'], + 'charleen': ['charleen', 'charlene'], + 'charlene': ['charleen', 'charlene'], + 'charles': ['charles', 'clasher'], + 'charm': ['charm', 'march'], + 'charmel': ['chalmer', 'charmel'], + 'charmer': ['charmer', 'marcher', 'remarch'], + 'charnel': ['charnel', 'larchen'], + 'charon': ['anchor', 'archon', 'charon', 'rancho'], + 'charpoy': ['charpoy', 'corypha'], + 'chart': ['chart', 'ratch'], + 'charter': ['charter', 'ratcher'], + 'charterer': ['charterer', 'recharter'], + 'charting': ['charting', 'ratching'], + 'chartism': ['carsmith', 'chartism'], + 'charuk': ['charuk', 'chukar'], + 'chary': ['archy', 'chary'], + 'chasable': ['cashable', 'chasable'], + 'chaser': ['arches', 'chaser', 'eschar', 'recash', 'search'], + 'chasma': ['ascham', 'chasma'], + 'chaste': ['chaste', 'sachet', 'scathe', 'scheat'], + 'chasten': ['chasten', 'sanetch'], + 'chastener': ['chastener', 'rechasten'], + 'chastity': ['chastity', 'yachtist'], + 'chasuble': ['chasuble', 'subchela'], + 'chat': ['chat', 'tach'], + 'chatelainry': ['chatelainry', 'trachylinae'], + 'chati': ['aitch', 'chait', 'chati', 'chita', 'taich', 'tchai'], + 'chatino': ['cathion', 'chatino'], + 'chatsome': ['chatsome', 'moschate'], + 'chatta': ['attach', 'chatta'], + 'chattation': ['chattation', 'thanatotic'], + 'chattel': ['chattel', 'latchet'], + 'chatter': ['chatter', 'ratchet'], + 'chattery': ['chattery', 'ratchety', 'trachyte'], + 'chatti': ['chatti', 'hattic'], + 'chatty': ['chatty', 'tatchy'], + 'chatwood': ['chatwood', 'woodchat'], + 'chaute': ['chaute', 'chueta'], + 'chawan': ['chawan', 'chwana', 'wachna'], + 'chawer': ['chawer', 'rechaw'], + 'chawk': ['chawk', 'whack'], + 'chay': ['achy', 'chay'], + 'cheap': ['chape', 'cheap', 'peach'], + 'cheapen': ['cheapen', 'peachen'], + 'cheapery': ['cheapery', 'peachery'], + 'cheapside': ['cheapside', 'sphecidae'], + 'cheat': ['cheat', 'tache', 'teach', 'theca'], + 'cheatable': ['cheatable', 'teachable'], + 'cheatableness': ['cheatableness', 'teachableness'], + 'cheater': ['cheater', 'hectare', 'recheat', 'reteach', 'teacher'], + 'cheatery': ['cheatery', 'cytherea', 'teachery'], + 'cheating': ['cheating', 'teaching'], + 'cheatingly': ['cheatingly', 'teachingly'], + 'cheatrie': ['cheatrie', 'hetaeric'], + 'checker': ['checker', 'recheck'], + 'chee': ['chee', 'eche'], + 'cheek': ['cheek', 'cheke', 'keech'], + 'cheerer': ['cheerer', 'recheer'], + 'cheerly': ['cheerly', 'lechery'], + 'cheery': ['cheery', 'reechy'], + 'cheet': ['cheet', 'hecte'], + 'cheir': ['cheir', 'rheic'], + 'cheiropodist': ['cheiropodist', 'coeditorship'], + 'cheka': ['cheka', 'keach'], + 'cheke': ['cheek', 'cheke', 'keech'], + 'chela': ['chela', 'lache', 'leach'], + 'chelide': ['chelide', 'heliced'], + 'chelidon': ['chelidon', 'chelonid', 'delichon'], + 'chelidonate': ['chelidonate', 'endothecial'], + 'chelodina': ['chelodina', 'hedonical'], + 'chelone': ['chelone', 'echelon'], + 'chelonid': ['chelidon', 'chelonid', 'delichon'], + 'cheloniid': ['cheloniid', 'lichenoid'], + 'chemiatrist': ['chemiatrist', 'chrismatite', 'theatricism'], + 'chemical': ['alchemic', 'chemical'], + 'chemicomechanical': ['chemicomechanical', 'mechanicochemical'], + 'chemicophysical': ['chemicophysical', 'physicochemical'], + 'chemicovital': ['chemicovital', 'vitochemical'], + 'chemiloon': ['chemiloon', 'homocline'], + 'chemotaxy': ['chemotaxy', 'myxotheca'], + 'chemotropic': ['cetomorphic', 'chemotropic', 'ectomorphic'], + 'chena': ['achen', 'chane', 'chena', 'hance'], + 'chenica': ['chenica', 'chicane'], + 'chenille': ['chenille', 'hellenic'], + 'chenopod': ['chenopod', 'ponchoed'], + 'chera': ['acher', 'arche', 'chare', 'chera', 'rache', 'reach'], + 'chermes': ['chermes', 'schemer'], + 'chert': ['chert', 'retch'], + 'cherte': ['cherte', 'etcher'], + 'chervil': ['chervil', 'chilver'], + 'cheson': ['cheson', 'chosen', 'schone'], + 'chest': ['chest', 'stech'], + 'chestily': ['chestily', 'lecythis'], + 'chesty': ['chesty', 'scythe'], + 'chet': ['chet', 'etch', 'tche', 'tech'], + 'chettik': ['chettik', 'thicket'], + 'chetty': ['chetty', 'tetchy'], + 'chewer': ['chewer', 'rechew'], + 'chewink': ['chewink', 'whicken'], + 'chi': ['chi', 'hic', 'ich'], + 'chia': ['chai', 'chia'], + 'chiam': ['chiam', 'machi', 'micah'], + 'chian': ['chain', 'chian', 'china'], + 'chiasmal': ['chamisal', 'chiasmal'], + 'chiastolite': ['chiastolite', 'heliostatic'], + 'chicane': ['chenica', 'chicane'], + 'chicle': ['chicle', 'cliche'], + 'chid': ['chid', 'dich'], + 'chider': ['chider', 'herdic'], + 'chidra': ['chidra', 'diarch'], + 'chief': ['chief', 'fiche'], + 'chield': ['chield', 'childe'], + 'chien': ['chien', 'chine', 'niche'], + 'chikara': ['chakari', 'chikara', 'kachari'], + 'chil': ['chil', 'lich'], + 'childe': ['chield', 'childe'], + 'chilean': ['chilean', 'echinal', 'nichael'], + 'chili': ['chili', 'lichi'], + 'chiliasm': ['chiliasm', 'hilasmic', 'machilis'], + 'chilla': ['achill', 'cahill', 'chilla'], + 'chiloma': ['chiloma', 'malicho'], + 'chilopod': ['chilopod', 'pholcoid'], + 'chilopoda': ['chilopoda', 'haplodoci'], + 'chilostome': ['chilostome', 'schooltime'], + 'chilver': ['chervil', 'chilver'], + 'chimane': ['chimane', 'machine'], + 'chime': ['chime', 'hemic', 'miche'], + 'chimer': ['chimer', 'mechir', 'micher'], + 'chimera': ['chimera', 'hermaic'], + 'chimney': ['chimney', 'hymenic'], + 'chimu': ['chimu', 'humic'], + 'chin': ['chin', 'inch'], + 'china': ['chain', 'chian', 'china'], + 'chinaman': ['chainman', 'chinaman'], + 'chinampa': ['champain', 'chinampa'], + 'chinanta': ['acanthin', 'chinanta'], + 'chinar': ['chinar', 'inarch'], + 'chine': ['chien', 'chine', 'niche'], + 'chined': ['chined', 'inched'], + 'chink': ['chink', 'kinch'], + 'chinkle': ['chinkle', 'kelchin'], + 'chinks': ['chinks', 'skinch'], + 'chinoa': ['chinoa', 'noahic'], + 'chinotti': ['chinotti', 'tithonic'], + 'chint': ['chint', 'nitch'], + 'chiolite': ['chiolite', 'eolithic'], + 'chionididae': ['chionididae', 'onchidiidae'], + 'chiral': ['archil', 'chiral'], + 'chirapsia': ['chirapsia', 'pharisaic'], + 'chirata': ['cathari', 'chirata', 'cithara'], + 'chiro': ['chiro', 'choir', 'ichor'], + 'chiromancist': ['chiromancist', 'monarchistic'], + 'chiromant': ['chiromant', 'chromatin'], + 'chiromantic': ['chiromantic', 'chromatinic'], + 'chiromantis': ['anchoritism', 'chiromantis', 'chrismation', 'harmonistic'], + 'chirometer': ['chirometer', 'rheometric'], + 'chiroplasty': ['chiroplasty', 'polyarchist'], + 'chiropter': ['chiropter', 'peritroch'], + 'chirosophist': ['chirosophist', 'opisthorchis'], + 'chirotes': ['chirotes', 'theorics'], + 'chirotype': ['chirotype', 'hypocrite'], + 'chirp': ['chirp', 'prich'], + 'chirper': ['chirper', 'prerich'], + 'chiseler': ['chiseler', 'rechisel'], + 'chit': ['chit', 'itch', 'tchi'], + 'chita': ['aitch', 'chait', 'chati', 'chita', 'taich', 'tchai'], + 'chital': ['chital', 'claith'], + 'chitinoid': ['chitinoid', 'dithionic'], + 'chitosan': ['atchison', 'chitosan'], + 'chitose': ['chitose', 'echoist'], + 'chloe': ['chloe', 'choel'], + 'chloracetate': ['ceratothecal', 'chloracetate'], + 'chloranthy': ['chloranthy', 'rhynchotal'], + 'chlorate': ['chlorate', 'trochlea'], + 'chlordan': ['chaldron', 'chlordan', 'chondral'], + 'chlore': ['chlore', 'choler', 'orchel'], + 'chloremia': ['chloremia', 'homerical'], + 'chlorinate': ['chlorinate', 'ectorhinal', 'tornachile'], + 'chlorite': ['chlorite', 'clothier'], + 'chloritic': ['chloritic', 'trochilic'], + 'chloroamine': ['chloroamine', 'melanochroi'], + 'chloroanaemia': ['aeolharmonica', 'chloroanaemia'], + 'chloroanemia': ['chloroanemia', 'choleromania'], + 'chloroiodide': ['chloroiodide', 'iodochloride'], + 'chloroplatinic': ['chloroplatinic', 'platinochloric'], + 'cho': ['cho', 'och'], + 'choana': ['aonach', 'choana'], + 'choca': ['chaco', 'choca', 'coach'], + 'choco': ['choco', 'hocco'], + 'choel': ['chloe', 'choel'], + 'choenix': ['choenix', 'hexonic'], + 'choes': ['choes', 'chose'], + 'choiak': ['choiak', 'kochia'], + 'choice': ['choice', 'echoic'], + 'choil': ['choil', 'choli', 'olchi'], + 'choir': ['chiro', 'choir', 'ichor'], + 'choirman': ['choirman', 'harmonic', 'omniarch'], + 'choker': ['choker', 'hocker'], + 'choky': ['choky', 'hocky'], + 'chol': ['chol', 'loch'], + 'chola': ['chola', 'loach', 'olcha'], + 'cholane': ['chalone', 'cholane'], + 'cholangioitis': ['angiocholitis', 'cholangioitis'], + 'cholanic': ['cholanic', 'colchian'], + 'cholate': ['cathole', 'cholate'], + 'cholecystoduodenostomy': ['cholecystoduodenostomy', 'duodenocholecystostomy'], + 'choler': ['chlore', 'choler', 'orchel'], + 'cholera': ['cholera', 'choreal'], + 'cholerine': ['cholerine', 'rhinocele'], + 'choleromania': ['chloroanemia', 'choleromania'], + 'cholesteremia': ['cholesteremia', 'heteroecismal'], + 'choli': ['choil', 'choli', 'olchi'], + 'choline': ['choline', 'helicon'], + 'cholo': ['cholo', 'cohol'], + 'chondral': ['chaldron', 'chlordan', 'chondral'], + 'chondrite': ['chondrite', 'threnodic'], + 'chondroadenoma': ['adenochondroma', 'chondroadenoma'], + 'chondroangioma': ['angiochondroma', 'chondroangioma'], + 'chondroarthritis': ['arthrochondritis', 'chondroarthritis'], + 'chondrocostal': ['chondrocostal', 'costochondral'], + 'chondrofibroma': ['chondrofibroma', 'fibrochondroma'], + 'chondrolipoma': ['chondrolipoma', 'lipochondroma'], + 'chondromyxoma': ['chondromyxoma', 'myxochondroma'], + 'chondromyxosarcoma': ['chondromyxosarcoma', 'myxochondrosarcoma'], + 'choop': ['choop', 'pooch'], + 'chopa': ['chopa', 'phoca', 'poach'], + 'chopin': ['chopin', 'phonic'], + 'chopine': ['chopine', 'phocine'], + 'chora': ['achor', 'chora', 'corah', 'orach', 'roach'], + 'choral': ['choral', 'lorcha'], + 'chorasmian': ['anachorism', 'chorasmian', 'maraschino'], + 'chordal': ['chordal', 'dorlach'], + 'chorditis': ['chorditis', 'orchidist'], + 'chordotonal': ['chordotonal', 'notochordal'], + 'chore': ['chore', 'ocher'], + 'chorea': ['chorea', 'ochrea', 'rochea'], + 'choreal': ['cholera', 'choreal'], + 'choree': ['choree', 'cohere', 'echoer'], + 'choreoid': ['choreoid', 'ochidore'], + 'choreus': ['choreus', 'chouser', 'rhoecus'], + 'choric': ['choric', 'orchic'], + 'choriocele': ['choriocele', 'orchiocele'], + 'chorioidoretinitis': ['chorioidoretinitis', 'retinochorioiditis'], + 'chorism': ['chorism', 'chrisom'], + 'chorist': ['chorist', 'ostrich'], + 'choristate': ['choristate', 'rheostatic'], + 'chorization': ['chorization', 'rhizoctonia', 'zonotrichia'], + 'choroid': ['choroid', 'ochroid'], + 'chort': ['chort', 'rotch', 'torch'], + 'chorten': ['chorten', 'notcher'], + 'chorti': ['chorti', 'orthic', 'thoric', 'trochi'], + 'chose': ['choes', 'chose'], + 'chosen': ['cheson', 'chosen', 'schone'], + 'chou': ['chou', 'ouch'], + 'chough': ['chough', 'hughoc'], + 'choup': ['choup', 'pouch'], + 'chous': ['chous', 'hocus'], + 'chouser': ['choreus', 'chouser', 'rhoecus'], + 'chowder': ['chowder', 'cowherd'], + 'chria': ['chair', 'chria'], + 'chrism': ['chrism', 'smirch'], + 'chrisma': ['charism', 'chrisma'], + 'chrismation': ['anchoritism', 'chiromantis', 'chrismation', 'harmonistic'], + 'chrismatite': ['chemiatrist', 'chrismatite', 'theatricism'], + 'chrisom': ['chorism', 'chrisom'], + 'christ': ['christ', 'strich'], + 'christen': ['christen', 'snitcher'], + 'christener': ['christener', 'rechristen'], + 'christian': ['christian', 'christina'], + 'christiana': ['arachnitis', 'christiana'], + 'christina': ['christian', 'christina'], + 'christophe': ['christophe', 'hectorship'], + 'chromatician': ['achromatinic', 'chromatician'], + 'chromatid': ['chromatid', 'dichromat'], + 'chromatin': ['chiromant', 'chromatin'], + 'chromatinic': ['chiromantic', 'chromatinic'], + 'chromatocyte': ['chromatocyte', 'thoracectomy'], + 'chromatoid': ['chromatoid', 'tichodroma'], + 'chromatone': ['chromatone', 'enomotarch'], + 'chromid': ['chromid', 'richdom'], + 'chromidae': ['archidome', 'chromidae'], + 'chromite': ['chromite', 'trichome'], + 'chromocyte': ['chromocyte', 'cytochrome'], + 'chromolithography': ['chromolithography', 'lithochromography'], + 'chromophotography': ['chromophotography', 'photochromography'], + 'chromophotolithograph': ['chromophotolithograph', 'photochromolithograph'], + 'chromopsia': ['chromopsia', 'isocamphor'], + 'chromotype': ['chromotype', 'cormophyte', 'ectomorphy'], + 'chromotypic': ['chromotypic', 'cormophytic', 'mycotrophic'], + 'chronophotograph': ['chronophotograph', 'photochronograph'], + 'chronophotographic': ['chronophotographic', 'photochronographic'], + 'chronophotography': ['chronophotography', 'photochronography'], + 'chrysography': ['chrysography', 'psychorrhagy'], + 'chrysolite': ['chrysolite', 'chrysotile'], + 'chrysopid': ['chrysopid', 'dysphoric'], + 'chrysotile': ['chrysolite', 'chrysotile'], + 'chucker': ['chucker', 'rechuck'], + 'chueta': ['chaute', 'chueta'], + 'chukar': ['charuk', 'chukar'], + 'chulan': ['chulan', 'launch', 'nuchal'], + 'chum': ['chum', 'much'], + 'chumpish': ['chumpish', 'chumship'], + 'chumship': ['chumpish', 'chumship'], + 'chunari': ['chunari', 'unchair'], + 'chunnia': ['chunnia', 'unchain'], + 'chuprassie': ['chuprassie', 'haruspices'], + 'churl': ['churl', 'lurch'], + 'churn': ['churn', 'runch'], + 'chut': ['chut', 'tchu', 'utch'], + 'chwana': ['chawan', 'chwana', 'wachna'], + 'chyak': ['chyak', 'hacky'], + 'chylous': ['chylous', 'slouchy'], + 'cibarial': ['biracial', 'cibarial'], + 'cibarian': ['arabinic', 'cabirian', 'carabini', 'cibarian'], + 'cibolan': ['cibolan', 'coalbin'], + 'cicala': ['alcaic', 'cicala'], + 'cicatrize': ['arcticize', 'cicatrize'], + 'cicely': ['cecily', 'cicely'], + 'cicer': ['cerci', 'ceric', 'cicer', 'circe'], + 'cicerone': ['cicerone', 'croceine'], + 'cicindela': ['cicindela', 'cinclidae', 'icelandic'], + 'ciclatoun': ['ciclatoun', 'noctiluca'], + 'ciconian': ['aniconic', 'ciconian'], + 'ciconine': ['ciconine', 'conicine'], + 'cidaridae': ['acrididae', 'cardiidae', 'cidaridae'], + 'cidaris': ['cidaris', 'sciarid'], + 'cider': ['cider', 'cried', 'deric', 'dicer'], + 'cigala': ['caliga', 'cigala'], + 'cigar': ['cigar', 'craig'], + 'cilia': ['cilia', 'iliac'], + 'ciliation': ['ciliation', 'coinitial'], + 'cilice': ['cilice', 'icicle'], + 'cimbia': ['cimbia', 'iambic'], + 'cimicidae': ['amicicide', 'cimicidae'], + 'cinchonine': ['cinchonine', 'conchinine'], + 'cinclidae': ['cicindela', 'cinclidae', 'icelandic'], + 'cinder': ['cedrin', 'cinder', 'crined'], + 'cinderous': ['cinderous', 'decursion'], + 'cindie': ['cindie', 'incide'], + 'cine': ['cine', 'nice'], + 'cinel': ['cinel', 'cline'], + 'cinema': ['anemic', 'cinema', 'iceman'], + 'cinematographer': ['cinematographer', 'megachiropteran'], + 'cinene': ['cinene', 'nicene'], + 'cineole': ['cineole', 'coeline'], + 'cinerama': ['amacrine', 'american', 'camerina', 'cinerama'], + 'cineration': ['cineration', 'inceration'], + 'cinerea': ['cairene', 'cinerea'], + 'cinereal': ['cerealin', 'cinereal', 'reliance'], + 'cingulum': ['cingulum', 'glucinum'], + 'cinnamate': ['antanemic', 'cinnamate'], + 'cinnamol': ['cinnamol', 'nonclaim'], + 'cinnamon': ['cinnamon', 'mannonic'], + 'cinnamoned': ['cinnamoned', 'demicannon'], + 'cinque': ['cinque', 'quince'], + 'cinter': ['cinter', 'cretin', 'crinet'], + 'cinura': ['anuric', 'cinura', 'uranic'], + 'cion': ['cion', 'coin', 'icon'], + 'cipher': ['cipher', 'rechip'], + 'cipo': ['cipo', 'pico'], + 'circe': ['cerci', 'ceric', 'cicer', 'circe'], + 'circle': ['circle', 'cleric'], + 'cirrate': ['cartier', 'cirrate', 'erratic'], + 'cirrated': ['cirrated', 'craterid'], + 'cirrhotic': ['cirrhotic', 'trichroic'], + 'cirrose': ['cirrose', 'crosier'], + 'cirsectomy': ['cirsectomy', 'citromyces'], + 'cirsoid': ['cirsoid', 'soricid'], + 'ciruela': ['auricle', 'ciruela'], + 'cise': ['cise', 'sice'], + 'cisplatine': ['cisplatine', 'plasticine'], + 'cispontine': ['cispontine', 'inspection'], + 'cissoidal': ['cissoidal', 'dissocial'], + 'cistern': ['cistern', 'increst'], + 'cisterna': ['canister', 'cestrian', 'cisterna', 'irascent'], + 'cisternal': ['cisternal', 'larcenist'], + 'cistvaen': ['cistvaen', 'vesicant'], + 'cit': ['cit', 'tic'], + 'citadel': ['citadel', 'deltaic', 'dialect', 'edictal', 'lactide'], + 'citatory': ['atrocity', 'citatory'], + 'cite': ['ceti', 'cite', 'tice'], + 'citer': ['citer', 'recti', 'ticer', 'trice'], + 'cithara': ['cathari', 'chirata', 'cithara'], + 'citharist': ['citharist', 'trachitis'], + 'citharoedic': ['citharoedic', 'diachoretic'], + 'cither': ['cither', 'thrice'], + 'citied': ['citied', 'dietic'], + 'citizen': ['citizen', 'zincite'], + 'citral': ['citral', 'rictal'], + 'citramide': ['citramide', 'diametric', 'matricide'], + 'citrange': ['argentic', 'citrange'], + 'citrate': ['atretic', 'citrate'], + 'citrated': ['citrated', 'tetracid', 'tetradic'], + 'citrean': ['centiar', 'certain', 'citrean', 'nacrite', 'nectria'], + 'citrene': ['citrene', 'enteric', 'enticer', 'tercine'], + 'citreous': ['citreous', 'urticose'], + 'citric': ['citric', 'critic'], + 'citrin': ['citrin', 'nitric'], + 'citrination': ['citrination', 'intrication'], + 'citrine': ['citrine', 'crinite', 'inciter', 'neritic'], + 'citromyces': ['cirsectomy', 'citromyces'], + 'citron': ['citron', 'cortin', 'crotin'], + 'citronade': ['citronade', 'endaortic', 'redaction'], + 'citronella': ['citronella', 'interlocal'], + 'citrus': ['citrus', 'curtis', 'rictus', 'rustic'], + 'cive': ['cive', 'vice'], + 'civet': ['civet', 'evict'], + 'civetone': ['civetone', 'evection'], + 'civitan': ['activin', 'civitan'], + 'cixo': ['cixo', 'coix'], + 'clabber': ['cabbler', 'clabber'], + 'clacker': ['cackler', 'clacker', 'crackle'], + 'cladine': ['cladine', 'decalin', 'iceland'], + 'cladonia': ['cladonia', 'condalia', 'diaconal'], + 'cladophyll': ['cladophyll', 'phylloclad'], + 'claim': ['claim', 'clima', 'malic'], + 'claimant': ['calamint', 'claimant'], + 'claimer': ['claimer', 'miracle', 'reclaim'], + 'clairce': ['clairce', 'clarice'], + 'claire': ['carlie', 'claire', 'eclair', 'erical'], + 'claith': ['chital', 'claith'], + 'claiver': ['caliver', 'caviler', 'claiver', 'clavier', 'valeric', 'velaric'], + 'clam': ['calm', 'clam'], + 'clamant': ['calmant', 'clamant'], + 'clamative': ['calmative', 'clamative'], + 'clamatores': ['clamatores', 'scleromata'], + 'clamber': ['cambrel', 'clamber', 'cramble'], + 'clame': ['camel', 'clame', 'cleam', 'macle'], + 'clamer': ['calmer', 'carmel', 'clamer', 'marcel', 'mercal'], + 'clamor': ['clamor', 'colmar'], + 'clamorist': ['clamorist', 'crotalism'], + 'clangingly': ['clangingly', 'glancingly'], + 'clap': ['calp', 'clap'], + 'clapper': ['clapper', 'crapple'], + 'claquer': ['claquer', 'lacquer'], + 'clarain': ['carinal', 'carlina', 'clarain', 'cranial'], + 'clare': ['ceral', 'clare', 'clear', 'lacer'], + 'clarence': ['canceler', 'clarence', 'recancel'], + 'claret': ['carlet', 'cartel', 'claret', 'rectal', 'talcer'], + 'claretian': ['carnalite', 'claretian', 'lacertian', 'nectarial'], + 'clarice': ['clairce', 'clarice'], + 'clarin': ['carlin', 'clarin', 'crinal'], + 'clarinda': ['cardinal', 'clarinda'], + 'clarion': ['carolin', 'clarion', 'colarin', 'locrian'], + 'clarionet': ['alectrion', 'clarionet', 'crotaline', 'locarnite'], + 'clarist': ['carlist', 'clarist'], + 'claro': ['alcor', 'calor', 'carlo', 'carol', 'claro', 'coral'], + 'clary': ['acryl', 'caryl', 'clary'], + 'clasher': ['charles', 'clasher'], + 'clasp': ['clasp', 'scalp'], + 'clasper': ['clasper', 'reclasp', 'scalper'], + 'clasping': ['clasping', 'scalping'], + 'classed': ['classed', 'declass'], + 'classer': ['carless', 'classer', 'reclass'], + 'classism': ['classism', 'misclass'], + 'classwork': ['classwork', 'crosswalk'], + 'clat': ['clat', 'talc'], + 'clathrina': ['alchitran', 'clathrina'], + 'clathrose': ['clathrose', 'searcloth'], + 'clatterer': ['clatterer', 'craterlet'], + 'claude': ['caudle', 'cedula', 'claude'], + 'claudian': ['claudian', 'dulciana'], + 'claudicate': ['aciculated', 'claudicate'], + 'clause': ['caelus', 'caules', 'clause'], + 'claustral': ['claustral', 'lacustral'], + 'clava': ['caval', 'clava'], + 'clavacin': ['clavacin', 'vaccinal'], + 'clavaria': ['calvaria', 'clavaria'], + 'clave': ['calve', 'cavel', 'clave'], + 'claver': ['calver', 'carvel', 'claver'], + 'claviculate': ['calculative', 'claviculate'], + 'clavier': ['caliver', 'caviler', 'claiver', 'clavier', 'valeric', 'velaric'], + 'clavis': ['clavis', 'slavic'], + 'clay': ['acyl', 'clay', 'lacy'], + 'clayer': ['clayer', 'lacery'], + 'claytonia': ['acylation', 'claytonia'], + 'clead': ['clead', 'decal', 'laced'], + 'cleam': ['camel', 'clame', 'cleam', 'macle'], + 'cleamer': ['carmele', 'cleamer'], + 'clean': ['canel', 'clean', 'lance', 'lenca'], + 'cleaner': ['cleaner', 'reclean'], + 'cleanly': ['cleanly', 'lancely'], + 'cleanout': ['cleanout', 'outlance'], + 'cleanse': ['cleanse', 'scalene'], + 'cleanup': ['cleanup', 'unplace'], + 'clear': ['ceral', 'clare', 'clear', 'lacer'], + 'clearable': ['clearable', 'lacerable'], + 'clearer': ['clearer', 'reclear'], + 'cleat': ['cleat', 'eclat', 'ectal', 'lacet', 'tecla'], + 'clefted': ['clefted', 'deflect'], + 'cleistocarp': ['ceroplastic', 'cleistocarp', 'coreplastic'], + 'cleistogeny': ['cleistogeny', 'lysogenetic'], + 'cleoid': ['cleoid', 'coiled', 'docile'], + 'cleopatra': ['acropetal', 'cleopatra'], + 'cleric': ['circle', 'cleric'], + 'clericature': ['clericature', 'recirculate'], + 'clerkess': ['clerkess', 'reckless'], + 'clerking': ['clerking', 'reckling'], + 'clerus': ['clerus', 'cruels'], + 'clethra': ['clethra', 'latcher', 'ratchel', 'relatch', 'talcher', 'trachle'], + 'cleveite': ['cleveite', 'elective'], + 'cliche': ['chicle', 'cliche'], + 'clicker': ['clicker', 'crickle'], + 'clidastes': ['clidastes', 'discastle'], + 'clientage': ['clientage', 'genetical'], + 'cliented': ['cliented', 'denticle'], + 'cliftonia': ['cliftonia', 'fictional'], + 'clima': ['claim', 'clima', 'malic'], + 'climber': ['climber', 'reclimb'], + 'clime': ['clime', 'melic'], + 'cline': ['cinel', 'cline'], + 'clinger': ['clinger', 'cringle'], + 'clinia': ['anilic', 'clinia'], + 'clinicopathological': ['clinicopathological', 'pathologicoclinical'], + 'clinium': ['clinium', 'ulminic'], + 'clinker': ['clinker', 'crinkle'], + 'clinoclase': ['clinoclase', 'oscillance'], + 'clinoclasite': ['callisection', 'clinoclasite'], + 'clinodome': ['clinodome', 'melodicon', 'monocleid'], + 'clinology': ['clinology', 'coolingly'], + 'clinometer': ['clinometer', 'recoilment'], + 'clinospore': ['clinospore', 'necropolis'], + 'clio': ['clio', 'coil', 'coli', 'loci'], + 'cliona': ['alnico', 'cliona', 'oilcan'], + 'clione': ['clione', 'coelin', 'encoil', 'enolic'], + 'clipeus': ['clipeus', 'spicule'], + 'clipper': ['clipper', 'cripple'], + 'clipse': ['clipse', 'splice'], + 'clipsome': ['clipsome', 'polemics'], + 'clite': ['clite', 'telic'], + 'clites': ['celtis', 'clites'], + 'clitia': ['clitia', 'italic'], + 'clition': ['clition', 'nilotic'], + 'clitoria': ['clitoria', 'loricati'], + 'clitoridean': ['clitoridean', 'directional'], + 'clitoris': ['clitoris', 'coistril'], + 'clive': ['clive', 'velic'], + 'cloacinal': ['cloacinal', 'cocillana'], + 'cloam': ['cloam', 'comal'], + 'cloamen': ['aclemon', 'cloamen'], + 'clobber': ['clobber', 'cobbler'], + 'clochan': ['chalcon', 'clochan', 'conchal'], + 'clocked': ['clocked', 'cockled'], + 'clocker': ['clocker', 'cockler'], + 'clod': ['clod', 'cold'], + 'clodder': ['clodder', 'coddler'], + 'cloggy': ['cloggy', 'coggly'], + 'cloister': ['cloister', 'coistrel'], + 'cloisteral': ['cloisteral', 'sclerotial'], + 'cloit': ['cloit', 'lotic'], + 'clonicotonic': ['clonicotonic', 'tonicoclonic'], + 'clonus': ['clonus', 'consul'], + 'clop': ['clop', 'colp'], + 'close': ['close', 'socle'], + 'closer': ['closer', 'cresol', 'escrol'], + 'closter': ['closter', 'costrel'], + 'closterium': ['closterium', 'sclerotium'], + 'clot': ['clot', 'colt'], + 'clothier': ['chlorite', 'clothier'], + 'clotho': ['clotho', 'coolth'], + 'clotter': ['clotter', 'crottle'], + 'cloture': ['cloture', 'clouter'], + 'cloud': ['cloud', 'could'], + 'clouter': ['cloture', 'clouter'], + 'clovene': ['cevenol', 'clovene'], + 'clow': ['clow', 'cowl'], + 'cloy': ['cloy', 'coly'], + 'clue': ['clue', 'luce'], + 'clumse': ['clumse', 'muscle'], + 'clumsily': ['clumsily', 'scyllium'], + 'clumsy': ['clumsy', 'muscly'], + 'clunist': ['clunist', 'linctus'], + 'clupea': ['alecup', 'clupea'], + 'clupeine': ['clupeine', 'pulicene'], + 'clusia': ['caulis', 'clusia', 'sicula'], + 'clutch': ['clutch', 'cultch'], + 'clutter': ['clutter', 'cuttler'], + 'clyde': ['clyde', 'decyl'], + 'clyer': ['ceryl', 'clyer'], + 'clymenia': ['clymenia', 'mycelian'], + 'clypeolate': ['clypeolate', 'ptyalocele'], + 'clysis': ['clysis', 'lyssic'], + 'clysmic': ['clysmic', 'cyclism'], + 'cnemial': ['cnemial', 'melanic'], + 'cnemis': ['cnemis', 'mnesic'], + 'cneorum': ['cneorum', 'corneum'], + 'cnicus': ['cnicus', 'succin'], + 'cnida': ['canid', 'cnida', 'danic'], + 'cnidaria': ['acridian', 'cnidaria'], + 'cnidian': ['cnidian', 'indican'], + 'cnidophore': ['cnidophore', 'princehood'], + 'coach': ['chaco', 'choca', 'coach'], + 'coacher': ['caroche', 'coacher', 'recoach'], + 'coachlet': ['catechol', 'coachlet'], + 'coactor': ['coactor', 'tarocco'], + 'coadamite': ['acetamido', 'coadamite'], + 'coadnate': ['anecdota', 'coadnate'], + 'coadunite': ['coadunite', 'education', 'noctuidae'], + 'coagent': ['coagent', 'cognate'], + 'coagulate': ['catalogue', 'coagulate'], + 'coaita': ['atocia', 'coaita'], + 'coal': ['alco', 'coal', 'cola', 'loca'], + 'coalbin': ['cibolan', 'coalbin'], + 'coaler': ['carole', 'coaler', 'coelar', 'oracle', 'recoal'], + 'coalite': ['aloetic', 'coalite'], + 'coalition': ['coalition', 'lociation'], + 'coalitionist': ['coalitionist', 'solicitation'], + 'coalizer': ['calorize', 'coalizer'], + 'coalpit': ['capitol', 'coalpit', 'optical', 'topical'], + 'coaltitude': ['coaltitude', 'colatitude'], + 'coaming': ['coaming', 'macigno'], + 'coan': ['coan', 'onca'], + 'coapt': ['capot', 'coapt'], + 'coarb': ['carbo', 'carob', 'coarb', 'cobra'], + 'coarrange': ['arrogance', 'coarrange'], + 'coarse': ['acrose', 'coarse'], + 'coarsen': ['carnose', 'coarsen', 'narcose'], + 'coassert': ['castores', 'coassert'], + 'coast': ['ascot', 'coast', 'costa', 'tacso', 'tasco'], + 'coastal': ['coastal', 'salacot'], + 'coaster': ['coaster', 'recoast'], + 'coasting': ['agnostic', 'coasting'], + 'coated': ['coated', 'decoat'], + 'coater': ['coater', 'recoat'], + 'coating': ['coating', 'cotinga'], + 'coatroom': ['coatroom', 'morocota'], + 'coax': ['coax', 'coxa'], + 'cobbler': ['clobber', 'cobbler'], + 'cobia': ['baioc', 'cabio', 'cobia'], + 'cobiron': ['boronic', 'cobiron'], + 'cobitis': ['biotics', 'cobitis'], + 'cobra': ['carbo', 'carob', 'coarb', 'cobra'], + 'cocaine': ['cocaine', 'oceanic'], + 'cocainist': ['cocainist', 'siccation'], + 'cocama': ['cocama', 'macaco'], + 'cocamine': ['cocamine', 'comacine'], + 'cochleare': ['archocele', 'cochleare'], + 'cochleitis': ['cochleitis', 'ochlesitic'], + 'cocillana': ['cloacinal', 'cocillana'], + 'cocker': ['cocker', 'recock'], + 'cockily': ['cockily', 'colicky'], + 'cockled': ['clocked', 'cockled'], + 'cockler': ['clocker', 'cockler'], + 'cockup': ['cockup', 'upcock'], + 'cocreditor': ['cocreditor', 'codirector'], + 'cocurrent': ['cocurrent', 'occurrent', 'uncorrect'], + 'cod': ['cod', 'doc'], + 'codamine': ['codamine', 'comedian', 'daemonic', 'demoniac'], + 'codder': ['codder', 'corded'], + 'coddler': ['clodder', 'coddler'], + 'code': ['code', 'coed'], + 'codebtor': ['bedoctor', 'codebtor'], + 'coder': ['coder', 'cored', 'credo'], + 'coderive': ['coderive', 'divorcee'], + 'codicil': ['codicil', 'dicolic'], + 'codille': ['celloid', 'codille', 'collide', 'collied'], + 'codirector': ['cocreditor', 'codirector'], + 'codium': ['codium', 'mucoid'], + 'coed': ['code', 'coed'], + 'coeditorship': ['cheiropodist', 'coeditorship'], + 'coelar': ['carole', 'coaler', 'coelar', 'oracle', 'recoal'], + 'coelata': ['alcoate', 'coelata'], + 'coelection': ['coelection', 'entocoelic'], + 'coelia': ['aeolic', 'coelia'], + 'coelin': ['clione', 'coelin', 'encoil', 'enolic'], + 'coeline': ['cineole', 'coeline'], + 'coelogyne': ['coelogyne', 'gonyocele'], + 'coenactor': ['coenactor', 'croconate'], + 'coenobiar': ['borocaine', 'coenobiar'], + 'coenurus': ['cernuous', 'coenurus'], + 'coestate': ['coestate', 'ecostate'], + 'coeternal': ['antrocele', 'coeternal', 'tolerance'], + 'coeval': ['alcove', 'coeval', 'volcae'], + 'cofaster': ['cofaster', 'forecast'], + 'coferment': ['coferment', 'forcement'], + 'cogeneric': ['cogeneric', 'concierge'], + 'coggly': ['cloggy', 'coggly'], + 'cognate': ['coagent', 'cognate'], + 'cognatical': ['cognatical', 'galactonic'], + 'cognation': ['cognation', 'contagion'], + 'cognition': ['cognition', 'incognito'], + 'cognominal': ['cognominal', 'gnomonical'], + 'cogon': ['cogon', 'congo'], + 'cograil': ['argolic', 'cograil'], + 'coheir': ['coheir', 'heroic'], + 'cohen': ['cohen', 'enoch'], + 'cohere': ['choree', 'cohere', 'echoer'], + 'cohol': ['cholo', 'cohol'], + 'cohune': ['cohune', 'hounce'], + 'coif': ['coif', 'fico', 'foci'], + 'coign': ['coign', 'incog'], + 'coil': ['clio', 'coil', 'coli', 'loci'], + 'coiled': ['cleoid', 'coiled', 'docile'], + 'coiler': ['coiler', 'recoil'], + 'coin': ['cion', 'coin', 'icon'], + 'coinclude': ['coinclude', 'undecolic'], + 'coiner': ['cerion', 'coiner', 'neroic', 'orcein', 'recoin'], + 'coinfer': ['coinfer', 'conifer'], + 'coinherence': ['coinherence', 'incoherence'], + 'coinherent': ['coinherent', 'incoherent'], + 'coinitial': ['ciliation', 'coinitial'], + 'coinmate': ['coinmate', 'maconite'], + 'coinspire': ['coinspire', 'precision'], + 'coinsure': ['coinsure', 'corineus', 'cusinero'], + 'cointer': ['cerotin', 'cointer', 'cotrine', 'cretion', 'noticer', 'rection'], + 'cointreau': ['cautioner', 'cointreau'], + 'coistrel': ['cloister', 'coistrel'], + 'coistril': ['clitoris', 'coistril'], + 'coix': ['cixo', 'coix'], + 'coker': ['coker', 'corke', 'korec'], + 'coky': ['coky', 'yock'], + 'cola': ['alco', 'coal', 'cola', 'loca'], + 'colalgia': ['alogical', 'colalgia'], + 'colan': ['colan', 'conal'], + 'colane': ['canelo', 'colane'], + 'colarin': ['carolin', 'clarion', 'colarin', 'locrian'], + 'colate': ['acetol', 'colate', 'locate'], + 'colation': ['colation', 'coontail', 'location'], + 'colatitude': ['coaltitude', 'colatitude'], + 'colchian': ['cholanic', 'colchian'], + 'colcine': ['colcine', 'concile', 'conicle'], + 'colcothar': ['colcothar', 'ochlocrat'], + 'cold': ['clod', 'cold'], + 'colder': ['cedrol', 'colder', 'cordel'], + 'colectomy': ['colectomy', 'cyclotome'], + 'colemanite': ['colemanite', 'melaconite'], + 'coleur': ['coleur', 'colure'], + 'coleus': ['coleus', 'oscule'], + 'coli': ['clio', 'coil', 'coli', 'loci'], + 'colias': ['colias', 'scolia', 'social'], + 'colicky': ['cockily', 'colicky'], + 'colima': ['colima', 'olamic'], + 'colin': ['colin', 'nicol'], + 'colinear': ['acrolein', + 'arecolin', + 'caroline', + 'colinear', + 'cornelia', + 'creolian', + 'lonicera'], + 'colitis': ['colitis', 'solicit'], + 'colk': ['colk', 'lock'], + 'colla': ['callo', 'colla', 'local'], + 'collage': ['alcogel', 'collage'], + 'collare': ['collare', 'corella', 'ocellar'], + 'collaret': ['collaret', 'corallet'], + 'collarino': ['collarino', 'coronilla'], + 'collatee': ['collatee', 'ocellate'], + 'collationer': ['collationer', 'recollation'], + 'collectioner': ['collectioner', 'recollection'], + 'collegial': ['collegial', 'gallicole'], + 'collegian': ['allogenic', 'collegian'], + 'colleri': ['cerillo', 'colleri', 'collier'], + 'colleter': ['colleter', 'coteller', 'coterell', 'recollet'], + 'colletia': ['colletia', 'teocalli'], + 'collide': ['celloid', 'codille', 'collide', 'collied'], + 'collidine': ['celloidin', 'collidine', 'decillion'], + 'collie': ['collie', 'ocelli'], + 'collied': ['celloid', 'codille', 'collide', 'collied'], + 'collier': ['cerillo', 'colleri', 'collier'], + 'colligate': ['colligate', 'cotillage'], + 'colline': ['colline', 'lioncel'], + 'collinear': ['collinear', 'coralline'], + 'collinsia': ['collinsia', 'isoclinal'], + 'collotypy': ['collotypy', 'polycotyl'], + 'collusive': ['collusive', 'colluvies'], + 'colluvies': ['collusive', 'colluvies'], + 'collyba': ['callboy', 'collyba'], + 'colmar': ['clamor', 'colmar'], + 'colobus': ['colobus', 'subcool'], + 'coloenteritis': ['coloenteritis', 'enterocolitis'], + 'colombian': ['colombian', 'colombina'], + 'colombina': ['colombian', 'colombina'], + 'colonalgia': ['colonalgia', 'naological'], + 'colonate': ['colonate', 'ecotonal'], + 'colonialist': ['colonialist', 'oscillation'], + 'coloproctitis': ['coloproctitis', 'proctocolitis'], + 'color': ['color', 'corol', 'crool'], + 'colored': ['colored', 'croodle', 'decolor'], + 'colorer': ['colorer', 'recolor'], + 'colorin': ['colorin', 'orcinol'], + 'colorman': ['colorman', 'conormal'], + 'colp': ['clop', 'colp'], + 'colpeurynter': ['colpeurynter', 'counterreply'], + 'colpitis': ['colpitis', 'politics', 'psilotic'], + 'colporrhagia': ['colporrhagia', 'orographical'], + 'colt': ['clot', 'colt'], + 'colter': ['colter', 'lector', 'torcel'], + 'coltskin': ['coltskin', 'linstock'], + 'colubrina': ['binocular', 'caliburno', 'colubrina'], + 'columbo': ['columbo', 'coulomb'], + 'columbotitanate': ['columbotitanate', 'titanocolumbate'], + 'columnated': ['columnated', 'documental'], + 'columned': ['columned', 'uncledom'], + 'colunar': ['colunar', 'cornual', 'courlan'], + 'colure': ['coleur', 'colure'], + 'colutea': ['caulote', 'colutea', 'oculate'], + 'coly': ['cloy', 'coly'], + 'coma': ['coma', 'maco'], + 'comacine': ['cocamine', 'comacine'], + 'comal': ['cloam', 'comal'], + 'coman': ['coman', 'macon', 'manoc'], + 'comart': ['carmot', 'comart'], + 'comate': ['comate', 'metoac', 'tecoma'], + 'combat': ['combat', 'tombac'], + 'comber': ['comber', 'recomb'], + 'combinedly': ['combinedly', 'molybdenic'], + 'comedial': ['cameloid', 'comedial', 'melodica'], + 'comedian': ['codamine', 'comedian', 'daemonic', 'demoniac'], + 'comediant': ['comediant', 'metaconid'], + 'comedist': ['comedist', 'demotics', 'docetism', 'domestic'], + 'comedown': ['comedown', 'downcome'], + 'comeliness': ['comeliness', 'incomeless'], + 'comeling': ['comeling', 'comingle'], + 'comenic': ['comenic', 'encomic', 'meconic'], + 'comer': ['comer', 'crome'], + 'comforter': ['comforter', 'recomfort'], + 'comid': ['comid', 'domic'], + 'coming': ['coming', 'gnomic'], + 'comingle': ['comeling', 'comingle'], + 'comintern': ['comintern', 'nonmetric'], + 'comitia': ['caimito', 'comitia'], + 'comitragedy': ['comitragedy', 'tragicomedy'], + 'comity': ['comity', 'myotic'], + 'commander': ['commander', 'recommand'], + 'commation': ['commation', 'monatomic'], + 'commelina': ['commelina', 'melomanic'], + 'commender': ['commender', 'recommend'], + 'commentarial': ['commentarial', 'manometrical'], + 'commination': ['commination', 'monamniotic'], + 'commissioner': ['commissioner', 'recommission'], + 'commonality': ['ammonolytic', 'commonality'], + 'commorient': ['commorient', 'metronomic', 'monometric'], + 'compact': ['accompt', 'compact'], + 'compacter': ['compacter', 'recompact'], + 'company': ['company', 'copyman'], + 'compare': ['compare', 'compear'], + 'comparition': ['comparition', 'proamniotic'], + 'compasser': ['compasser', 'recompass'], + 'compear': ['compare', 'compear'], + 'compenetrate': ['compenetrate', 'contemperate'], + 'competitioner': ['competitioner', 'recompetition'], + 'compile': ['compile', 'polemic'], + 'compiler': ['compiler', 'complier'], + 'complainer': ['complainer', 'procnemial', 'recomplain'], + 'complaint': ['complaint', 'compliant'], + 'complanate': ['complanate', 'placentoma'], + 'compliant': ['complaint', 'compliant'], + 'complier': ['compiler', 'complier'], + 'compounder': ['compounder', 'recompound'], + 'comprehender': ['comprehender', 'recomprehend'], + 'compressed': ['compressed', 'decompress'], + 'comprise': ['comprise', 'perosmic'], + 'compromission': ['compromission', 'procommission'], + 'conal': ['colan', 'conal'], + 'conamed': ['conamed', 'macedon'], + 'conant': ['cannot', 'canton', 'conant', 'nonact'], + 'conarial': ['carolina', 'conarial'], + 'conarium': ['conarium', 'coumarin'], + 'conative': ['conative', 'invocate'], + 'concealer': ['concealer', 'reconceal'], + 'concent': ['concent', 'connect'], + 'concenter': ['concenter', 'reconnect'], + 'concentive': ['concentive', 'connective'], + 'concertize': ['concertize', 'concretize'], + 'concessioner': ['concessioner', 'reconcession'], + 'concha': ['chanco', 'concha'], + 'conchal': ['chalcon', 'clochan', 'conchal'], + 'conchinine': ['cinchonine', 'conchinine'], + 'concierge': ['cogeneric', 'concierge'], + 'concile': ['colcine', 'concile', 'conicle'], + 'concocter': ['concocter', 'reconcoct'], + 'concreter': ['concreter', 'reconcert'], + 'concretize': ['concertize', 'concretize'], + 'concretor': ['concretor', 'conrector'], + 'condalia': ['cladonia', 'condalia', 'diaconal'], + 'condemner': ['condemner', 'recondemn'], + 'condite': ['condite', 'ctenoid'], + 'conditioner': ['conditioner', 'recondition'], + 'condor': ['condor', 'cordon'], + 'conduit': ['conduit', 'duction', 'noctuid'], + 'condylomatous': ['condylomatous', 'monodactylous'], + 'cone': ['cone', 'once'], + 'conepate': ['conepate', 'tepecano'], + 'coner': ['coner', 'crone', 'recon'], + 'cones': ['cones', 'scone'], + 'confesser': ['confesser', 'reconfess'], + 'configurationism': ['configurationism', 'misconfiguration'], + 'confirmer': ['confirmer', 'reconfirm'], + 'confirmor': ['confirmor', 'corniform'], + 'conflate': ['conflate', 'falconet'], + 'conformer': ['conformer', 'reconform'], + 'confounder': ['confounder', 'reconfound'], + 'confrere': ['confrere', 'enforcer', 'reconfer'], + 'confronter': ['confronter', 'reconfront'], + 'congealer': ['congealer', 'recongeal'], + 'congeneric': ['congeneric', 'necrogenic'], + 'congenerous': ['congenerous', 'necrogenous'], + 'congenial': ['congenial', 'goclenian'], + 'congo': ['cogon', 'congo'], + 'congreet': ['congreet', 'coregent'], + 'congreve': ['congreve', 'converge'], + 'conical': ['conical', 'laconic'], + 'conicine': ['ciconine', 'conicine'], + 'conicle': ['colcine', 'concile', 'conicle'], + 'conicoid': ['conicoid', 'conoidic'], + 'conidium': ['conidium', 'mucinoid', 'oncidium'], + 'conifer': ['coinfer', 'conifer'], + 'conima': ['camion', 'conima', 'manioc', 'monica'], + 'conin': ['conin', 'nonic', 'oncin'], + 'conine': ['conine', 'connie', 'ennoic'], + 'conjoiner': ['conjoiner', 'reconjoin'], + 'conk': ['conk', 'nock'], + 'conker': ['conker', 'reckon'], + 'conkers': ['conkers', 'snocker'], + 'connarite': ['connarite', 'container', 'cotarnine', 'crenation', 'narcotine'], + 'connatal': ['cantonal', 'connatal'], + 'connation': ['connation', 'nonaction'], + 'connature': ['antecornu', 'connature'], + 'connect': ['concent', 'connect'], + 'connectival': ['connectival', 'conventical'], + 'connective': ['concentive', 'connective'], + 'connie': ['conine', 'connie', 'ennoic'], + 'connoissance': ['connoissance', 'nonaccession'], + 'conoidal': ['conoidal', 'dolciano'], + 'conoidic': ['conicoid', 'conoidic'], + 'conor': ['conor', 'croon', 'ronco'], + 'conormal': ['colorman', 'conormal'], + 'conoy': ['conoy', 'coony'], + 'conrad': ['candor', 'cardon', 'conrad'], + 'conrector': ['concretor', 'conrector'], + 'conred': ['cedron', 'conred'], + 'conringia': ['conringia', 'inorganic'], + 'consenter': ['consenter', 'nonsecret', 'reconsent'], + 'conservable': ['conservable', 'conversable'], + 'conservancy': ['conservancy', 'conversancy'], + 'conservant': ['conservant', 'conversant'], + 'conservation': ['conservation', 'conversation'], + 'conservational': ['conservational', 'conversational'], + 'conservationist': ['conservationist', 'conversationist'], + 'conservative': ['conservative', 'conversative'], + 'conserve': ['conserve', 'converse'], + 'conserver': ['conserver', 'converser'], + 'considerate': ['considerate', 'desecration'], + 'considerative': ['considerative', 'devisceration'], + 'considered': ['considered', 'deconsider'], + 'considerer': ['considerer', 'reconsider'], + 'consigner': ['consigner', 'reconsign'], + 'conspiracy': ['conspiracy', 'snipocracy'], + 'conspire': ['conspire', 'incorpse'], + 'constate': ['catstone', 'constate'], + 'constitutionalism': ['constitutionalism', 'misconstitutional'], + 'constitutioner': ['constitutioner', 'reconstitution'], + 'constrain': ['constrain', 'transonic'], + 'constructer': ['constructer', 'reconstruct'], + 'constructionism': ['constructionism', 'misconstruction'], + 'consul': ['clonus', 'consul'], + 'consulage': ['consulage', 'glucosane'], + 'consulary': ['consulary', 'cynosural'], + 'consulter': ['consulter', 'reconsult'], + 'consume': ['consume', 'muscone'], + 'consumer': ['consumer', 'mucrones'], + 'consute': ['consute', 'contuse'], + 'contagion': ['cognation', 'contagion'], + 'contain': ['actinon', 'cantion', 'contain'], + 'container': ['connarite', 'container', 'cotarnine', 'crenation', 'narcotine'], + 'conte': ['cento', 'conte', 'tecon'], + 'contemperate': ['compenetrate', 'contemperate'], + 'contender': ['contender', 'recontend'], + 'conter': ['conter', 'cornet', 'cronet', 'roncet'], + 'conterminal': ['centinormal', 'conterminal', 'nonmetrical'], + 'contester': ['contester', 'recontest'], + 'continual': ['continual', 'inoculant', 'unctional'], + 'continued': ['continued', 'unnoticed'], + 'continuer': ['centurion', 'continuer', 'cornutine'], + 'contise': ['contise', 'noetics', 'section'], + 'contline': ['contline', 'nonlicet'], + 'contortae': ['contortae', 'crotonate'], + 'contour': ['contour', 'cornuto', 'countor', 'crouton'], + 'contra': ['cantor', 'carton', 'contra'], + 'contracter': ['contracter', 'correctant', 'recontract'], + 'contrapose': ['antroscope', 'contrapose'], + 'contravene': ['contravene', 'covenanter'], + 'contrite': ['contrite', 'tetronic'], + 'contrive': ['contrive', 'invector'], + 'conturbation': ['conturbation', 'obtruncation'], + 'contuse': ['consute', 'contuse'], + 'conure': ['conure', 'rounce', 'uncore'], + 'conventical': ['connectival', 'conventical'], + 'conventioner': ['conventioner', 'reconvention'], + 'converge': ['congreve', 'converge'], + 'conversable': ['conservable', 'conversable'], + 'conversancy': ['conservancy', 'conversancy'], + 'conversant': ['conservant', 'conversant'], + 'conversation': ['conservation', 'conversation'], + 'conversational': ['conservational', 'conversational'], + 'conversationist': ['conservationist', 'conversationist'], + 'conversative': ['conservative', 'conversative'], + 'converse': ['conserve', 'converse'], + 'converser': ['conserver', 'converser'], + 'converter': ['converter', 'reconvert'], + 'convertise': ['convertise', 'ventricose'], + 'conveyer': ['conveyer', 'reconvey'], + 'conycatcher': ['conycatcher', 'technocracy'], + 'conyrine': ['conyrine', 'corynine'], + 'cooker': ['cooker', 'recook'], + 'cool': ['cool', 'loco'], + 'coolant': ['coolant', 'octonal'], + 'cooler': ['cooler', 'recool'], + 'coolingly': ['clinology', 'coolingly'], + 'coolth': ['clotho', 'coolth'], + 'coolweed': ['coolweed', 'locoweed'], + 'cooly': ['cooly', 'coyol'], + 'coonroot': ['coonroot', 'octoroon'], + 'coontail': ['colation', 'coontail', 'location'], + 'coony': ['conoy', 'coony'], + 'coop': ['coop', 'poco'], + 'coos': ['coos', 'soco'], + 'coost': ['coost', 'scoot'], + 'coot': ['coot', 'coto', 'toco'], + 'copa': ['copa', 'paco'], + 'copable': ['copable', 'placebo'], + 'copalite': ['copalite', 'poetical'], + 'coparent': ['coparent', 'portance'], + 'copart': ['captor', 'copart'], + 'copartner': ['copartner', 'procreant'], + 'copatain': ['copatain', 'pacation'], + 'copehan': ['copehan', 'panoche', 'phocean'], + 'copen': ['copen', 'ponce'], + 'coperta': ['coperta', 'pectora', 'porcate'], + 'copied': ['copied', 'epodic'], + 'copis': ['copis', 'pisco'], + 'copist': ['copist', 'coptis', 'optics', 'postic'], + 'copita': ['atopic', 'capito', 'copita'], + 'coplanar': ['coplanar', 'procanal'], + 'copleased': ['copleased', 'escaloped'], + 'copperer': ['copperer', 'recopper'], + 'coppery': ['coppery', 'precopy'], + 'copr': ['copr', 'corp', 'crop'], + 'coprinae': ['caponier', 'coprinae', 'procaine'], + 'coprinus': ['coprinus', 'poncirus'], + 'coprolagnia': ['carpogonial', 'coprolagnia'], + 'coprophagist': ['coprophagist', 'topographics'], + 'coprose': ['coprose', 'scooper'], + 'copse': ['copse', 'pecos', 'scope'], + 'copter': ['ceptor', 'copter'], + 'coptis': ['copist', 'coptis', 'optics', 'postic'], + 'copula': ['copula', 'cupola'], + 'copular': ['copular', 'croupal', 'cupolar', 'porcula'], + 'copulate': ['copulate', 'outplace'], + 'copulation': ['copulation', 'poculation'], + 'copus': ['copus', 'scoup'], + 'copyman': ['company', 'copyman'], + 'copyrighter': ['copyrighter', 'recopyright'], + 'coque': ['coque', 'ocque'], + 'coquitlam': ['coquitlam', 'quamoclit'], + 'cor': ['cor', 'cro', 'orc', 'roc'], + 'cora': ['acor', 'caro', 'cora', 'orca'], + 'coraciae': ['coraciae', 'icacorea'], + 'coracial': ['caracoli', 'coracial'], + 'coracias': ['coracias', 'rascacio'], + 'coradicate': ['coradicate', 'ectocardia'], + 'corah': ['achor', 'chora', 'corah', 'orach', 'roach'], + 'coraise': ['coraise', 'scoriae'], + 'coral': ['alcor', 'calor', 'carlo', 'carol', 'claro', 'coral'], + 'coraled': ['acerdol', 'coraled'], + 'coralist': ['calorist', 'coralist'], + 'corallet': ['collaret', 'corallet'], + 'corallian': ['corallian', 'corallina'], + 'corallina': ['corallian', 'corallina'], + 'coralline': ['collinear', 'coralline'], + 'corallite': ['corallite', 'lectorial'], + 'coram': ['carom', 'coram', 'macro', 'marco'], + 'coranto': ['cartoon', 'coranto'], + 'corban': ['bracon', 'carbon', 'corban'], + 'corbeil': ['bricole', 'corbeil', 'orbicle'], + 'cordaitean': ['arctoidean', 'carotidean', 'cordaitean', 'dinocerata'], + 'cordate': ['cordate', 'decator', 'redcoat'], + 'corded': ['codder', 'corded'], + 'cordel': ['cedrol', 'colder', 'cordel'], + 'corder': ['corder', 'record'], + 'cordia': ['caroid', 'cordia'], + 'cordial': ['cordial', 'dorical'], + 'cordicole': ['cordicole', 'crocodile'], + 'cordierite': ['cordierite', 'directoire'], + 'cordoba': ['bocardo', 'cordoba'], + 'cordon': ['condor', 'cordon'], + 'core': ['cero', 'core'], + 'cored': ['coder', 'cored', 'credo'], + 'coregent': ['congreet', 'coregent'], + 'coreless': ['coreless', 'sclerose'], + 'corella': ['collare', 'corella', 'ocellar'], + 'corema': ['ceroma', 'corema'], + 'coreplastic': ['ceroplastic', 'cleistocarp', 'coreplastic'], + 'coreplasty': ['ceroplasty', 'coreplasty'], + 'corer': ['corer', 'crore'], + 'coresidual': ['coresidual', 'radiculose'], + 'coresign': ['coresign', 'cosigner'], + 'corge': ['corge', 'gorce'], + 'corgi': ['corgi', 'goric', 'orgic'], + 'corial': ['caroli', 'corial', 'lorica'], + 'coriamyrtin': ['coriamyrtin', 'criminatory'], + 'corin': ['corin', 'noric', 'orcin'], + 'corindon': ['corindon', 'nodicorn'], + 'corineus': ['coinsure', 'corineus', 'cusinero'], + 'corinna': ['corinna', 'cronian'], + 'corinne': ['corinne', 'cornein', 'neronic'], + 'cork': ['cork', 'rock'], + 'corke': ['coker', 'corke', 'korec'], + 'corked': ['corked', 'docker', 'redock'], + 'corker': ['corker', 'recork', 'rocker'], + 'corkiness': ['corkiness', 'rockiness'], + 'corking': ['corking', 'rocking'], + 'corkish': ['corkish', 'rockish'], + 'corkwood': ['corkwood', 'rockwood', 'woodrock'], + 'corky': ['corky', 'rocky'], + 'corm': ['corm', 'crom'], + 'cormophyte': ['chromotype', 'cormophyte', 'ectomorphy'], + 'cormophytic': ['chromotypic', 'cormophytic', 'mycotrophic'], + 'cornage': ['acrogen', 'cornage'], + 'cornea': ['carone', 'cornea'], + 'corneal': ['carneol', 'corneal'], + 'cornein': ['corinne', 'cornein', 'neronic'], + 'cornelia': ['acrolein', + 'arecolin', + 'caroline', + 'colinear', + 'cornelia', + 'creolian', + 'lonicera'], + 'cornelius': ['cornelius', 'inclosure', 'reclusion'], + 'corneocalcareous': ['calcareocorneous', 'corneocalcareous'], + 'cornet': ['conter', 'cornet', 'cronet', 'roncet'], + 'corneum': ['cneorum', 'corneum'], + 'cornic': ['cornic', 'crocin'], + 'cornice': ['cornice', 'crocein'], + 'corniform': ['confirmor', 'corniform'], + 'cornin': ['cornin', 'rincon'], + 'cornish': ['cornish', 'cronish', 'sorchin'], + 'cornual': ['colunar', 'cornual', 'courlan'], + 'cornuate': ['cornuate', 'courante', 'cuneator', 'outrance'], + 'cornuated': ['cornuated', 'undercoat'], + 'cornucopiate': ['cornucopiate', 'reoccupation'], + 'cornulites': ['cornulites', 'uncloister'], + 'cornute': ['cornute', 'counter', 'recount', 'trounce'], + 'cornutine': ['centurion', 'continuer', 'cornutine'], + 'cornuto': ['contour', 'cornuto', 'countor', 'crouton'], + 'corny': ['corny', 'crony'], + 'corol': ['color', 'corol', 'crool'], + 'corollated': ['corollated', 'decollator'], + 'corona': ['caroon', 'corona', 'racoon'], + 'coronad': ['cardoon', 'coronad'], + 'coronadite': ['carotenoid', 'coronadite', 'decoration'], + 'coronal': ['coronal', 'locarno'], + 'coronaled': ['canoodler', 'coronaled'], + 'coronate': ['coronate', 'octonare', 'otocrane'], + 'coronated': ['coronated', 'creodonta'], + 'coroner': ['coroner', 'crooner', 'recroon'], + 'coronilla': ['collarino', 'coronilla'], + 'corp': ['copr', 'corp', 'crop'], + 'corporealist': ['corporealist', 'prosectorial'], + 'corradiate': ['corradiate', 'cortaderia', 'eradicator'], + 'correal': ['caroler', 'correal'], + 'correctant': ['contracter', 'correctant', 'recontract'], + 'correctioner': ['correctioner', 'recorrection'], + 'corrente': ['corrente', 'terceron'], + 'correption': ['correption', 'porrection'], + 'corrodentia': ['corrodentia', 'recordation'], + 'corrupter': ['corrupter', 'recorrupt'], + 'corsage': ['corsage', 'socager'], + 'corsaint': ['cantoris', 'castorin', 'corsaint'], + 'corse': ['corse', 'score'], + 'corselet': ['corselet', 'sclerote', 'selector'], + 'corset': ['corset', 'cortes', 'coster', 'escort', 'scoter', 'sector'], + 'corta': ['actor', 'corta', 'croat', 'rocta', 'taroc', 'troca'], + 'cortaderia': ['corradiate', 'cortaderia', 'eradicator'], + 'cortes': ['corset', 'cortes', 'coster', 'escort', 'scoter', 'sector'], + 'cortical': ['cortical', 'crotalic'], + 'cortices': ['cortices', 'cresotic'], + 'corticose': ['corticose', 'creosotic'], + 'cortin': ['citron', 'cortin', 'crotin'], + 'cortina': ['anticor', 'carotin', 'cortina', 'ontaric'], + 'cortinate': ['carnotite', 'cortinate'], + 'cortisone': ['certosino', 'cortisone', 'socotrine'], + 'corton': ['corton', 'croton'], + 'corvinae': ['corvinae', 'veronica'], + 'cory': ['cory', 'croy'], + 'corycavidine': ['cervicodynia', 'corycavidine'], + 'corydon': ['corydon', 'croydon'], + 'corynine': ['conyrine', 'corynine'], + 'corypha': ['charpoy', 'corypha'], + 'coryphene': ['coryphene', 'hypercone'], + 'cos': ['cos', 'osc', 'soc'], + 'cosalite': ['cosalite', 'societal'], + 'coset': ['coset', 'estoc', 'scote'], + 'cosh': ['cosh', 'scho'], + 'cosharer': ['cosharer', 'horsecar'], + 'cosigner': ['coresign', 'cosigner'], + 'cosine': ['cosine', 'oscine'], + 'cosmati': ['atomics', 'catoism', 'cosmati', 'osmatic', 'somatic'], + 'cosmetical': ['cacomistle', 'cosmetical'], + 'cosmetician': ['cosmetician', 'encomiastic'], + 'cosmist': ['cosmist', 'scotism'], + 'cossack': ['cassock', 'cossack'], + 'cosse': ['cosse', 'secos'], + 'cost': ['cost', 'scot'], + 'costa': ['ascot', 'coast', 'costa', 'tacso', 'tasco'], + 'costar': ['arctos', 'castor', 'costar', 'scrota'], + 'costean': ['costean', 'tsoneca'], + 'coster': ['corset', 'cortes', 'coster', 'escort', 'scoter', 'sector'], + 'costing': ['costing', 'gnostic'], + 'costispinal': ['costispinal', 'pansciolist'], + 'costmary': ['arctomys', 'costmary', 'mascotry'], + 'costochondral': ['chondrocostal', 'costochondral'], + 'costosternal': ['costosternal', 'sternocostal'], + 'costovertebral': ['costovertebral', 'vertebrocostal'], + 'costrel': ['closter', 'costrel'], + 'costula': ['costula', 'locusta', 'talcous'], + 'costumer': ['costumer', 'customer'], + 'cosurety': ['cosurety', 'courtesy'], + 'cosustain': ['cosustain', 'scusation'], + 'cotarius': ['cotarius', 'octarius', 'suctoria'], + 'cotarnine': ['connarite', 'container', 'cotarnine', 'crenation', 'narcotine'], + 'cote': ['cote', 'teco'], + 'coteline': ['coteline', 'election'], + 'coteller': ['colleter', 'coteller', 'coterell', 'recollet'], + 'coterell': ['colleter', 'coteller', 'coterell', 'recollet'], + 'cotesian': ['canoeist', 'cotesian'], + 'coth': ['coth', 'ocht'], + 'cotidal': ['cotidal', 'lactoid', 'talcoid'], + 'cotillage': ['colligate', 'cotillage'], + 'cotillion': ['cotillion', 'octillion'], + 'cotinga': ['coating', 'cotinga'], + 'cotinus': ['cotinus', 'suction', 'unstoic'], + 'cotise': ['cotise', 'oecist'], + 'coto': ['coot', 'coto', 'toco'], + 'cotranspire': ['cotranspire', 'pornerastic'], + 'cotrine': ['cerotin', 'cointer', 'cotrine', 'cretion', 'noticer', 'rection'], + 'cotripper': ['cotripper', 'periproct'], + 'cotte': ['cotte', 'octet'], + 'cotylosaur': ['cotylosaur', 'osculatory'], + 'cotype': ['cotype', 'ectopy'], + 'coude': ['coude', 'douce'], + 'could': ['cloud', 'could'], + 'coulisse': ['coulisse', 'leucosis', 'ossicule'], + 'coulomb': ['columbo', 'coulomb'], + 'coumalic': ['caulomic', 'coumalic'], + 'coumarin': ['conarium', 'coumarin'], + 'counsel': ['counsel', 'unclose'], + 'counter': ['cornute', 'counter', 'recount', 'trounce'], + 'counteracter': ['counteracter', 'countercarte'], + 'countercarte': ['counteracter', 'countercarte'], + 'countercharm': ['countercharm', 'countermarch'], + 'counterguard': ['counterguard', 'uncorrugated'], + 'counteridea': ['counteridea', 'decurionate'], + 'countermarch': ['countercharm', 'countermarch'], + 'counterpaled': ['counterpaled', 'counterplead', 'unpercolated'], + 'counterpaly': ['counterpaly', 'counterplay'], + 'counterplay': ['counterpaly', 'counterplay'], + 'counterplead': ['counterpaled', 'counterplead', 'unpercolated'], + 'counterreply': ['colpeurynter', 'counterreply'], + 'countersale': ['countersale', 'counterseal'], + 'countersea': ['countersea', 'nectareous'], + 'counterseal': ['countersale', 'counterseal'], + 'countershade': ['countershade', 'decantherous'], + 'counterstand': ['counterstand', 'uncontrasted'], + 'countertail': ['countertail', 'reluctation'], + 'countertrades': ['countertrades', 'unstercorated'], + 'countervail': ['countervail', 'involucrate'], + 'countervair': ['countervair', 'overcurtain', 'recurvation'], + 'countor': ['contour', 'cornuto', 'countor', 'crouton'], + 'coupe': ['coupe', 'pouce'], + 'couper': ['couper', 'croupe', 'poucer', 'recoup'], + 'couplement': ['couplement', 'uncomplete'], + 'couplet': ['couplet', 'octuple'], + 'coupon': ['coupon', 'uncoop'], + 'couponed': ['couponed', 'uncooped'], + 'courante': ['cornuate', 'courante', 'cuneator', 'outrance'], + 'courbaril': ['courbaril', 'orbicular'], + 'courlan': ['colunar', 'cornual', 'courlan'], + 'cours': ['cours', 'scour'], + 'course': ['cerous', 'course', 'crouse', 'source'], + 'coursed': ['coursed', 'scoured'], + 'courser': ['courser', 'scourer'], + 'coursing': ['coursing', 'scouring'], + 'court': ['court', 'crout', 'turco'], + 'courtesan': ['acentrous', 'courtesan', 'nectarous'], + 'courtesy': ['cosurety', 'courtesy'], + 'courtier': ['courtier', 'outcrier'], + 'courtiership': ['courtiership', 'peritrichous'], + 'courtin': ['courtin', 'ruction'], + 'courtman': ['courtman', 'turcoman'], + 'couter': ['couter', 'croute'], + 'couth': ['couth', 'thuoc', 'touch'], + 'couthily': ['couthily', 'touchily'], + 'couthiness': ['couthiness', 'touchiness'], + 'couthless': ['couthless', 'touchless'], + 'coutil': ['coutil', 'toluic'], + 'covenanter': ['contravene', 'covenanter'], + 'coverer': ['coverer', 'recover'], + 'coversine': ['coversine', 'vernicose'], + 'covert': ['covert', 'vector'], + 'covisit': ['covisit', 'ovistic'], + 'cowardy': ['cowardy', 'cowyard'], + 'cowherd': ['chowder', 'cowherd'], + 'cowl': ['clow', 'cowl'], + 'cowyard': ['cowardy', 'cowyard'], + 'coxa': ['coax', 'coxa'], + 'coxite': ['coxite', 'exotic'], + 'coyness': ['coyness', 'sycones'], + 'coyol': ['cooly', 'coyol'], + 'coyote': ['coyote', 'oocyte'], + 'craber': ['bracer', 'craber'], + 'crabhole': ['bachelor', 'crabhole'], + 'crablet': ['beclart', 'crablet'], + 'crackable': ['blackacre', 'crackable'], + 'crackle': ['cackler', 'clacker', 'crackle'], + 'crackmans': ['crackmans', 'cracksman'], + 'cracksman': ['crackmans', 'cracksman'], + 'cradge': ['cadger', 'cradge'], + 'cradle': ['cardel', 'cradle'], + 'cradlemate': ['cradlemate', 'malcreated'], + 'craig': ['cigar', 'craig'], + 'crain': ['cairn', 'crain', 'naric'], + 'crake': ['acker', 'caker', 'crake', 'creak'], + 'cram': ['cram', 'marc'], + 'cramasie': ['cramasie', 'mesaraic'], + 'crambe': ['becram', 'camber', 'crambe'], + 'crambidae': ['carbamide', 'crambidae'], + 'crambinae': ['carbamine', 'crambinae'], + 'cramble': ['cambrel', 'clamber', 'cramble'], + 'cramper': ['cramper', 'recramp'], + 'crampon': ['crampon', 'cropman'], + 'cranage': ['carnage', 'cranage', 'garance'], + 'crance': ['cancer', 'crance'], + 'crane': ['caner', 'crane', 'crena', 'nacre', 'rance'], + 'craner': ['craner', 'rancer'], + 'craney': ['carney', 'craney'], + 'crania': ['acinar', + 'arnica', + 'canari', + 'carian', + 'carina', + 'crania', + 'narica'], + 'craniad': ['acridan', 'craniad'], + 'cranial': ['carinal', 'carlina', 'clarain', 'cranial'], + 'cranially': ['ancillary', 'carlylian', 'cranially'], + 'cranian': ['canarin', 'cranian'], + 'craniate': ['anaretic', 'arcanite', 'carinate', 'craniate'], + 'cranic': ['cancri', 'carnic', 'cranic'], + 'craniectomy': ['craniectomy', 'cyanometric'], + 'craniognomy': ['craniognomy', 'organonymic'], + 'craniota': ['craniota', 'croatian', 'narcotia', 'raincoat'], + 'cranker': ['cranker', 'recrank'], + 'crap': ['carp', 'crap'], + 'crape': ['caper', 'crape', 'pacer', 'perca', 'recap'], + 'crappie': ['crappie', 'epicarp'], + 'crapple': ['clapper', 'crapple'], + 'crappo': ['crappo', 'croppa'], + 'craps': ['craps', 'scarp', 'scrap'], + 'crapulous': ['crapulous', 'opuscular'], + 'crare': ['carer', 'crare', 'racer'], + 'crate': ['caret', + 'carte', + 'cater', + 'crate', + 'creat', + 'creta', + 'react', + 'recta', + 'trace'], + 'crateful': ['crateful', 'fulcrate'], + 'crater': ['arrect', 'carter', 'crater', 'recart', 'tracer'], + 'craterid': ['cirrated', 'craterid'], + 'crateriform': ['crateriform', 'terraciform'], + 'crateris': ['crateris', 'serratic'], + 'craterlet': ['clatterer', 'craterlet'], + 'craterous': ['craterous', 'recusator'], + 'cratinean': ['cratinean', 'incarnate', 'nectarian'], + 'cratometric': ['cratometric', 'metrocratic'], + 'crave': ['carve', 'crave', 'varec'], + 'craven': ['carven', 'cavern', 'craven'], + 'craver': ['carver', 'craver'], + 'craving': ['carving', 'craving'], + 'crayon': ['canroy', 'crayon', 'cyrano', 'nyroca'], + 'crayonist': ['carnosity', 'crayonist'], + 'crea': ['acer', 'acre', 'care', 'crea', 'race'], + 'creagh': ['charge', 'creagh'], + 'creak': ['acker', 'caker', 'crake', 'creak'], + 'cream': ['cream', 'macer'], + 'creamer': ['amercer', 'creamer'], + 'creant': ['canter', + 'creant', + 'cretan', + 'nectar', + 'recant', + 'tanrec', + 'trance'], + 'crease': ['cesare', 'crease', 'recase', 'searce'], + 'creaser': ['creaser', 'searcer'], + 'creasing': ['creasing', 'scirenga'], + 'creat': ['caret', + 'carte', + 'cater', + 'crate', + 'creat', + 'creta', + 'react', + 'recta', + 'trace'], + 'creatable': ['creatable', 'traceable'], + 'create': ['cerate', 'create', 'ecarte'], + 'creatine': ['aneretic', 'centiare', 'creatine', 'increate', 'iterance'], + 'creatinine': ['creatinine', 'incinerate'], + 'creation': ['actioner', 'anerotic', 'ceration', 'creation', 'reaction'], + 'creational': ['creational', 'crotalinae', 'laceration', 'reactional'], + 'creationary': ['creationary', 'reactionary'], + 'creationism': ['anisometric', + 'creationism', + 'miscreation', + 'ramisection', + 'reactionism'], + 'creationist': ['creationist', 'reactionist'], + 'creative': ['creative', 'reactive'], + 'creatively': ['creatively', 'reactively'], + 'creativeness': ['creativeness', 'reactiveness'], + 'creativity': ['creativity', 'reactivity'], + 'creator': ['creator', 'reactor'], + 'crebrous': ['crebrous', 'obscurer'], + 'credential': ['credential', 'interlaced', 'reclinated'], + 'credit': ['credit', 'direct'], + 'creditable': ['creditable', 'directable'], + 'creditive': ['creditive', 'directive'], + 'creditor': ['creditor', 'director'], + 'creditorship': ['creditorship', 'directorship'], + 'creditress': ['creditress', 'directress'], + 'creditrix': ['creditrix', 'directrix'], + 'crednerite': ['crednerite', 'interceder'], + 'credo': ['coder', 'cored', 'credo'], + 'cree': ['cere', 'cree'], + 'creed': ['ceder', 'cedre', 'cered', 'creed'], + 'creedal': ['cedrela', 'creedal', 'declare'], + 'creedalism': ['creedalism', 'misdeclare'], + 'creedist': ['creedist', 'desertic', 'discreet', 'discrete'], + 'creep': ['creep', 'crepe'], + 'creepered': ['creepered', 'predecree'], + 'creepie': ['creepie', 'repiece'], + 'cremation': ['cremation', 'manticore'], + 'cremator': ['cremator', 'mercator'], + 'crematorial': ['crematorial', 'mercatorial'], + 'cremor': ['cremor', 'cromer'], + 'crena': ['caner', 'crane', 'crena', 'nacre', 'rance'], + 'crenate': ['centare', 'crenate'], + 'crenated': ['crenated', 'decanter', 'nectared'], + 'crenation': ['connarite', 'container', 'cotarnine', 'crenation', 'narcotine'], + 'crenelate': ['crenelate', 'lanceteer'], + 'crenelation': ['crenelation', 'intolerance'], + 'crenele': ['crenele', 'encreel'], + 'crenellation': ['centrolineal', 'crenellation'], + 'crenitic': ['crenitic', 'cretinic'], + 'crenology': ['crenology', 'necrology'], + 'crenula': ['crenula', 'lucarne', 'nuclear', 'unclear'], + 'crenulate': ['calenture', 'crenulate'], + 'creodonta': ['coronated', 'creodonta'], + 'creolian': ['acrolein', + 'arecolin', + 'caroline', + 'colinear', + 'cornelia', + 'creolian', + 'lonicera'], + 'creolin': ['creolin', 'licorne', 'locrine'], + 'creosotic': ['corticose', 'creosotic'], + 'crepe': ['creep', 'crepe'], + 'crepidula': ['crepidula', 'pedicular'], + 'crepine': ['crepine', 'increep'], + 'crepiness': ['crepiness', 'princesse'], + 'crepis': ['crepis', 'cripes', 'persic', 'precis', 'spicer'], + 'crepitant': ['crepitant', 'pittancer'], + 'crepitation': ['actinopteri', 'crepitation', 'precitation'], + 'crepitous': ['crepitous', 'euproctis', 'uroseptic'], + 'crepitus': ['crepitus', 'piecrust'], + 'crepon': ['crepon', 'procne'], + 'crepy': ['crepy', 'cypre', 'percy'], + 'cresol': ['closer', 'cresol', 'escrol'], + 'cresolin': ['cresolin', 'licensor'], + 'cresotic': ['cortices', 'cresotic'], + 'cresson': ['cresson', 'crosnes'], + 'crestline': ['crestline', 'stenciler'], + 'crestmoreite': ['crestmoreite', 'stereometric'], + 'creta': ['caret', + 'carte', + 'cater', + 'crate', + 'creat', + 'creta', + 'react', + 'recta', + 'trace'], + 'cretan': ['canter', + 'creant', + 'cretan', + 'nectar', + 'recant', + 'tanrec', + 'trance'], + 'crete': ['crete', 'erect'], + 'cretification': ['certification', 'cretification', 'rectification'], + 'cretify': ['certify', 'cretify', 'rectify'], + 'cretin': ['cinter', 'cretin', 'crinet'], + 'cretinic': ['crenitic', 'cretinic'], + 'cretinoid': ['cretinoid', 'direction'], + 'cretion': ['cerotin', 'cointer', 'cotrine', 'cretion', 'noticer', 'rection'], + 'cretism': ['cretism', 'metrics'], + 'crewer': ['crewer', 'recrew'], + 'cribo': ['boric', 'cribo', 'orbic'], + 'crickle': ['clicker', 'crickle'], + 'cricothyroid': ['cricothyroid', 'thyrocricoid'], + 'cried': ['cider', 'cried', 'deric', 'dicer'], + 'crier': ['crier', 'ricer'], + 'criey': ['criey', 'ricey'], + 'crile': ['crile', 'elric', 'relic'], + 'crimean': ['armenic', 'carmine', 'ceriman', 'crimean', 'mercian'], + 'crimeful': ['crimeful', 'merciful'], + 'crimeless': ['crimeless', 'merciless'], + 'crimelessness': ['crimelessness', 'mercilessness'], + 'criminalese': ['criminalese', 'misreliance'], + 'criminate': ['antimeric', 'carminite', 'criminate', 'metrician'], + 'criminatory': ['coriamyrtin', 'criminatory'], + 'crimpage': ['crimpage', 'pergamic'], + 'crinal': ['carlin', 'clarin', 'crinal'], + 'crinanite': ['crinanite', 'natricine'], + 'crinated': ['crinated', 'dicentra'], + 'crine': ['cerin', 'crine'], + 'crined': ['cedrin', 'cinder', 'crined'], + 'crinet': ['cinter', 'cretin', 'crinet'], + 'cringle': ['clinger', 'cringle'], + 'crinite': ['citrine', 'crinite', 'inciter', 'neritic'], + 'crinkle': ['clinker', 'crinkle'], + 'cripes': ['crepis', 'cripes', 'persic', 'precis', 'spicer'], + 'cripple': ['clipper', 'cripple'], + 'crisp': ['crisp', 'scrip'], + 'crispation': ['antipsoric', 'ascription', 'crispation'], + 'crisped': ['crisped', 'discerp'], + 'crispy': ['crispy', 'cypris'], + 'crista': ['crista', 'racist'], + 'cristopher': ['cristopher', 'rectorship'], + 'criteria': ['criteria', 'triceria'], + 'criterion': ['criterion', 'tricerion'], + 'criterium': ['criterium', 'tricerium'], + 'crith': ['crith', 'richt'], + 'critic': ['citric', 'critic'], + 'cro': ['cor', 'cro', 'orc', 'roc'], + 'croak': ['arock', 'croak'], + 'croat': ['actor', 'corta', 'croat', 'rocta', 'taroc', 'troca'], + 'croatan': ['cantaro', 'croatan'], + 'croatian': ['craniota', 'croatian', 'narcotia', 'raincoat'], + 'crocein': ['cornice', 'crocein'], + 'croceine': ['cicerone', 'croceine'], + 'crocetin': ['crocetin', 'necrotic'], + 'crocidolite': ['crocidolite', 'crocodilite'], + 'crocin': ['cornic', 'crocin'], + 'crocodile': ['cordicole', 'crocodile'], + 'crocodilite': ['crocidolite', 'crocodilite'], + 'croconate': ['coenactor', 'croconate'], + 'crocus': ['crocus', 'succor'], + 'crom': ['corm', 'crom'], + 'crome': ['comer', 'crome'], + 'cromer': ['cremor', 'cromer'], + 'crone': ['coner', 'crone', 'recon'], + 'cronet': ['conter', 'cornet', 'cronet', 'roncet'], + 'cronian': ['corinna', 'cronian'], + 'cronish': ['cornish', 'cronish', 'sorchin'], + 'crony': ['corny', 'crony'], + 'croodle': ['colored', 'croodle', 'decolor'], + 'crool': ['color', 'corol', 'crool'], + 'croon': ['conor', 'croon', 'ronco'], + 'crooner': ['coroner', 'crooner', 'recroon'], + 'crop': ['copr', 'corp', 'crop'], + 'cropman': ['crampon', 'cropman'], + 'croppa': ['crappo', 'croppa'], + 'crore': ['corer', 'crore'], + 'crosa': ['arcos', 'crosa', 'oscar', 'sacro'], + 'crosier': ['cirrose', 'crosier'], + 'crosnes': ['cresson', 'crosnes'], + 'crosse': ['cessor', 'crosse', 'scorse'], + 'crosser': ['crosser', 'recross'], + 'crossite': ['crossite', 'crosstie'], + 'crossover': ['crossover', 'overcross'], + 'crosstie': ['crossite', 'crosstie'], + 'crosstied': ['crosstied', 'dissector'], + 'crosstree': ['crosstree', 'rectoress'], + 'crosswalk': ['classwork', 'crosswalk'], + 'crotal': ['carlot', 'crotal'], + 'crotalic': ['cortical', 'crotalic'], + 'crotalinae': ['creational', 'crotalinae', 'laceration', 'reactional'], + 'crotaline': ['alectrion', 'clarionet', 'crotaline', 'locarnite'], + 'crotalism': ['clamorist', 'crotalism'], + 'crotalo': ['crotalo', 'locator'], + 'crotaloid': ['crotaloid', 'doctorial'], + 'crotin': ['citron', 'cortin', 'crotin'], + 'croton': ['corton', 'croton'], + 'crotonate': ['contortae', 'crotonate'], + 'crottle': ['clotter', 'crottle'], + 'crouchant': ['archcount', 'crouchant'], + 'croupal': ['copular', 'croupal', 'cupolar', 'porcula'], + 'croupe': ['couper', 'croupe', 'poucer', 'recoup'], + 'croupily': ['croupily', 'polyuric'], + 'croupiness': ['croupiness', 'percussion', 'supersonic'], + 'crouse': ['cerous', 'course', 'crouse', 'source'], + 'crout': ['court', 'crout', 'turco'], + 'croute': ['couter', 'croute'], + 'crouton': ['contour', 'cornuto', 'countor', 'crouton'], + 'crowder': ['crowder', 'recrowd'], + 'crowned': ['crowned', 'decrown'], + 'crowner': ['crowner', 'recrown'], + 'crownmaker': ['cankerworm', 'crownmaker'], + 'croy': ['cory', 'croy'], + 'croydon': ['corydon', 'croydon'], + 'cruces': ['cercus', 'cruces'], + 'cruciate': ['aceturic', 'cruciate'], + 'crudwort': ['crudwort', 'curdwort'], + 'cruel': ['cruel', 'lucre', 'ulcer'], + 'cruels': ['clerus', 'cruels'], + 'cruelty': ['cruelty', 'cutlery'], + 'cruet': ['cruet', 'eruct', 'recut', 'truce'], + 'cruise': ['cruise', 'crusie'], + 'cruisken': ['cruisken', 'unsicker'], + 'crunode': ['crunode', 'uncored'], + 'crureus': ['crureus', 'surcrue'], + 'crurogenital': ['crurogenital', 'genitocrural'], + 'cruroinguinal': ['cruroinguinal', 'inguinocrural'], + 'crus': ['crus', 'scur'], + 'crusado': ['acrodus', 'crusado'], + 'crusca': ['crusca', 'curcas'], + 'cruse': ['cruse', 'curse', 'sucre'], + 'crusher': ['crusher', 'recrush'], + 'crusie': ['cruise', 'crusie'], + 'crust': ['crust', 'curst'], + 'crustate': ['crustate', 'scrutate'], + 'crustation': ['crustation', 'scrutation'], + 'crustily': ['crustily', 'rusticly'], + 'crustiness': ['crustiness', 'rusticness'], + 'crusty': ['crusty', 'curtsy'], + 'cruth': ['cruth', 'rutch'], + 'cryosel': ['cryosel', 'scroyle'], + 'cryptodire': ['cryptodire', 'predictory'], + 'cryptomeria': ['cryptomeria', 'imprecatory'], + 'cryptostomate': ['cryptostomate', 'prostatectomy'], + 'ctenidial': ['ctenidial', 'identical'], + 'ctenoid': ['condite', 'ctenoid'], + 'ctenolium': ['ctenolium', 'monticule'], + 'ctenophore': ['ctenophore', 'nectophore'], + 'ctetology': ['ctetology', 'tectology'], + 'cuailnge': ['cuailnge', 'glaucine'], + 'cuarteron': ['cuarteron', 'raconteur'], + 'cubanite': ['cubanite', 'incubate'], + 'cuber': ['bruce', 'cebur', 'cuber'], + 'cubist': ['bustic', 'cubist'], + 'cubit': ['butic', 'cubit'], + 'cubitale': ['baculite', 'cubitale'], + 'cuboidal': ['baculoid', 'cuboidal'], + 'cuchan': ['caunch', 'cuchan'], + 'cueball': ['bullace', 'cueball'], + 'cueman': ['acumen', 'cueman'], + 'cuir': ['cuir', 'uric'], + 'culebra': ['culebra', 'curable'], + 'culet': ['culet', 'lucet'], + 'culinary': ['culinary', 'uranylic'], + 'culmy': ['culmy', 'cumyl'], + 'culpose': ['culpose', 'ploceus', 'upclose'], + 'cultch': ['clutch', 'cultch'], + 'cultivar': ['cultivar', 'curvital'], + 'culturine': ['culturine', 'inculture'], + 'cumaean': ['cumaean', 'encauma'], + 'cumar': ['carum', 'cumar'], + 'cumber': ['cumber', 'cumbre'], + 'cumberer': ['cerebrum', 'cumberer'], + 'cumbraite': ['bacterium', 'cumbraite'], + 'cumbre': ['cumber', 'cumbre'], + 'cumic': ['cumic', 'mucic'], + 'cumin': ['cumin', 'mucin'], + 'cumol': ['cumol', 'locum'], + 'cumulite': ['cumulite', 'lutecium'], + 'cumyl': ['culmy', 'cumyl'], + 'cuna': ['cuna', 'unca'], + 'cunan': ['canun', 'cunan'], + 'cuneal': ['auncel', 'cuneal', 'lacune', 'launce', 'unlace'], + 'cuneator': ['cornuate', 'courante', 'cuneator', 'outrance'], + 'cunila': ['cunila', 'lucian', 'lucina', 'uncial'], + 'cuon': ['cuon', 'unco'], + 'cuorin': ['cuorin', 'uronic'], + 'cupid': ['cupid', 'pudic'], + 'cupidity': ['cupidity', 'pudicity'], + 'cupidone': ['cupidone', 'uncopied'], + 'cupola': ['copula', 'cupola'], + 'cupolar': ['copular', 'croupal', 'cupolar', 'porcula'], + 'cupreous': ['cupreous', 'upcourse'], + 'cuprite': ['cuprite', 'picture'], + 'curable': ['culebra', 'curable'], + 'curate': ['acture', 'cauter', 'curate'], + 'curateship': ['curateship', 'pasticheur'], + 'curation': ['curation', 'nocturia'], + 'curatory': ['curatory', 'outcarry'], + 'curcas': ['crusca', 'curcas'], + 'curdle': ['curdle', 'curled'], + 'curdwort': ['crudwort', 'curdwort'], + 'cure': ['cure', 'ecru', 'eruc'], + 'curer': ['curer', 'recur'], + 'curial': ['curial', 'lauric', 'uracil', 'uralic'], + 'curialist': ['curialist', 'rusticial'], + 'curie': ['curie', 'ureic'], + 'curin': ['curin', 'incur', 'runic'], + 'curine': ['curine', 'erucin', 'neuric'], + 'curiosa': ['carious', 'curiosa'], + 'curite': ['curite', 'teucri', 'uretic'], + 'curled': ['curdle', 'curled'], + 'curler': ['curler', 'recurl'], + 'cursa': ['cursa', 'scaur'], + 'cursal': ['cursal', 'sulcar'], + 'curse': ['cruse', 'curse', 'sucre'], + 'cursed': ['cedrus', 'cursed'], + 'curst': ['crust', 'curst'], + 'cursus': ['cursus', 'ruscus'], + 'curtail': ['curtail', 'trucial'], + 'curtailer': ['curtailer', 'recruital', 'reticular'], + 'curtain': ['curtain', 'turacin', 'turcian'], + 'curtation': ['anticourt', 'curtation', 'ructation'], + 'curtilage': ['curtilage', 'cutigeral', 'graticule'], + 'curtis': ['citrus', 'curtis', 'rictus', 'rustic'], + 'curtise': ['curtise', 'icterus'], + 'curtsy': ['crusty', 'curtsy'], + 'curvital': ['cultivar', 'curvital'], + 'cush': ['cush', 'such'], + 'cushionless': ['cushionless', 'slouchiness'], + 'cusinero': ['coinsure', 'corineus', 'cusinero'], + 'cusk': ['cusk', 'suck'], + 'cusp': ['cusp', 'scup'], + 'cuspal': ['cuspal', 'placus'], + 'custom': ['custom', 'muscot'], + 'customer': ['costumer', 'customer'], + 'cutheal': ['auchlet', 'cutheal', 'taluche'], + 'cutigeral': ['curtilage', 'cutigeral', 'graticule'], + 'cutin': ['cutin', 'incut', 'tunic'], + 'cutis': ['cutis', 'ictus'], + 'cutler': ['cutler', 'reluct'], + 'cutleress': ['cutleress', 'lecturess', 'truceless'], + 'cutleria': ['arculite', 'cutleria', 'lucretia', 'reticula', 'treculia'], + 'cutlery': ['cruelty', 'cutlery'], + 'cutlet': ['cutlet', 'cuttle'], + 'cutoff': ['cutoff', 'offcut'], + 'cutout': ['cutout', 'outcut'], + 'cutover': ['cutover', 'overcut'], + 'cuttle': ['cutlet', 'cuttle'], + 'cuttler': ['clutter', 'cuttler'], + 'cutup': ['cutup', 'upcut'], + 'cuya': ['cuya', 'yuca'], + 'cyamus': ['cyamus', 'muysca'], + 'cyan': ['cany', 'cyan'], + 'cyanidine': ['cyanidine', 'dicyanine'], + 'cyanol': ['alcyon', 'cyanol'], + 'cyanole': ['alcyone', 'cyanole'], + 'cyanometric': ['craniectomy', 'cyanometric'], + 'cyanophycin': ['cyanophycin', 'phycocyanin'], + 'cyanuret': ['centaury', 'cyanuret'], + 'cyath': ['cathy', 'cyath', 'yacht'], + 'cyclamine': ['cyclamine', 'macilency'], + 'cyclian': ['cyclian', 'cynical'], + 'cyclide': ['cyclide', 'decylic', 'dicycle'], + 'cyclism': ['clysmic', 'cyclism'], + 'cyclotome': ['colectomy', 'cyclotome'], + 'cydonian': ['anodynic', 'cydonian'], + 'cylindrite': ['cylindrite', 'indirectly'], + 'cylix': ['cylix', 'xylic'], + 'cymation': ['cymation', 'myatonic', 'onymatic'], + 'cymoid': ['cymoid', 'mycoid'], + 'cymometer': ['cymometer', 'mecometry'], + 'cymose': ['cymose', 'mycose'], + 'cymule': ['cymule', 'lyceum'], + 'cynara': ['canary', 'cynara'], + 'cynaroid': ['cynaroid', 'dicaryon'], + 'cynical': ['cyclian', 'cynical'], + 'cynogale': ['acylogen', 'cynogale'], + 'cynophilic': ['cynophilic', 'philocynic'], + 'cynosural': ['consulary', 'cynosural'], + 'cyphonism': ['cyphonism', 'symphonic'], + 'cypre': ['crepy', 'cypre', 'percy'], + 'cypria': ['cypria', 'picary', 'piracy'], + 'cyprian': ['cyprian', 'cyprina'], + 'cyprina': ['cyprian', 'cyprina'], + 'cyprine': ['cyprine', 'pyrenic'], + 'cypris': ['crispy', 'cypris'], + 'cyrano': ['canroy', 'crayon', 'cyrano', 'nyroca'], + 'cyril': ['cyril', 'lyric'], + 'cyrilla': ['cyrilla', 'lyrical'], + 'cyrtopia': ['cyrtopia', 'poticary'], + 'cyst': ['cyst', 'scyt'], + 'cystidean': ['asyndetic', 'cystidean', 'syndicate'], + 'cystitis': ['cystitis', 'scytitis'], + 'cystoadenoma': ['adenocystoma', 'cystoadenoma'], + 'cystofibroma': ['cystofibroma', 'fibrocystoma'], + 'cystolith': ['cystolith', 'lithocyst'], + 'cystomyxoma': ['cystomyxoma', 'myxocystoma'], + 'cystonephrosis': ['cystonephrosis', 'nephrocystosis'], + 'cystopyelitis': ['cystopyelitis', 'pyelocystitis'], + 'cystotome': ['cystotome', 'cytostome', 'ostectomy'], + 'cystourethritis': ['cystourethritis', 'urethrocystitis'], + 'cytase': ['cytase', 'stacey'], + 'cytherea': ['cheatery', 'cytherea', 'teachery'], + 'cytherean': ['cytherean', 'enchytrae'], + 'cytisine': ['cytisine', 'syenitic'], + 'cytoblastemic': ['blastomycetic', 'cytoblastemic'], + 'cytoblastemous': ['blastomycetous', 'cytoblastemous'], + 'cytochrome': ['chromocyte', 'cytochrome'], + 'cytoid': ['cytoid', 'docity'], + 'cytomere': ['cytomere', 'merocyte'], + 'cytophil': ['cytophil', 'phycitol'], + 'cytosine': ['cenosity', 'cytosine'], + 'cytosome': ['cytosome', 'otomyces'], + 'cytost': ['cytost', 'scotty'], + 'cytostome': ['cystotome', 'cytostome', 'ostectomy'], + 'czarian': ['czarian', 'czarina'], + 'czarina': ['czarian', 'czarina'], + 'da': ['ad', 'da'], + 'dab': ['bad', 'dab'], + 'dabber': ['barbed', 'dabber'], + 'dabbler': ['dabbler', 'drabble'], + 'dabitis': ['dabitis', 'dibatis'], + 'dablet': ['dablet', 'tabled'], + 'dace': ['cade', 'dace', 'ecad'], + 'dacelo': ['alcedo', 'dacelo'], + 'dacian': ['acnida', 'anacid', 'dacian'], + 'dacker': ['arcked', 'dacker'], + 'dacryolith': ['dacryolith', 'hydrotical'], + 'dacryon': ['candroy', 'dacryon'], + 'dactylonomy': ['dactylonomy', 'monodactyly'], + 'dactylopteridae': ['dactylopteridae', 'pterodactylidae'], + 'dactylopterus': ['dactylopterus', 'pterodactylus'], + 'dacus': ['cadus', 'dacus'], + 'dad': ['add', 'dad'], + 'dada': ['adad', 'adda', 'dada'], + 'dadap': ['dadap', 'padda'], + 'dade': ['dade', 'dead', 'edda'], + 'dadu': ['addu', 'dadu', 'daud', 'duad'], + 'dae': ['ade', 'dae'], + 'daemon': ['daemon', 'damone', 'modena'], + 'daemonic': ['codamine', 'comedian', 'daemonic', 'demoniac'], + 'daer': ['ared', 'daer', 'dare', 'dear', 'read'], + 'dag': ['dag', 'gad'], + 'dagaba': ['badaga', 'dagaba', 'gadaba'], + 'dagame': ['dagame', 'damage'], + 'dagbane': ['bandage', 'dagbane'], + 'dagestan': ['dagestan', 'standage'], + 'dagger': ['dagger', 'gadger', 'ragged'], + 'daggers': ['daggers', 'seggard'], + 'daggle': ['daggle', 'lagged'], + 'dago': ['dago', 'goad'], + 'dagomba': ['dagomba', 'gambado'], + 'dags': ['dags', 'sgad'], + 'dah': ['dah', 'dha', 'had'], + 'daidle': ['daidle', 'laddie'], + 'daikon': ['daikon', 'nodiak'], + 'dail': ['dail', 'dali', 'dial', 'laid', 'lida'], + 'daily': ['daily', 'lydia'], + 'daimen': ['daimen', 'damine', 'maiden', 'median', 'medina'], + 'daimio': ['daimio', 'maioid'], + 'daimon': ['amidon', 'daimon', 'domain'], + 'dain': ['adin', 'andi', 'dain', 'dani', 'dian', 'naid'], + 'dairi': ['dairi', 'darii', 'radii'], + 'dairy': ['dairy', 'diary', 'yaird'], + 'dais': ['dais', 'dasi', 'disa', 'said', 'sida'], + 'daisy': ['daisy', 'sayid'], + 'daker': ['daker', 'drake', 'kedar', 'radek'], + 'dal': ['dal', 'lad'], + 'dale': ['dale', 'deal', 'lade', 'lead', 'leda'], + 'dalea': ['adela', 'dalea'], + 'dalecarlian': ['calendarial', 'dalecarlian'], + 'daleman': ['daleman', 'lademan', 'leadman'], + 'daler': ['alder', 'daler', 'lader'], + 'dalesman': ['dalesman', 'leadsman'], + 'dali': ['dail', 'dali', 'dial', 'laid', 'lida'], + 'dalle': ['dalle', 'della', 'ladle'], + 'dallying': ['dallying', 'ladyling'], + 'dalt': ['dalt', 'tald'], + 'dalteen': ['dalteen', 'dentale', 'edental'], + 'dam': ['dam', 'mad'], + 'dama': ['adam', 'dama'], + 'damage': ['dagame', 'damage'], + 'daman': ['adman', 'daman', 'namda'], + 'damara': ['armada', 'damara', 'ramada'], + 'dame': ['dame', 'made', 'mead'], + 'damewort': ['damewort', 'wardmote'], + 'damia': ['amadi', 'damia', 'madia', 'maida'], + 'damie': ['amide', 'damie', 'media'], + 'damier': ['admire', 'armied', 'damier', 'dimera', 'merida'], + 'damine': ['daimen', 'damine', 'maiden', 'median', 'medina'], + 'dammer': ['dammer', 'dramme'], + 'dammish': ['dammish', 'mahdism'], + 'damn': ['damn', 'mand'], + 'damnation': ['damnation', 'mandation'], + 'damnatory': ['damnatory', 'mandatory'], + 'damned': ['damned', 'demand', 'madden'], + 'damner': ['damner', 'manred', 'randem', 'remand'], + 'damnii': ['amidin', 'damnii'], + 'damnous': ['damnous', 'osmunda'], + 'damon': ['damon', 'monad', 'nomad'], + 'damone': ['daemon', 'damone', 'modena'], + 'damonico': ['damonico', 'monoacid'], + 'dampen': ['dampen', 'madnep'], + 'damper': ['damper', 'ramped'], + 'dampish': ['dampish', 'madship', 'phasmid'], + 'dan': ['and', 'dan'], + 'dana': ['anda', 'dana'], + 'danaan': ['ananda', 'danaan'], + 'danai': ['danai', 'diana', 'naiad'], + 'danainae': ['anadenia', 'danainae'], + 'danakil': ['danakil', 'dankali', 'kaldani', 'ladakin'], + 'danalite': ['danalite', 'detainal'], + 'dancalite': ['cadential', 'dancalite'], + 'dance': ['dance', 'decan'], + 'dancer': ['cedarn', 'dancer', 'nacred'], + 'dancery': ['ardency', 'dancery'], + 'dander': ['dander', 'darned', 'nadder'], + 'dandle': ['dandle', 'landed'], + 'dandler': ['dandler', 'dendral'], + 'dane': ['ande', 'dane', 'dean', 'edna'], + 'danewort': ['danewort', 'teardown'], + 'danger': ['danger', 'gander', 'garden', 'ranged'], + 'dangerful': ['dangerful', 'gardenful'], + 'dangerless': ['dangerless', 'gardenless'], + 'dangle': ['angled', 'dangle', 'englad', 'lagend'], + 'dangler': ['dangler', 'gnarled'], + 'danglin': ['danglin', 'landing'], + 'dani': ['adin', 'andi', 'dain', 'dani', 'dian', 'naid'], + 'danian': ['andian', 'danian', 'nidana'], + 'danic': ['canid', 'cnida', 'danic'], + 'daniel': ['aldine', 'daniel', 'delian', 'denial', 'enalid', 'leadin'], + 'daniele': ['adeline', 'daniele', 'delaine'], + 'danielic': ['alcidine', 'danielic', 'lecaniid'], + 'danio': ['adion', 'danio', 'doina', 'donia'], + 'danish': ['danish', 'sandhi'], + 'danism': ['danism', 'disman'], + 'danite': ['danite', 'detain'], + 'dankali': ['danakil', 'dankali', 'kaldani', 'ladakin'], + 'danli': ['danli', 'ladin', 'linda', 'nidal'], + 'dannie': ['aidenn', 'andine', 'dannie', 'indane'], + 'danseuse': ['danseuse', 'sudanese'], + 'dantean': ['andante', 'dantean'], + 'dantist': ['dantist', 'distant'], + 'danuri': ['danuri', 'diurna', 'dunair', 'durain', 'durani', 'durian'], + 'dao': ['ado', 'dao', 'oda'], + 'daoine': ['daoine', 'oneida'], + 'dap': ['dap', 'pad'], + 'daphnis': ['daphnis', 'dishpan'], + 'dapicho': ['dapicho', 'phacoid'], + 'dapple': ['dapple', 'lapped', 'palped'], + 'dar': ['dar', 'rad'], + 'daraf': ['daraf', 'farad'], + 'darby': ['bardy', 'darby'], + 'darci': ['acrid', 'caird', 'carid', 'darci', 'daric', 'dirca'], + 'dare': ['ared', 'daer', 'dare', 'dear', 'read'], + 'dareall': ['ardella', 'dareall'], + 'daren': ['andre', 'arend', 'daren', 'redan'], + 'darer': ['darer', 'drear'], + 'darg': ['darg', 'drag', 'grad'], + 'darger': ['darger', 'gerard', 'grader', 'redrag', 'regard'], + 'dargo': ['dargo', 'dogra', 'drago'], + 'dargsman': ['dargsman', 'dragsman'], + 'dari': ['arid', 'dari', 'raid'], + 'daric': ['acrid', 'caird', 'carid', 'darci', 'daric', 'dirca'], + 'darien': ['darien', 'draine'], + 'darii': ['dairi', 'darii', 'radii'], + 'darin': ['darin', 'dinar', 'drain', 'indra', 'nadir', 'ranid'], + 'daring': ['daring', 'dingar', 'gradin'], + 'darius': ['darius', 'radius'], + 'darken': ['darken', 'kanred', 'ranked'], + 'darkener': ['darkener', 'redarken'], + 'darn': ['darn', 'nard', 'rand'], + 'darned': ['dander', 'darned', 'nadder'], + 'darnel': ['aldern', + 'darnel', + 'enlard', + 'lander', + 'lenard', + 'randle', + 'reland'], + 'darner': ['darner', 'darren', 'errand', 'rander', 'redarn'], + 'darning': ['darning', 'randing'], + 'darrein': ['darrein', 'drainer'], + 'darren': ['darner', 'darren', 'errand', 'rander', 'redarn'], + 'darshana': ['darshana', 'shardana'], + 'darst': ['darst', 'darts', 'strad'], + 'dart': ['dart', 'drat'], + 'darter': ['darter', + 'dartre', + 'redart', + 'retard', + 'retrad', + 'tarred', + 'trader'], + 'darting': ['darting', 'trading'], + 'dartle': ['dartle', 'tardle'], + 'dartoic': ['arctoid', 'carotid', 'dartoic'], + 'dartre': ['darter', + 'dartre', + 'redart', + 'retard', + 'retrad', + 'tarred', + 'trader'], + 'dartrose': ['dartrose', 'roadster'], + 'darts': ['darst', 'darts', 'strad'], + 'daryl': ['daryl', 'lardy', 'lyard'], + 'das': ['das', 'sad'], + 'dash': ['dash', 'sadh', 'shad'], + 'dashed': ['dashed', 'shaded'], + 'dasheen': ['dasheen', 'enshade'], + 'dasher': ['dasher', 'shader', 'sheard'], + 'dashing': ['dashing', 'shading'], + 'dashnak': ['dashnak', 'shadkan'], + 'dashy': ['dashy', 'shady'], + 'dasi': ['dais', 'dasi', 'disa', 'said', 'sida'], + 'dasnt': ['dasnt', 'stand'], + 'dasturi': ['dasturi', 'rudista'], + 'dasya': ['adays', 'dasya'], + 'dasyurine': ['dasyurine', 'dysneuria'], + 'data': ['adat', 'data'], + 'datable': ['albetad', 'datable'], + 'dataria': ['dataria', 'radiata'], + 'date': ['adet', 'date', 'tade', 'tead', 'teda'], + 'dateless': ['dateless', 'detassel'], + 'dater': ['dater', 'derat', 'detar', 'drate', 'rated', 'trade', 'tread'], + 'datil': ['datil', 'dital', 'tidal', 'tilda'], + 'datism': ['amidst', 'datism'], + 'daub': ['baud', 'buda', 'daub'], + 'dauber': ['dauber', 'redaub'], + 'daubster': ['daubster', 'subtread'], + 'daud': ['addu', 'dadu', 'daud', 'duad'], + 'daunch': ['chandu', 'daunch'], + 'daunter': ['daunter', 'unarted', 'unrated', 'untread'], + 'dauntless': ['adultness', 'dauntless'], + 'daur': ['ardu', 'daur', 'dura'], + 'dave': ['dave', 'deva', 'vade', 'veda'], + 'daven': ['daven', 'vaned'], + 'davy': ['davy', 'vady'], + 'daw': ['awd', 'daw', 'wad'], + 'dawdler': ['dawdler', 'waddler'], + 'dawdling': ['dawdling', 'waddling'], + 'dawdlingly': ['dawdlingly', 'waddlingly'], + 'dawdy': ['dawdy', 'waddy'], + 'dawn': ['dawn', 'wand'], + 'dawnlike': ['dawnlike', 'wandlike'], + 'dawny': ['dawny', 'wandy'], + 'day': ['ady', 'day', 'yad'], + 'dayal': ['adlay', 'dayal'], + 'dayfly': ['dayfly', 'ladyfy'], + 'days': ['days', 'dyas'], + 'daysman': ['daysman', 'mandyas'], + 'daytime': ['daytime', 'maytide'], + 'daywork': ['daywork', 'workday'], + 'daze': ['adze', 'daze'], + 'de': ['de', 'ed'], + 'deacon': ['acnode', 'deacon'], + 'deaconship': ['deaconship', 'endophasic'], + 'dead': ['dade', 'dead', 'edda'], + 'deadborn': ['deadborn', 'endboard'], + 'deadener': ['deadener', 'endeared'], + 'deadlock': ['deadlock', 'deckload'], + 'deaf': ['deaf', 'fade'], + 'deair': ['aider', 'deair', 'irade', 'redia'], + 'deal': ['dale', 'deal', 'lade', 'lead', 'leda'], + 'dealable': ['dealable', 'leadable'], + 'dealation': ['atloidean', 'dealation'], + 'dealer': ['dealer', 'leader', 'redeal', 'relade', 'relead'], + 'dealership': ['dealership', 'leadership'], + 'dealing': ['adeling', 'dealing', 'leading'], + 'dealt': ['adlet', 'dealt', 'delta', 'lated', 'taled'], + 'deaminase': ['deaminase', 'mesadenia'], + 'dean': ['ande', 'dane', 'dean', 'edna'], + 'deaner': ['deaner', 'endear'], + 'deaness': ['deaness', 'edessan'], + 'deaquation': ['adequation', 'deaquation'], + 'dear': ['ared', 'daer', 'dare', 'dear', 'read'], + 'dearie': ['aeried', 'dearie'], + 'dearth': ['dearth', 'hatred', 'rathed', 'thread'], + 'deary': ['deary', 'deray', 'rayed', 'ready', 'yeard'], + 'deash': ['deash', 'hades', 'sadhe', 'shade'], + 'deasil': ['aisled', 'deasil', 'ladies', 'sailed'], + 'deave': ['deave', 'eaved', 'evade'], + 'deb': ['bed', 'deb'], + 'debacle': ['belaced', 'debacle'], + 'debar': ['ardeb', 'beard', 'bread', 'debar'], + 'debark': ['bedark', 'debark'], + 'debaser': ['debaser', 'sabered'], + 'debater': ['betread', 'debater'], + 'deben': ['beden', 'deben', 'deneb'], + 'debi': ['beid', 'bide', 'debi', 'dieb'], + 'debile': ['debile', 'edible'], + 'debit': ['bidet', 'debit'], + 'debosh': ['beshod', 'debosh'], + 'debrief': ['debrief', 'defiber', 'fibered'], + 'debutant': ['debutant', 'unbatted'], + 'debutante': ['debutante', 'unabetted'], + 'decachord': ['decachord', 'dodecarch'], + 'decadic': ['caddice', 'decadic'], + 'decal': ['clead', 'decal', 'laced'], + 'decalin': ['cladine', 'decalin', 'iceland'], + 'decaliter': ['decaliter', 'decalitre'], + 'decalitre': ['decaliter', 'decalitre'], + 'decameter': ['decameter', 'decametre'], + 'decametre': ['decameter', 'decametre'], + 'decan': ['dance', 'decan'], + 'decanal': ['candela', 'decanal'], + 'decani': ['decani', 'decian'], + 'decant': ['cadent', 'canted', 'decant'], + 'decantate': ['catenated', 'decantate'], + 'decanter': ['crenated', 'decanter', 'nectared'], + 'decantherous': ['countershade', 'decantherous'], + 'decap': ['caped', 'decap', 'paced'], + 'decart': ['cedrat', 'decart', 'redact'], + 'decastere': ['decastere', 'desecrate'], + 'decator': ['cordate', 'decator', 'redcoat'], + 'decay': ['acedy', 'decay'], + 'deceiver': ['deceiver', 'received'], + 'decennia': ['cadinene', 'decennia', 'enneadic'], + 'decennial': ['celandine', 'decennial'], + 'decent': ['cedent', 'decent'], + 'decenter': ['centered', 'decenter', 'decentre', 'recedent'], + 'decentre': ['centered', 'decenter', 'decentre', 'recedent'], + 'decern': ['cendre', 'decern'], + 'decian': ['decani', 'decian'], + 'deciatine': ['deciatine', 'diacetine', 'taenicide', 'teniacide'], + 'decider': ['decider', 'decried'], + 'decillion': ['celloidin', 'collidine', 'decillion'], + 'decima': ['amiced', 'decima'], + 'decimal': ['camelid', 'decimal', 'declaim', 'medical'], + 'decimally': ['decimally', 'medically'], + 'decimate': ['decimate', 'medicate'], + 'decimation': ['decimation', 'medication'], + 'decimator': ['decimator', 'medicator', 'mordicate'], + 'decimestrial': ['decimestrial', 'sedimetrical'], + 'decimosexto': ['decimosexto', 'sextodecimo'], + 'deckel': ['deckel', 'deckle'], + 'decker': ['decker', 'redeck'], + 'deckle': ['deckel', 'deckle'], + 'deckload': ['deadlock', 'deckload'], + 'declaim': ['camelid', 'decimal', 'declaim', 'medical'], + 'declaimer': ['declaimer', 'demiracle'], + 'declaration': ['declaration', 'redactional'], + 'declare': ['cedrela', 'creedal', 'declare'], + 'declass': ['classed', 'declass'], + 'declinate': ['declinate', 'encitadel'], + 'declinatory': ['adrenolytic', 'declinatory'], + 'decoat': ['coated', 'decoat'], + 'decollate': ['decollate', 'ocellated'], + 'decollator': ['corollated', 'decollator'], + 'decolor': ['colored', 'croodle', 'decolor'], + 'decompress': ['compressed', 'decompress'], + 'deconsider': ['considered', 'deconsider'], + 'decorate': ['decorate', 'ocreated'], + 'decoration': ['carotenoid', 'coronadite', 'decoration'], + 'decorist': ['decorist', 'sectroid'], + 'decream': ['decream', 'racemed'], + 'decree': ['decree', 'recede'], + 'decreer': ['decreer', 'receder'], + 'decreet': ['decreet', 'decrete'], + 'decrepit': ['decrepit', 'depicter', 'precited'], + 'decrete': ['decreet', 'decrete'], + 'decretist': ['decretist', 'trisected'], + 'decrial': ['decrial', 'radicel', 'radicle'], + 'decried': ['decider', 'decried'], + 'decrown': ['crowned', 'decrown'], + 'decry': ['cedry', 'decry'], + 'decurionate': ['counteridea', 'decurionate'], + 'decurrency': ['decurrency', 'recrudency'], + 'decursion': ['cinderous', 'decursion'], + 'decus': ['decus', 'duces'], + 'decyl': ['clyde', 'decyl'], + 'decylic': ['cyclide', 'decylic', 'dicycle'], + 'dedan': ['dedan', 'denda'], + 'dedicant': ['addicent', 'dedicant'], + 'dedo': ['dedo', 'dode', 'eddo'], + 'deduce': ['deduce', 'deuced'], + 'deduct': ['deduct', 'ducted'], + 'deem': ['deem', 'deme', 'mede', 'meed'], + 'deemer': ['deemer', 'meered', 'redeem', 'remede'], + 'deep': ['deep', 'peed'], + 'deer': ['deer', 'dere', 'dree', 'rede', 'reed'], + 'deerhair': ['deerhair', 'dehairer'], + 'deerhorn': ['deerhorn', 'dehorner'], + 'deerwood': ['deerwood', 'doorweed'], + 'defat': ['defat', 'fated'], + 'defaulter': ['defaulter', 'redefault'], + 'defeater': ['defeater', 'federate', 'redefeat'], + 'defensor': ['defensor', 'foresend'], + 'defer': ['defer', 'freed'], + 'defial': ['afield', 'defial'], + 'defiber': ['debrief', 'defiber', 'fibered'], + 'defile': ['defile', 'fidele'], + 'defiled': ['defiled', 'fielded'], + 'defiler': ['defiler', 'fielder'], + 'definable': ['beanfield', 'definable'], + 'define': ['define', 'infeed'], + 'definer': ['definer', 'refined'], + 'deflect': ['clefted', 'deflect'], + 'deflesh': ['deflesh', 'fleshed'], + 'deflex': ['deflex', 'flexed'], + 'deflower': ['deflower', 'flowered'], + 'defluent': ['defluent', 'unfelted'], + 'defog': ['defog', 'fodge'], + 'deforciant': ['deforciant', 'fornicated'], + 'deforest': ['deforest', 'forested'], + 'deform': ['deform', 'formed'], + 'deformer': ['deformer', 'reformed'], + 'defray': ['defray', 'frayed'], + 'defrost': ['defrost', 'frosted'], + 'deg': ['deg', 'ged'], + 'degarnish': ['degarnish', 'garnished'], + 'degasser': ['degasser', 'dressage'], + 'degelation': ['degelation', 'delegation'], + 'degrain': ['degrain', 'deraign', 'deringa', 'gradine', 'grained', 'reading'], + 'degu': ['degu', 'gude'], + 'dehair': ['dehair', 'haired'], + 'dehairer': ['deerhair', 'dehairer'], + 'dehorn': ['dehorn', 'horned'], + 'dehorner': ['deerhorn', 'dehorner'], + 'dehors': ['dehors', 'rhodes', 'shoder', 'shored'], + 'dehortation': ['dehortation', 'theriodonta'], + 'dehusk': ['dehusk', 'husked'], + 'deicer': ['ceride', 'deicer'], + 'deictical': ['deictical', 'dialectic'], + 'deification': ['deification', 'edification'], + 'deificatory': ['deificatory', 'edificatory'], + 'deifier': ['deifier', 'edifier'], + 'deify': ['deify', 'edify'], + 'deign': ['deign', 'dinge', 'nidge'], + 'deino': ['deino', 'dione', 'edoni'], + 'deinocephalia': ['deinocephalia', 'palaeechinoid'], + 'deinos': ['deinos', 'donsie', 'inodes', 'onside'], + 'deipara': ['deipara', 'paridae'], + 'deirdre': ['deirdre', 'derider', 'derride', 'ridered'], + 'deism': ['deism', 'disme'], + 'deist': ['deist', 'steid'], + 'deistic': ['deistic', 'dietics'], + 'deistically': ['deistically', 'dialystelic'], + 'deity': ['deity', 'tydie'], + 'deityship': ['deityship', 'diphysite'], + 'del': ['del', 'eld', 'led'], + 'delaine': ['adeline', 'daniele', 'delaine'], + 'delaminate': ['antemedial', 'delaminate'], + 'delapse': ['delapse', 'sepaled'], + 'delate': ['delate', 'elated'], + 'delater': ['delater', 'related', 'treadle'], + 'delator': ['delator', 'leotard'], + 'delawn': ['delawn', 'lawned', 'wandle'], + 'delay': ['delay', 'leady'], + 'delayer': ['delayer', 'layered', 'redelay'], + 'delayful': ['delayful', 'feudally'], + 'dele': ['dele', 'lede', 'leed'], + 'delead': ['delead', 'leaded'], + 'delegation': ['degelation', 'delegation'], + 'delegatory': ['delegatory', 'derogately'], + 'delete': ['delete', 'teedle'], + 'delf': ['delf', 'fled'], + 'delhi': ['delhi', 'hield'], + 'delia': ['adiel', 'delia', 'ideal'], + 'delian': ['aldine', 'daniel', 'delian', 'denial', 'enalid', 'leadin'], + 'delible': ['bellied', 'delible'], + 'delicateness': ['delicateness', 'delicatessen'], + 'delicatessen': ['delicateness', 'delicatessen'], + 'delichon': ['chelidon', 'chelonid', 'delichon'], + 'delict': ['delict', 'deltic'], + 'deligation': ['deligation', 'gadolinite', 'gelatinoid'], + 'delignate': ['delignate', 'gelatined'], + 'delimit': ['delimit', 'limited'], + 'delimitation': ['delimitation', 'mniotiltidae'], + 'delineator': ['delineator', 'rondeletia'], + 'delint': ['delint', 'dentil'], + 'delirament': ['delirament', 'derailment'], + 'deliriant': ['deliriant', 'draintile', 'interlaid'], + 'deliver': ['deliver', 'deviler', 'livered'], + 'deliverer': ['deliverer', 'redeliver'], + 'della': ['dalle', 'della', 'ladle'], + 'deloul': ['deloul', 'duello'], + 'delphinius': ['delphinius', 'sulphinide'], + 'delta': ['adlet', 'dealt', 'delta', 'lated', 'taled'], + 'deltaic': ['citadel', 'deltaic', 'dialect', 'edictal', 'lactide'], + 'deltic': ['delict', 'deltic'], + 'deluding': ['deluding', 'ungilded'], + 'delusion': ['delusion', 'unsoiled'], + 'delusionist': ['delusionist', 'indissolute'], + 'deluster': ['deluster', 'ulstered'], + 'demal': ['demal', 'medal'], + 'demand': ['damned', 'demand', 'madden'], + 'demander': ['demander', 'redemand'], + 'demanding': ['demanding', 'maddening'], + 'demandingly': ['demandingly', 'maddeningly'], + 'demantoid': ['demantoid', 'dominated'], + 'demarcate': ['camerated', 'demarcate'], + 'demarcation': ['demarcation', 'democratian'], + 'demark': ['demark', 'marked'], + 'demast': ['demast', 'masted'], + 'deme': ['deem', 'deme', 'mede', 'meed'], + 'demean': ['amende', 'demean', 'meaned', 'nadeem'], + 'demeanor': ['demeanor', 'enamored'], + 'dementia': ['dementia', 'mendaite'], + 'demerit': ['demerit', 'dimeter', 'merited', 'mitered'], + 'demerol': ['demerol', 'modeler', 'remodel'], + 'demetrian': ['demetrian', 'dermatine', 'meandrite', 'minareted'], + 'demi': ['demi', 'diem', 'dime', 'mide'], + 'demibrute': ['bermudite', 'demibrute'], + 'demicannon': ['cinnamoned', 'demicannon'], + 'demicanon': ['demicanon', 'dominance'], + 'demidog': ['demidog', 'demigod'], + 'demigod': ['demidog', 'demigod'], + 'demiluster': ['demiluster', 'demilustre'], + 'demilustre': ['demiluster', 'demilustre'], + 'demiparallel': ['demiparallel', 'imparalleled'], + 'demipronation': ['demipronation', 'preadmonition', 'predomination'], + 'demiracle': ['declaimer', 'demiracle'], + 'demiram': ['demiram', 'mermaid'], + 'demirep': ['demirep', 'epiderm', 'impeder', 'remiped'], + 'demirobe': ['demirobe', 'embodier'], + 'demisable': ['beadleism', 'demisable'], + 'demise': ['demise', 'diseme'], + 'demit': ['demit', 'timed'], + 'demiturned': ['demiturned', 'undertimed'], + 'demob': ['demob', 'mobed'], + 'democratian': ['demarcation', 'democratian'], + 'demolisher': ['demolisher', 'redemolish'], + 'demoniac': ['codamine', 'comedian', 'daemonic', 'demoniac'], + 'demoniacism': ['demoniacism', 'seminomadic'], + 'demonial': ['demonial', 'melanoid'], + 'demoniast': ['ademonist', 'demoniast', 'staminode'], + 'demonish': ['demonish', 'hedonism'], + 'demonism': ['demonism', 'medimnos', 'misnomed'], + 'demotics': ['comedist', 'demotics', 'docetism', 'domestic'], + 'demotion': ['demotion', 'entomoid', 'moontide'], + 'demount': ['demount', 'mounted'], + 'demurrer': ['demurrer', 'murderer'], + 'demurring': ['demurring', 'murdering'], + 'demurringly': ['demurringly', 'murderingly'], + 'demy': ['demy', 'emyd'], + 'den': ['den', 'end', 'ned'], + 'denarius': ['denarius', 'desaurin', 'unraised'], + 'denaro': ['denaro', 'orenda'], + 'denary': ['denary', 'yander'], + 'denat': ['denat', 'entad'], + 'denature': ['denature', 'undereat'], + 'denda': ['dedan', 'denda'], + 'dendral': ['dandler', 'dendral'], + 'dendrite': ['dendrite', 'tindered'], + 'dendrites': ['dendrites', 'distender', 'redistend'], + 'dene': ['dene', 'eden', 'need'], + 'deneb': ['beden', 'deben', 'deneb'], + 'dengue': ['dengue', 'unedge'], + 'denial': ['aldine', 'daniel', 'delian', 'denial', 'enalid', 'leadin'], + 'denier': ['denier', 'nereid'], + 'denierer': ['denierer', 'reindeer'], + 'denigrate': ['argentide', 'denigrate', 'dinergate'], + 'denim': ['denim', 'mendi'], + 'denis': ['denis', 'snide'], + 'denominate': ['denominate', 'emendation'], + 'denotable': ['denotable', 'detonable'], + 'denotation': ['denotation', 'detonation'], + 'denotative': ['denotative', 'detonative'], + 'denotive': ['denotive', 'devonite'], + 'denouncer': ['denouncer', 'unencored'], + 'dense': ['dense', 'needs'], + 'denshare': ['denshare', 'seerhand'], + 'denshire': ['denshire', 'drisheen'], + 'density': ['density', 'destiny'], + 'dent': ['dent', 'tend'], + 'dental': ['dental', 'tandle'], + 'dentale': ['dalteen', 'dentale', 'edental'], + 'dentalism': ['dentalism', 'dismantle'], + 'dentaria': ['anteriad', 'atridean', 'dentaria'], + 'dentatoserrate': ['dentatoserrate', 'serratodentate'], + 'dentatosinuate': ['dentatosinuate', 'sinuatodentate'], + 'denter': ['denter', 'rented', 'tender'], + 'dentex': ['dentex', 'extend'], + 'denticle': ['cliented', 'denticle'], + 'denticular': ['denticular', 'unarticled'], + 'dentil': ['delint', 'dentil'], + 'dentilingual': ['dentilingual', 'indulgential', 'linguidental'], + 'dentin': ['dentin', 'indent', 'intend', 'tinned'], + 'dentinal': ['dentinal', 'teinland', 'tendinal'], + 'dentine': ['dentine', 'nineted'], + 'dentinitis': ['dentinitis', 'tendinitis'], + 'dentinoma': ['dentinoma', 'nominated'], + 'dentist': ['dentist', 'distent', 'stinted'], + 'dentolabial': ['dentolabial', 'labiodental'], + 'dentolingual': ['dentolingual', 'linguodental'], + 'denture': ['denture', 'untreed'], + 'denudative': ['denudative', 'undeviated'], + 'denude': ['denude', 'dudeen'], + 'denumeral': ['denumeral', 'undermeal', 'unrealmed'], + 'denunciator': ['denunciator', 'underaction'], + 'deny': ['deny', 'dyne'], + 'deoppilant': ['deoppilant', 'pentaploid'], + 'deota': ['deota', 'todea'], + 'depa': ['depa', 'peda'], + 'depaint': ['depaint', 'inadept', 'painted', 'patined'], + 'depart': ['depart', 'parted', 'petard'], + 'departition': ['departition', 'partitioned', 'trepidation'], + 'departure': ['apertured', 'departure'], + 'depas': ['depas', 'sepad', 'spade'], + 'depencil': ['depencil', 'penciled', 'pendicle'], + 'depender': ['depender', 'redepend'], + 'depetticoat': ['depetticoat', 'petticoated'], + 'depicter': ['decrepit', 'depicter', 'precited'], + 'depiction': ['depiction', 'pectinoid'], + 'depilate': ['depilate', 'leptidae', 'pileated'], + 'depletion': ['depletion', 'diplotene'], + 'deploration': ['deploration', 'periodontal'], + 'deploy': ['deploy', 'podley'], + 'depoh': ['depoh', 'ephod', 'hoped'], + 'depolish': ['depolish', 'polished'], + 'deport': ['deport', 'ported', 'redtop'], + 'deportation': ['antitorpedo', 'deportation'], + 'deposal': ['adelops', 'deposal'], + 'deposer': ['deposer', 'reposed'], + 'deposit': ['deposit', 'topside'], + 'deposition': ['deposition', 'positioned'], + 'depositional': ['depositional', 'despoliation'], + 'depositure': ['depositure', 'pterideous'], + 'deprave': ['deprave', 'pervade'], + 'depraver': ['depraver', 'pervader'], + 'depravingly': ['depravingly', 'pervadingly'], + 'deprecable': ['deprecable', 'precedable'], + 'deprecation': ['capernoited', 'deprecation'], + 'depreciation': ['depreciation', 'predeication'], + 'depressant': ['depressant', 'partedness'], + 'deprint': ['deprint', 'printed'], + 'deprival': ['deprival', 'prevalid'], + 'deprivate': ['deprivate', 'predative'], + 'deprive': ['deprive', 'previde'], + 'depriver': ['depriver', 'predrive'], + 'depurant': ['depurant', 'unparted'], + 'depuration': ['depuration', 'portunidae'], + 'deraign': ['degrain', 'deraign', 'deringa', 'gradine', 'grained', 'reading'], + 'derail': ['ariled', 'derail', 'dialer'], + 'derailment': ['delirament', 'derailment'], + 'derange': ['derange', 'enraged', 'gardeen', 'gerenda', 'grandee', 'grenade'], + 'deranged': ['deranged', 'gardened'], + 'deranger': ['deranger', 'gardener'], + 'derat': ['dater', 'derat', 'detar', 'drate', 'rated', 'trade', 'tread'], + 'derate': ['derate', 'redate'], + 'derater': ['derater', 'retrade', 'retread', 'treader'], + 'deray': ['deary', 'deray', 'rayed', 'ready', 'yeard'], + 'dere': ['deer', 'dere', 'dree', 'rede', 'reed'], + 'deregister': ['deregister', 'registered'], + 'derelict': ['derelict', 'relicted'], + 'deric': ['cider', 'cried', 'deric', 'dicer'], + 'derider': ['deirdre', 'derider', 'derride', 'ridered'], + 'deringa': ['degrain', 'deraign', 'deringa', 'gradine', 'grained', 'reading'], + 'derision': ['derision', 'ironside', 'resinoid', 'sirenoid'], + 'derivation': ['derivation', 'ordinative'], + 'derivational': ['derivational', 'revalidation'], + 'derive': ['derive', 'redive'], + 'deriver': ['deriver', 'redrive', 'rivered'], + 'derma': ['armed', 'derma', 'dream', 'ramed'], + 'dermad': ['dermad', 'madder'], + 'dermal': ['dermal', 'marled', 'medlar'], + 'dermatic': ['dermatic', 'timecard'], + 'dermatine': ['demetrian', 'dermatine', 'meandrite', 'minareted'], + 'dermatoneurosis': ['dermatoneurosis', 'neurodermatosis'], + 'dermatophone': ['dermatophone', 'herpetomonad'], + 'dermoblast': ['blastoderm', 'dermoblast'], + 'dermol': ['dermol', 'molder', 'remold'], + 'dermosclerite': ['dermosclerite', 'sclerodermite'], + 'dern': ['dern', 'rend'], + 'derogately': ['delegatory', 'derogately'], + 'derogation': ['derogation', 'trogonidae'], + 'derout': ['derout', 'detour', 'douter'], + 'derride': ['deirdre', 'derider', 'derride', 'ridered'], + 'derries': ['derries', 'desirer', 'resider', 'serried'], + 'derringer': ['derringer', 'regrinder'], + 'derry': ['derry', 'redry', 'ryder'], + 'derust': ['derust', 'duster'], + 'desalt': ['desalt', 'salted'], + 'desand': ['desand', 'sadden', 'sanded'], + 'desaurin': ['denarius', 'desaurin', 'unraised'], + 'descendant': ['adscendent', 'descendant'], + 'descender': ['descender', 'redescend'], + 'descent': ['descent', 'scented'], + 'description': ['description', 'discerption'], + 'desecrate': ['decastere', 'desecrate'], + 'desecration': ['considerate', 'desecration'], + 'deseed': ['deseed', 'seeded'], + 'desertic': ['creedist', 'desertic', 'discreet', 'discrete'], + 'desertion': ['desertion', 'detersion'], + 'deserver': ['deserver', 'reserved', 'reversed'], + 'desex': ['desex', 'sexed'], + 'deshabille': ['deshabille', 'shieldable'], + 'desi': ['desi', 'ides', 'seid', 'side'], + 'desiccation': ['desiccation', 'discoactine'], + 'desight': ['desight', 'sighted'], + 'design': ['design', 'singed'], + 'designer': ['designer', 'redesign', 'resigned'], + 'desilver': ['desilver', 'silvered'], + 'desirable': ['desirable', 'redisable'], + 'desire': ['desire', 'reside'], + 'desirer': ['derries', 'desirer', 'resider', 'serried'], + 'desirous': ['desirous', 'siderous'], + 'desition': ['desition', 'sedition'], + 'desma': ['desma', 'mesad'], + 'desman': ['amends', 'desman'], + 'desmopathy': ['desmopathy', 'phymatodes'], + 'desorption': ['desorption', 'priodontes'], + 'despair': ['despair', 'pardesi'], + 'despairing': ['despairing', 'spinigrade'], + 'desperation': ['desperation', 'esperantido'], + 'despise': ['despise', 'pedesis'], + 'despiser': ['despiser', 'disperse'], + 'despoil': ['despoil', 'soliped', 'spoiled'], + 'despoiler': ['despoiler', 'leprosied'], + 'despoliation': ['depositional', 'despoliation'], + 'despot': ['despot', 'posted'], + 'despotat': ['despotat', 'postdate'], + 'dessert': ['dessert', 'tressed'], + 'destain': ['destain', 'instead', 'sainted', 'satined'], + 'destine': ['destine', 'edestin'], + 'destinism': ['destinism', 'timidness'], + 'destiny': ['density', 'destiny'], + 'desugar': ['desugar', 'sugared'], + 'detail': ['detail', 'dietal', 'dilate', 'edital', 'tailed'], + 'detailer': ['detailer', 'elaterid'], + 'detain': ['danite', 'detain'], + 'detainal': ['danalite', 'detainal'], + 'detar': ['dater', 'derat', 'detar', 'drate', 'rated', 'trade', 'tread'], + 'detassel': ['dateless', 'detassel'], + 'detax': ['detax', 'taxed'], + 'detecter': ['detecter', 'redetect'], + 'detent': ['detent', 'netted', 'tented'], + 'deter': ['deter', 'treed'], + 'determinant': ['determinant', 'detrainment'], + 'detersion': ['desertion', 'detersion'], + 'detest': ['detest', 'tested'], + 'dethrone': ['dethrone', 'threnode'], + 'detin': ['detin', 'teind', 'tined'], + 'detinet': ['detinet', 'dinette'], + 'detonable': ['denotable', 'detonable'], + 'detonation': ['denotation', 'detonation'], + 'detonative': ['denotative', 'detonative'], + 'detonator': ['detonator', 'tetraodon'], + 'detour': ['derout', 'detour', 'douter'], + 'detracter': ['detracter', 'retracted'], + 'detraction': ['detraction', 'doctrinate', 'tetarconid'], + 'detrain': ['antired', 'detrain', 'randite', 'trained'], + 'detrainment': ['determinant', 'detrainment'], + 'detrusion': ['detrusion', 'tinderous', 'unstoried'], + 'detrusive': ['detrusive', 'divesture', 'servitude'], + 'deuce': ['deuce', 'educe'], + 'deuced': ['deduce', 'deuced'], + 'deul': ['deul', 'duel', 'leud'], + 'deva': ['dave', 'deva', 'vade', 'veda'], + 'devance': ['devance', 'vendace'], + 'develin': ['develin', 'endevil'], + 'developer': ['developer', 'redevelop'], + 'devil': ['devil', 'divel', 'lived'], + 'deviler': ['deliver', 'deviler', 'livered'], + 'devisceration': ['considerative', 'devisceration'], + 'deviser': ['deviser', 'diverse', 'revised'], + 'devitrify': ['devitrify', 'fervidity'], + 'devoid': ['devoid', 'voided'], + 'devoir': ['devoir', 'voider'], + 'devonite': ['denotive', 'devonite'], + 'devourer': ['devourer', 'overdure', 'overrude'], + 'devow': ['devow', 'vowed'], + 'dew': ['dew', 'wed'], + 'dewan': ['awned', 'dewan', 'waned'], + 'dewater': ['dewater', 'tarweed', 'watered'], + 'dewer': ['dewer', 'ewder', 'rewed'], + 'dewey': ['dewey', 'weedy'], + 'dewily': ['dewily', 'widely', 'wieldy'], + 'dewiness': ['dewiness', 'wideness'], + 'dewool': ['dewool', 'elwood', 'wooled'], + 'deworm': ['deworm', 'wormed'], + 'dewy': ['dewy', 'wyde'], + 'dextraural': ['dextraural', 'extradural'], + 'dextrosinistral': ['dextrosinistral', 'sinistrodextral'], + 'dey': ['dey', 'dye', 'yed'], + 'deyhouse': ['deyhouse', 'dyehouse'], + 'deyship': ['deyship', 'diphyes'], + 'dezinc': ['dezinc', 'zendic'], + 'dha': ['dah', 'dha', 'had'], + 'dhamnoo': ['dhamnoo', 'hoodman', 'manhood'], + 'dhan': ['dhan', 'hand'], + 'dharna': ['andhra', 'dharna'], + 'dheri': ['dheri', 'hider', 'hired'], + 'dhobi': ['bodhi', 'dhobi'], + 'dhoon': ['dhoon', 'hondo'], + 'dhu': ['dhu', 'hud'], + 'di': ['di', 'id'], + 'diabolist': ['diabolist', 'idioblast'], + 'diacetin': ['diacetin', 'indicate'], + 'diacetine': ['deciatine', 'diacetine', 'taenicide', 'teniacide'], + 'diacetyl': ['diacetyl', 'lyctidae'], + 'diachoretic': ['citharoedic', 'diachoretic'], + 'diaclase': ['diaclase', 'sidalcea'], + 'diaconal': ['cladonia', 'condalia', 'diaconal'], + 'diact': ['diact', 'dicta'], + 'diadem': ['diadem', 'mediad'], + 'diaderm': ['admired', 'diaderm'], + 'diaeretic': ['diaeretic', 'icteridae'], + 'diagenetic': ['diagenetic', 'digenetica'], + 'diageotropism': ['diageotropism', 'geodiatropism'], + 'diagonal': ['diagonal', 'ganoidal', 'gonadial'], + 'dial': ['dail', 'dali', 'dial', 'laid', 'lida'], + 'dialect': ['citadel', 'deltaic', 'dialect', 'edictal', 'lactide'], + 'dialectic': ['deictical', 'dialectic'], + 'dialector': ['dialector', 'lacertoid'], + 'dialer': ['ariled', 'derail', 'dialer'], + 'dialin': ['anilid', 'dialin', 'dianil', 'inlaid'], + 'dialing': ['dialing', 'gliadin'], + 'dialister': ['dialister', 'trailside'], + 'diallelon': ['diallelon', 'llandeilo'], + 'dialogism': ['dialogism', 'sigmoidal'], + 'dialystelic': ['deistically', 'dialystelic'], + 'dialytic': ['calidity', 'dialytic'], + 'diamagnet': ['agminated', 'diamagnet'], + 'diamantine': ['diamantine', 'inanimated'], + 'diameter': ['diameter', 'diatreme'], + 'diametric': ['citramide', 'diametric', 'matricide'], + 'diamide': ['amidide', 'diamide', 'mididae'], + 'diamine': ['amidine', 'diamine'], + 'diamorphine': ['diamorphine', 'phronimidae'], + 'dian': ['adin', 'andi', 'dain', 'dani', 'dian', 'naid'], + 'diana': ['danai', 'diana', 'naiad'], + 'diander': ['diander', 'drained'], + 'diane': ['diane', 'idean'], + 'dianetics': ['andesitic', 'dianetics'], + 'dianil': ['anilid', 'dialin', 'dianil', 'inlaid'], + 'diapensia': ['diapensia', 'diaspinae'], + 'diaper': ['diaper', 'paired'], + 'diaphote': ['diaphote', 'hepatoid'], + 'diaphtherin': ['diaphtherin', 'diphtherian'], + 'diapnoic': ['diapnoic', 'pinacoid'], + 'diapnotic': ['antipodic', 'diapnotic'], + 'diaporthe': ['aphrodite', 'atrophied', 'diaporthe'], + 'diarch': ['chidra', 'diarch'], + 'diarchial': ['diarchial', 'rachidial'], + 'diarchy': ['diarchy', 'hyracid'], + 'diarian': ['aridian', 'diarian'], + 'diary': ['dairy', 'diary', 'yaird'], + 'diascia': ['ascidia', 'diascia'], + 'diascope': ['diascope', 'psocidae', 'scopidae'], + 'diaspinae': ['diapensia', 'diaspinae'], + 'diastem': ['diastem', 'misdate'], + 'diastema': ['adamsite', 'diastema'], + 'diaster': ['astride', 'diaster', 'disrate', 'restiad', 'staired'], + 'diastole': ['diastole', 'isolated', 'sodalite', 'solidate'], + 'diastrophic': ['aphrodistic', 'diastrophic'], + 'diastrophy': ['diastrophy', 'dystrophia'], + 'diatomales': ['diatomales', 'mastoidale', 'mastoideal'], + 'diatomean': ['diatomean', 'mantoidea'], + 'diatomin': ['diatomin', 'domitian'], + 'diatonic': ['actinoid', 'diatonic', 'naticoid'], + 'diatreme': ['diameter', 'diatreme'], + 'diatropism': ['diatropism', 'prismatoid'], + 'dib': ['bid', 'dib'], + 'dibatis': ['dabitis', 'dibatis'], + 'dibber': ['dibber', 'ribbed'], + 'dibbler': ['dibbler', 'dribble'], + 'dibrom': ['dibrom', 'morbid'], + 'dicaryon': ['cynaroid', 'dicaryon'], + 'dicast': ['dicast', 'stadic'], + 'dice': ['dice', 'iced'], + 'dicentra': ['crinated', 'dicentra'], + 'dicer': ['cider', 'cried', 'deric', 'dicer'], + 'diceras': ['diceras', 'radices', 'sidecar'], + 'dich': ['chid', 'dich'], + 'dichroite': ['dichroite', 'erichtoid', 'theriodic'], + 'dichromat': ['chromatid', 'dichromat'], + 'dichter': ['dichter', 'ditcher'], + 'dicolic': ['codicil', 'dicolic'], + 'dicolon': ['dicolon', 'dolcino'], + 'dicoumarin': ['acridonium', 'dicoumarin'], + 'dicta': ['diact', 'dicta'], + 'dictaphone': ['dictaphone', 'endopathic'], + 'dictational': ['antidotical', 'dictational'], + 'dictionary': ['dictionary', 'indicatory'], + 'dicyanine': ['cyanidine', 'dicyanine'], + 'dicycle': ['cyclide', 'decylic', 'dicycle'], + 'dicyema': ['dicyema', 'mediacy'], + 'diddle': ['diddle', 'lidded'], + 'diddler': ['diddler', 'driddle'], + 'didym': ['didym', 'middy'], + 'die': ['die', 'ide'], + 'dieb': ['beid', 'bide', 'debi', 'dieb'], + 'diego': ['diego', 'dogie', 'geoid'], + 'dielytra': ['dielytra', 'tileyard'], + 'diem': ['demi', 'diem', 'dime', 'mide'], + 'dier': ['dier', 'dire', 'reid', 'ride'], + 'diesel': ['diesel', 'sedile', 'seidel'], + 'diet': ['diet', 'dite', 'edit', 'tide', 'tied'], + 'dietal': ['detail', 'dietal', 'dilate', 'edital', 'tailed'], + 'dieter': ['dieter', 'tiered'], + 'dietic': ['citied', 'dietic'], + 'dietics': ['deistic', 'dietics'], + 'dig': ['dig', 'gid'], + 'digenetica': ['diagenetic', 'digenetica'], + 'digeny': ['digeny', 'dyeing'], + 'digester': ['digester', 'redigest'], + 'digitalein': ['digitalein', 'diligentia'], + 'digitation': ['digitation', 'goniatitid'], + 'digitonin': ['digitonin', 'indigotin'], + 'digredient': ['digredient', 'reddingite'], + 'dihalo': ['dihalo', 'haloid'], + 'diiambus': ['basidium', 'diiambus'], + 'dika': ['dika', 'kaid'], + 'dikaryon': ['ankyroid', 'dikaryon'], + 'dike': ['dike', 'keid'], + 'dilacerate': ['dilacerate', 'lacertidae'], + 'dilatant': ['atlantid', 'dilatant'], + 'dilate': ['detail', 'dietal', 'dilate', 'edital', 'tailed'], + 'dilater': ['dilater', 'lardite', 'redtail'], + 'dilatometric': ['calotermitid', 'dilatometric'], + 'dilator': ['dilator', 'ortalid'], + 'dilatory': ['adroitly', 'dilatory', 'idolatry'], + 'diligence': ['ceilinged', 'diligence'], + 'diligentia': ['digitalein', 'diligentia'], + 'dillue': ['dillue', 'illude'], + 'dilluer': ['dilluer', 'illuder'], + 'dilo': ['dilo', 'diol', 'doli', 'idol', 'olid'], + 'diluent': ['diluent', 'untiled'], + 'dilute': ['dilute', 'dultie'], + 'diluted': ['diluted', 'luddite'], + 'dilutent': ['dilutent', 'untilted', 'untitled'], + 'diluvian': ['diluvian', 'induvial'], + 'dim': ['dim', 'mid'], + 'dimatis': ['amidist', 'dimatis'], + 'dimble': ['dimble', 'limbed'], + 'dime': ['demi', 'diem', 'dime', 'mide'], + 'dimer': ['dimer', 'mider'], + 'dimera': ['admire', 'armied', 'damier', 'dimera', 'merida'], + 'dimeran': ['adermin', 'amerind', 'dimeran'], + 'dimerous': ['dimerous', 'soredium'], + 'dimeter': ['demerit', 'dimeter', 'merited', 'mitered'], + 'dimetria': ['dimetria', 'mitridae', 'tiremaid', 'triamide'], + 'diminisher': ['diminisher', 'rediminish'], + 'dimit': ['dimit', 'timid'], + 'dimmer': ['dimmer', 'immerd', 'rimmed'], + 'dimna': ['dimna', 'manid'], + 'dimyarian': ['dimyarian', 'myrianida'], + 'din': ['din', 'ind', 'nid'], + 'dinah': ['ahind', 'dinah'], + 'dinar': ['darin', 'dinar', 'drain', 'indra', 'nadir', 'ranid'], + 'dinder': ['dinder', 'ridden', 'rinded'], + 'dindle': ['dindle', 'niddle'], + 'dine': ['dine', 'enid', 'inde', 'nide'], + 'diner': ['diner', 'riden', 'rinde'], + 'dinergate': ['argentide', 'denigrate', 'dinergate'], + 'dinero': ['dinero', 'dorine'], + 'dinette': ['detinet', 'dinette'], + 'dineuric': ['dineuric', 'eurindic'], + 'dingar': ['daring', 'dingar', 'gradin'], + 'dinge': ['deign', 'dinge', 'nidge'], + 'dingle': ['dingle', 'elding', 'engild', 'gilden'], + 'dingo': ['dingo', 'doing', 'gondi', 'gonid'], + 'dingwall': ['dingwall', 'windgall'], + 'dingy': ['dingy', 'dying'], + 'dinheiro': ['dinheiro', 'hernioid'], + 'dinic': ['dinic', 'indic'], + 'dining': ['dining', 'indign', 'niding'], + 'dink': ['dink', 'kind'], + 'dinkey': ['dinkey', 'kidney'], + 'dinocerata': ['arctoidean', 'carotidean', 'cordaitean', 'dinocerata'], + 'dinoceratan': ['carnationed', 'dinoceratan'], + 'dinomic': ['dinomic', 'dominic'], + 'dint': ['dint', 'tind'], + 'dinus': ['dinus', 'indus', 'nidus'], + 'dioeciopolygamous': ['dioeciopolygamous', 'polygamodioecious'], + 'diogenite': ['diogenite', 'gideonite'], + 'diol': ['dilo', 'diol', 'doli', 'idol', 'olid'], + 'dion': ['dion', 'nodi', 'odin'], + 'dione': ['deino', 'dione', 'edoni'], + 'diopter': ['diopter', 'peridot', 'proetid', 'protide', 'pteroid'], + 'dioptra': ['dioptra', 'parotid'], + 'dioptral': ['dioptral', 'tripodal'], + 'dioptric': ['dioptric', 'tripodic'], + 'dioptrical': ['dioptrical', 'tripodical'], + 'dioptry': ['dioptry', 'tripody'], + 'diorama': ['amaroid', 'diorama'], + 'dioramic': ['dioramic', 'dromicia'], + 'dioscorein': ['dioscorein', 'dioscorine'], + 'dioscorine': ['dioscorein', 'dioscorine'], + 'dioscuri': ['dioscuri', 'sciuroid'], + 'diose': ['diose', 'idose', 'oside'], + 'diosmin': ['diosmin', 'odinism'], + 'diosmotic': ['diosmotic', 'sodomitic'], + 'diparentum': ['diparentum', 'unimparted'], + 'dipetto': ['dipetto', 'diptote'], + 'diphase': ['aphides', 'diphase'], + 'diphaser': ['diphaser', 'parished', 'raphides', 'sephardi'], + 'diphosphate': ['diphosphate', 'phosphatide'], + 'diphtherian': ['diaphtherin', 'diphtherian'], + 'diphyes': ['deyship', 'diphyes'], + 'diphysite': ['deityship', 'diphysite'], + 'dipicrate': ['dipicrate', 'patricide', 'pediatric'], + 'diplanar': ['diplanar', 'prandial'], + 'diplasion': ['aspidinol', 'diplasion'], + 'dipleura': ['dipleura', 'epidural'], + 'dipleural': ['dipleural', 'preludial'], + 'diplocephalus': ['diplocephalus', 'pseudophallic'], + 'diploe': ['diploe', 'dipole'], + 'diploetic': ['diploetic', 'lepidotic'], + 'diplotene': ['depletion', 'diplotene'], + 'dipnoan': ['dipnoan', 'nonpaid', 'pandion'], + 'dipolar': ['dipolar', 'polarid'], + 'dipole': ['diploe', 'dipole'], + 'dipsaceous': ['dipsaceous', 'spadiceous'], + 'dipter': ['dipter', 'trepid'], + 'dipteraceous': ['dipteraceous', 'epiceratodus'], + 'dipteral': ['dipteral', 'tripedal'], + 'dipterological': ['dipterological', 'pteridological'], + 'dipterologist': ['dipterologist', 'pteridologist'], + 'dipterology': ['dipterology', 'pteridology'], + 'dipteros': ['dipteros', 'portside'], + 'diptote': ['dipetto', 'diptote'], + 'dirca': ['acrid', 'caird', 'carid', 'darci', 'daric', 'dirca'], + 'dircaean': ['caridean', 'dircaean', 'radiance'], + 'dire': ['dier', 'dire', 'reid', 'ride'], + 'direct': ['credit', 'direct'], + 'directable': ['creditable', 'directable'], + 'directer': ['cedriret', 'directer', 'recredit', 'redirect'], + 'direction': ['cretinoid', 'direction'], + 'directional': ['clitoridean', 'directional'], + 'directive': ['creditive', 'directive'], + 'directly': ['directly', 'tridecyl'], + 'directoire': ['cordierite', 'directoire'], + 'director': ['creditor', 'director'], + 'directorship': ['creditorship', 'directorship'], + 'directress': ['creditress', 'directress'], + 'directrix': ['creditrix', 'directrix'], + 'direly': ['direly', 'idyler'], + 'direption': ['direption', 'perdition', 'tropidine'], + 'dirge': ['dirge', 'gride', 'redig', 'ridge'], + 'dirgelike': ['dirgelike', 'ridgelike'], + 'dirgeman': ['dirgeman', 'margined', 'midrange'], + 'dirgler': ['dirgler', 'girdler'], + 'dirten': ['dirten', 'rident', 'tinder'], + 'dis': ['dis', 'sid'], + 'disa': ['dais', 'dasi', 'disa', 'said', 'sida'], + 'disadventure': ['disadventure', 'unadvertised'], + 'disappearer': ['disappearer', 'redisappear'], + 'disarmed': ['disarmed', 'misdread'], + 'disastimeter': ['disastimeter', 'semistriated'], + 'disattire': ['disattire', 'distraite'], + 'disbud': ['disbud', 'disdub'], + 'disburse': ['disburse', 'subsider'], + 'discastle': ['clidastes', 'discastle'], + 'discern': ['discern', 'rescind'], + 'discerner': ['discerner', 'rescinder'], + 'discernment': ['discernment', 'rescindment'], + 'discerp': ['crisped', 'discerp'], + 'discerption': ['description', 'discerption'], + 'disclike': ['disclike', 'sicklied'], + 'discoactine': ['desiccation', 'discoactine'], + 'discoid': ['discoid', 'disodic'], + 'discontinuer': ['discontinuer', 'undiscretion'], + 'discounter': ['discounter', 'rediscount'], + 'discoverer': ['discoverer', 'rediscover'], + 'discreate': ['discreate', 'sericated'], + 'discreet': ['creedist', 'desertic', 'discreet', 'discrete'], + 'discreetly': ['discreetly', 'discretely'], + 'discreetness': ['discreetness', 'discreteness'], + 'discrepate': ['discrepate', 'pederastic'], + 'discrete': ['creedist', 'desertic', 'discreet', 'discrete'], + 'discretely': ['discreetly', 'discretely'], + 'discreteness': ['discreetness', 'discreteness'], + 'discretion': ['discretion', 'soricident'], + 'discriminator': ['discriminator', 'doctrinairism'], + 'disculpate': ['disculpate', 'spiculated'], + 'discusser': ['discusser', 'rediscuss'], + 'discutable': ['discutable', 'subdeltaic', 'subdialect'], + 'disdub': ['disbud', 'disdub'], + 'disease': ['disease', 'seaside'], + 'diseme': ['demise', 'diseme'], + 'disenact': ['disenact', 'distance'], + 'disendow': ['disendow', 'downside'], + 'disentwine': ['disentwine', 'indentwise'], + 'disharmony': ['disharmony', 'hydramnios'], + 'dishearten': ['dishearten', 'intershade'], + 'dished': ['dished', 'eddish'], + 'disherent': ['disherent', 'hinderest', 'tenderish'], + 'dishling': ['dishling', 'hidlings'], + 'dishonor': ['dishonor', 'ironshod'], + 'dishorn': ['dishorn', 'dronish'], + 'dishpan': ['daphnis', 'dishpan'], + 'disilicate': ['disilicate', 'idealistic'], + 'disimprove': ['disimprove', 'misprovide'], + 'disk': ['disk', 'kids', 'skid'], + 'dislocate': ['dislocate', 'lactoside'], + 'disman': ['danism', 'disman'], + 'dismantle': ['dentalism', 'dismantle'], + 'disme': ['deism', 'disme'], + 'dismemberer': ['dismemberer', 'disremember'], + 'disnature': ['disnature', 'sturnidae', 'truandise'], + 'disnest': ['disnest', 'dissent'], + 'disodic': ['discoid', 'disodic'], + 'disparage': ['disparage', 'grapsidae'], + 'disparation': ['disparation', 'tridiapason'], + 'dispatcher': ['dispatcher', 'redispatch'], + 'dispensable': ['dispensable', 'piebaldness'], + 'dispense': ['dispense', 'piedness'], + 'disperse': ['despiser', 'disperse'], + 'dispetal': ['dispetal', 'pedalist'], + 'dispireme': ['dispireme', 'epidermis'], + 'displayer': ['displayer', 'redisplay'], + 'displeaser': ['displeaser', 'pearlsides'], + 'disponee': ['disponee', 'openside'], + 'disporum': ['disporum', 'misproud'], + 'disprepare': ['disprepare', 'predespair'], + 'disrate': ['astride', 'diaster', 'disrate', 'restiad', 'staired'], + 'disremember': ['dismemberer', 'disremember'], + 'disrepute': ['disrepute', 'redispute'], + 'disrespect': ['disrespect', 'disscepter'], + 'disrupt': ['disrupt', 'prudist'], + 'disscepter': ['disrespect', 'disscepter'], + 'disseat': ['disseat', 'sestiad'], + 'dissector': ['crosstied', 'dissector'], + 'dissent': ['disnest', 'dissent'], + 'dissenter': ['dissenter', 'tiredness'], + 'dissertate': ['dissertate', 'statesider'], + 'disserve': ['disserve', 'dissever'], + 'dissever': ['disserve', 'dissever'], + 'dissocial': ['cissoidal', 'dissocial'], + 'dissolve': ['dissolve', 'voidless'], + 'dissoul': ['dissoul', 'dulosis', 'solidus'], + 'distale': ['distale', 'salited'], + 'distance': ['disenact', 'distance'], + 'distant': ['dantist', 'distant'], + 'distater': ['distater', 'striated'], + 'distender': ['dendrites', 'distender', 'redistend'], + 'distent': ['dentist', 'distent', 'stinted'], + 'distich': ['distich', 'stichid'], + 'distillage': ['distillage', 'sigillated'], + 'distiller': ['distiller', 'redistill'], + 'distinguisher': ['distinguisher', 'redistinguish'], + 'distoma': ['distoma', 'mastoid'], + 'distome': ['distome', 'modiste'], + 'distrainer': ['distrainer', 'redistrain'], + 'distrait': ['distrait', 'triadist'], + 'distraite': ['disattire', 'distraite'], + 'disturber': ['disturber', 'redisturb'], + 'disulphone': ['disulphone', 'unpolished'], + 'disuniform': ['disuniform', 'indusiform'], + 'dit': ['dit', 'tid'], + 'dita': ['adit', 'dita'], + 'dital': ['datil', 'dital', 'tidal', 'tilda'], + 'ditcher': ['dichter', 'ditcher'], + 'dite': ['diet', 'dite', 'edit', 'tide', 'tied'], + 'diter': ['diter', 'tired', 'tried'], + 'dithionic': ['chitinoid', 'dithionic'], + 'ditone': ['ditone', 'intoed'], + 'ditrochean': ['achondrite', 'ditrochean', 'ordanchite'], + 'diuranate': ['diuranate', 'untiaraed'], + 'diurna': ['danuri', 'diurna', 'dunair', 'durain', 'durani', 'durian'], + 'diurnation': ['diurnation', 'induration'], + 'diurne': ['diurne', 'inured', 'ruined', 'unride'], + 'diva': ['avid', 'diva'], + 'divan': ['divan', 'viand'], + 'divata': ['divata', 'dvaita'], + 'divel': ['devil', 'divel', 'lived'], + 'diver': ['diver', 'drive'], + 'diverge': ['diverge', 'grieved'], + 'diverse': ['deviser', 'diverse', 'revised'], + 'diverter': ['diverter', 'redivert', 'verditer'], + 'divest': ['divest', 'vedist'], + 'divesture': ['detrusive', 'divesture', 'servitude'], + 'divisionism': ['divisionism', 'misdivision'], + 'divorce': ['cervoid', 'divorce'], + 'divorcee': ['coderive', 'divorcee'], + 'do': ['do', 'od'], + 'doable': ['albedo', 'doable'], + 'doarium': ['doarium', 'uramido'], + 'doat': ['doat', 'toad', 'toda'], + 'doater': ['doater', 'toader'], + 'doating': ['antigod', 'doating'], + 'doatish': ['doatish', 'toadish'], + 'dob': ['bod', 'dob'], + 'dobe': ['bode', 'dobe'], + 'dobra': ['abord', 'bardo', 'board', 'broad', 'dobra', 'dorab'], + 'dobrao': ['dobrao', 'doorba'], + 'doby': ['body', 'boyd', 'doby'], + 'doc': ['cod', 'doc'], + 'docetism': ['comedist', 'demotics', 'docetism', 'domestic'], + 'docile': ['cleoid', 'coiled', 'docile'], + 'docity': ['cytoid', 'docity'], + 'docker': ['corked', 'docker', 'redock'], + 'doctorial': ['crotaloid', 'doctorial'], + 'doctorship': ['doctorship', 'trophodisc'], + 'doctrinairism': ['discriminator', 'doctrinairism'], + 'doctrinate': ['detraction', 'doctrinate', 'tetarconid'], + 'doctrine': ['centroid', 'doctrine'], + 'documental': ['columnated', 'documental'], + 'dod': ['dod', 'odd'], + 'dode': ['dedo', 'dode', 'eddo'], + 'dodecarch': ['decachord', 'dodecarch'], + 'dodlet': ['dodlet', 'toddle'], + 'dodman': ['dodman', 'oddman'], + 'doe': ['doe', 'edo', 'ode'], + 'doeg': ['doeg', 'doge', 'gode'], + 'doer': ['doer', 'redo', 'rode', 'roed'], + 'does': ['does', 'dose'], + 'doesnt': ['doesnt', 'stoned'], + 'dog': ['dog', 'god'], + 'dogate': ['dogate', 'dotage', 'togaed'], + 'dogbane': ['bondage', 'dogbane'], + 'dogbite': ['bigoted', 'dogbite'], + 'doge': ['doeg', 'doge', 'gode'], + 'dogger': ['dogger', 'gorged'], + 'doghead': ['doghead', 'godhead'], + 'doghood': ['doghood', 'godhood'], + 'dogie': ['diego', 'dogie', 'geoid'], + 'dogless': ['dogless', 'glossed', 'godless'], + 'doglike': ['doglike', 'godlike'], + 'dogly': ['dogly', 'godly', 'goldy'], + 'dogra': ['dargo', 'dogra', 'drago'], + 'dogship': ['dogship', 'godship'], + 'dogstone': ['dogstone', 'stegodon'], + 'dogwatch': ['dogwatch', 'watchdog'], + 'doina': ['adion', 'danio', 'doina', 'donia'], + 'doing': ['dingo', 'doing', 'gondi', 'gonid'], + 'doko': ['doko', 'dook'], + 'dol': ['dol', 'lod', 'old'], + 'dola': ['alod', 'dola', 'load', 'odal'], + 'dolcian': ['dolcian', 'nodical'], + 'dolciano': ['conoidal', 'dolciano'], + 'dolcino': ['dicolon', 'dolcino'], + 'dole': ['dole', 'elod', 'lode', 'odel'], + 'dolesman': ['dolesman', 'lodesman'], + 'doless': ['doless', 'dossel'], + 'doli': ['dilo', 'diol', 'doli', 'idol', 'olid'], + 'dolia': ['aloid', 'dolia', 'idola'], + 'dolina': ['dolina', 'ladino'], + 'doline': ['doline', 'indole', 'leonid', 'loined', 'olenid'], + 'dolium': ['dolium', 'idolum'], + 'dolly': ['dolly', 'lloyd'], + 'dolman': ['almond', 'dolman'], + 'dolor': ['dolor', 'drool'], + 'dolose': ['dolose', 'oodles', 'soodle'], + 'dolphin': ['dolphin', 'pinhold'], + 'dolt': ['dolt', 'told'], + 'dom': ['dom', 'mod'], + 'domain': ['amidon', 'daimon', 'domain'], + 'domainal': ['domainal', 'domanial'], + 'domal': ['domal', 'modal'], + 'domanial': ['domainal', 'domanial'], + 'dome': ['dome', 'mode', 'moed'], + 'domer': ['domer', 'drome'], + 'domestic': ['comedist', 'demotics', 'docetism', 'domestic'], + 'domic': ['comid', 'domic'], + 'domical': ['domical', 'lacmoid'], + 'dominance': ['demicanon', 'dominance'], + 'dominate': ['dominate', 'nematoid'], + 'dominated': ['demantoid', 'dominated'], + 'domination': ['admonition', 'domination'], + 'dominative': ['admonitive', 'dominative'], + 'dominator': ['admonitor', 'dominator'], + 'domine': ['domine', 'domnei', 'emodin', 'medino'], + 'dominial': ['dominial', 'imolinda', 'limoniad'], + 'dominic': ['dinomic', 'dominic'], + 'domino': ['domino', 'monoid'], + 'domitian': ['diatomin', 'domitian'], + 'domnei': ['domine', 'domnei', 'emodin', 'medino'], + 'don': ['don', 'nod'], + 'donal': ['donal', 'nodal'], + 'donar': ['adorn', 'donar', 'drona', 'radon'], + 'donated': ['donated', 'nodated'], + 'donatiaceae': ['actaeonidae', 'donatiaceae'], + 'donatism': ['donatism', 'saintdom'], + 'donator': ['donator', 'odorant', 'tornado'], + 'done': ['done', 'node'], + 'donet': ['donet', 'noted', 'toned'], + 'dong': ['dong', 'gond'], + 'donga': ['donga', 'gonad'], + 'dongola': ['dongola', 'gondola'], + 'dongon': ['dongon', 'nongod'], + 'donia': ['adion', 'danio', 'doina', 'donia'], + 'donna': ['donna', 'nonda'], + 'donnert': ['donnert', 'tendron'], + 'donnie': ['donnie', 'indone', 'ondine'], + 'donor': ['donor', 'rondo'], + 'donorship': ['donorship', 'rhodopsin'], + 'donsie': ['deinos', 'donsie', 'inodes', 'onside'], + 'donum': ['donum', 'mound'], + 'doob': ['bodo', 'bood', 'doob'], + 'dook': ['doko', 'dook'], + 'dool': ['dool', 'lood'], + 'dooli': ['dooli', 'iodol'], + 'doom': ['doom', 'mood'], + 'doomer': ['doomer', 'mooder', 'redoom', 'roomed'], + 'dooms': ['dooms', 'sodom'], + 'door': ['door', 'odor', 'oord', 'rood'], + 'doorba': ['dobrao', 'doorba'], + 'doorbell': ['bordello', 'doorbell'], + 'doored': ['doored', 'odored'], + 'doorframe': ['doorframe', 'reformado'], + 'doorless': ['doorless', 'odorless'], + 'doorplate': ['doorplate', 'leptodora'], + 'doorpost': ['doorpost', 'doorstop'], + 'doorstone': ['doorstone', 'roodstone'], + 'doorstop': ['doorpost', 'doorstop'], + 'doorweed': ['deerwood', 'doorweed'], + 'dop': ['dop', 'pod'], + 'dopa': ['apod', 'dopa'], + 'doper': ['doper', 'pedro', 'pored'], + 'dopplerite': ['dopplerite', 'lepidopter'], + 'dor': ['dor', 'rod'], + 'dora': ['dora', 'orad', 'road'], + 'dorab': ['abord', 'bardo', 'board', 'broad', 'dobra', 'dorab'], + 'doree': ['doree', 'erode'], + 'dori': ['dori', 'roid'], + 'doria': ['aroid', 'doria', 'radio'], + 'dorian': ['dorian', 'inroad', 'ordain'], + 'dorical': ['cordial', 'dorical'], + 'dorine': ['dinero', 'dorine'], + 'dorlach': ['chordal', 'dorlach'], + 'dormancy': ['dormancy', 'mordancy'], + 'dormant': ['dormant', 'mordant'], + 'dormer': ['dormer', 'remord'], + 'dormie': ['dormie', 'moider'], + 'dorn': ['dorn', 'rond'], + 'dornic': ['dornic', 'nordic'], + 'dorothea': ['dorothea', 'theodora'], + 'dorp': ['dorp', 'drop', 'prod'], + 'dorsel': ['dorsel', 'seldor', 'solder'], + 'dorsoapical': ['dorsoapical', 'prosodiacal'], + 'dorsocaudal': ['caudodorsal', 'dorsocaudal'], + 'dorsocentral': ['centrodorsal', 'dorsocentral'], + 'dorsocervical': ['cervicodorsal', 'dorsocervical'], + 'dorsolateral': ['dorsolateral', 'laterodorsal'], + 'dorsomedial': ['dorsomedial', 'mediodorsal'], + 'dorsosacral': ['dorsosacral', 'sacrodorsal'], + 'dorsoventrad': ['dorsoventrad', 'ventrodorsad'], + 'dorsoventral': ['dorsoventral', 'ventrodorsal'], + 'dorsoventrally': ['dorsoventrally', 'ventrodorsally'], + 'dos': ['dos', 'ods', 'sod'], + 'dosa': ['dosa', 'sado', 'soda'], + 'dosage': ['dosage', 'seadog'], + 'dose': ['does', 'dose'], + 'doser': ['doser', 'rosed'], + 'dosimetric': ['dosimetric', 'mediocrist'], + 'dossel': ['doless', 'dossel'], + 'dosser': ['dosser', 'sordes'], + 'dot': ['dot', 'tod'], + 'dotage': ['dogate', 'dotage', 'togaed'], + 'dote': ['dote', 'tode', 'toed'], + 'doter': ['doter', 'tored', 'trode'], + 'doty': ['doty', 'tody'], + 'doubler': ['boulder', 'doubler'], + 'doubter': ['doubter', 'obtrude', 'outbred', 'redoubt'], + 'douc': ['douc', 'duco'], + 'douce': ['coude', 'douce'], + 'doum': ['doum', 'moud', 'odum'], + 'doup': ['doup', 'updo'], + 'dour': ['dour', 'duro', 'ordu', 'roud'], + 'dourine': ['dourine', 'neuroid'], + 'dourly': ['dourly', 'lourdy'], + 'douser': ['douser', 'soured'], + 'douter': ['derout', 'detour', 'douter'], + 'dover': ['dover', 'drove', 'vedro'], + 'dow': ['dow', 'owd', 'wod'], + 'dowager': ['dowager', 'wordage'], + 'dower': ['dower', 'rowed'], + 'dowl': ['dowl', 'wold'], + 'dowlas': ['dowlas', 'oswald'], + 'downbear': ['downbear', 'rawboned'], + 'downcome': ['comedown', 'downcome'], + 'downer': ['downer', 'wonder', 'worden'], + 'downingia': ['downingia', 'godwinian'], + 'downset': ['downset', 'setdown'], + 'downside': ['disendow', 'downside'], + 'downtake': ['downtake', 'takedown'], + 'downthrow': ['downthrow', 'throwdown'], + 'downturn': ['downturn', 'turndown'], + 'downward': ['downward', 'drawdown'], + 'dowry': ['dowry', 'rowdy', 'wordy'], + 'dowser': ['dowser', 'drowse'], + 'doxa': ['doxa', 'odax'], + 'doyle': ['doyle', 'yodel'], + 'dozen': ['dozen', 'zoned'], + 'drab': ['bard', 'brad', 'drab'], + 'draba': ['barad', 'draba'], + 'drabble': ['dabbler', 'drabble'], + 'draco': ['cardo', 'draco'], + 'draconic': ['cancroid', 'draconic'], + 'draconis': ['draconis', 'sardonic'], + 'dracontian': ['dracontian', 'octandrian'], + 'drafter': ['drafter', 'redraft'], + 'drag': ['darg', 'drag', 'grad'], + 'draggle': ['draggle', 'raggled'], + 'dragline': ['dragline', 'reginald', 'ringlead'], + 'dragman': ['dragman', 'grandam', 'grandma'], + 'drago': ['dargo', 'dogra', 'drago'], + 'dragoman': ['dragoman', 'garamond', 'ondagram'], + 'dragonize': ['dragonize', 'organized'], + 'dragoon': ['dragoon', 'gadroon'], + 'dragoonage': ['dragoonage', 'gadroonage'], + 'dragsman': ['dargsman', 'dragsman'], + 'drail': ['drail', 'laird', 'larid', 'liard'], + 'drain': ['darin', 'dinar', 'drain', 'indra', 'nadir', 'ranid'], + 'drainable': ['albardine', 'drainable'], + 'drainage': ['drainage', 'gardenia'], + 'draine': ['darien', 'draine'], + 'drained': ['diander', 'drained'], + 'drainer': ['darrein', 'drainer'], + 'drainman': ['drainman', 'mandarin'], + 'draintile': ['deliriant', 'draintile', 'interlaid'], + 'drake': ['daker', 'drake', 'kedar', 'radek'], + 'dramme': ['dammer', 'dramme'], + 'drang': ['drang', 'grand'], + 'drape': ['drape', 'padre'], + 'drat': ['dart', 'drat'], + 'drate': ['dater', 'derat', 'detar', 'drate', 'rated', 'trade', 'tread'], + 'draw': ['draw', 'ward'], + 'drawable': ['drawable', 'wardable'], + 'drawback': ['backward', 'drawback'], + 'drawbore': ['drawbore', 'wardrobe'], + 'drawbridge': ['bridgeward', 'drawbridge'], + 'drawdown': ['downward', 'drawdown'], + 'drawee': ['drawee', 'rewade'], + 'drawer': ['drawer', 'redraw', 'reward', 'warder'], + 'drawers': ['drawers', 'resward'], + 'drawfile': ['drawfile', 'lifeward'], + 'drawgate': ['drawgate', 'gateward'], + 'drawhead': ['drawhead', 'headward'], + 'drawhorse': ['drawhorse', 'shoreward'], + 'drawing': ['drawing', 'ginward', 'warding'], + 'drawoff': ['drawoff', 'offward'], + 'drawout': ['drawout', 'outdraw', 'outward'], + 'drawsheet': ['drawsheet', 'watershed'], + 'drawstop': ['drawstop', 'postward'], + 'dray': ['adry', 'dray', 'yard'], + 'drayage': ['drayage', 'yardage'], + 'drayman': ['drayman', 'yardman'], + 'dread': ['adder', 'dread', 'readd'], + 'dreadly': ['dreadly', 'laddery'], + 'dream': ['armed', 'derma', 'dream', 'ramed'], + 'dreamage': ['dreamage', 'redamage'], + 'dreamer': ['dreamer', 'redream'], + 'dreamhole': ['dreamhole', 'heloderma'], + 'dreamish': ['dreamish', 'semihard'], + 'dreamland': ['dreamland', 'raddleman'], + 'drear': ['darer', 'drear'], + 'dreary': ['dreary', 'yarder'], + 'dredge': ['dredge', 'gedder'], + 'dree': ['deer', 'dere', 'dree', 'rede', 'reed'], + 'dreiling': ['dreiling', 'gridelin'], + 'dressage': ['degasser', 'dressage'], + 'dresser': ['dresser', 'redress'], + 'drib': ['bird', 'drib'], + 'dribble': ['dibbler', 'dribble'], + 'driblet': ['birdlet', 'driblet'], + 'driddle': ['diddler', 'driddle'], + 'drier': ['drier', 'rider'], + 'driest': ['driest', 'stride'], + 'driller': ['driller', 'redrill'], + 'drillman': ['drillman', 'mandrill'], + 'dringle': ['dringle', 'grindle'], + 'drisheen': ['denshire', 'drisheen'], + 'drive': ['diver', 'drive'], + 'driven': ['driven', 'nervid', 'verdin'], + 'drivescrew': ['drivescrew', 'screwdrive'], + 'drogue': ['drogue', 'gourde'], + 'drolly': ['drolly', 'lordly'], + 'drome': ['domer', 'drome'], + 'dromicia': ['dioramic', 'dromicia'], + 'drona': ['adorn', 'donar', 'drona', 'radon'], + 'drone': ['drone', 'ronde'], + 'drongo': ['drongo', 'gordon'], + 'dronish': ['dishorn', 'dronish'], + 'drool': ['dolor', 'drool'], + 'drop': ['dorp', 'drop', 'prod'], + 'dropsy': ['dropsy', 'dryops'], + 'drossel': ['drossel', 'rodless'], + 'drove': ['dover', 'drove', 'vedro'], + 'drow': ['drow', 'word'], + 'drowse': ['dowser', 'drowse'], + 'drub': ['burd', 'drub'], + 'drugger': ['drugger', 'grudger'], + 'druggery': ['druggery', 'grudgery'], + 'drungar': ['drungar', 'gurnard'], + 'drupe': ['drupe', 'duper', 'perdu', 'prude', 'pured'], + 'drusean': ['asunder', 'drusean'], + 'dryops': ['dropsy', 'dryops'], + 'duad': ['addu', 'dadu', 'daud', 'duad'], + 'dual': ['auld', 'dual', 'laud', 'udal'], + 'duali': ['duali', 'dulia'], + 'dualin': ['dualin', 'ludian', 'unlaid'], + 'dualism': ['dualism', 'laudism'], + 'dualist': ['dualist', 'laudist'], + 'dub': ['bud', 'dub'], + 'dubber': ['dubber', 'rubbed'], + 'dubious': ['biduous', 'dubious'], + 'dubitate': ['dubitate', 'tabitude'], + 'ducal': ['cauld', 'ducal'], + 'duces': ['decus', 'duces'], + 'duckstone': ['duckstone', 'unstocked'], + 'duco': ['douc', 'duco'], + 'ducted': ['deduct', 'ducted'], + 'duction': ['conduit', 'duction', 'noctuid'], + 'duculinae': ['duculinae', 'nuculidae'], + 'dudeen': ['denude', 'dudeen'], + 'dudler': ['dudler', 'ruddle'], + 'duel': ['deul', 'duel', 'leud'], + 'dueler': ['dueler', 'eluder'], + 'dueling': ['dueling', 'indulge'], + 'duello': ['deloul', 'duello'], + 'duenna': ['duenna', 'undean'], + 'duer': ['duer', 'dure', 'rude', 'urde'], + 'duffer': ['duffer', 'ruffed'], + 'dufter': ['dufter', 'turfed'], + 'dug': ['dug', 'gud'], + 'duim': ['duim', 'muid'], + 'dukery': ['dukery', 'duyker'], + 'dulat': ['adult', 'dulat'], + 'dulcian': ['dulcian', 'incudal', 'lucanid', 'lucinda'], + 'dulciana': ['claudian', 'dulciana'], + 'duler': ['duler', 'urled'], + 'dulia': ['duali', 'dulia'], + 'dullify': ['dullify', 'fluidly'], + 'dulosis': ['dissoul', 'dulosis', 'solidus'], + 'dulseman': ['dulseman', 'unalmsed'], + 'dultie': ['dilute', 'dultie'], + 'dum': ['dum', 'mud'], + 'duma': ['duma', 'maud'], + 'dumaist': ['dumaist', 'stadium'], + 'dumontite': ['dumontite', 'unomitted'], + 'dumple': ['dumple', 'plumed'], + 'dunair': ['danuri', 'diurna', 'dunair', 'durain', 'durani', 'durian'], + 'dunal': ['dunal', 'laund', 'lunda', 'ulnad'], + 'dunderpate': ['dunderpate', 'undeparted'], + 'dune': ['dune', 'nude', 'unde'], + 'dungaree': ['dungaree', 'guardeen', 'unagreed', 'underage', 'ungeared'], + 'dungeon': ['dungeon', 'negundo'], + 'dunger': ['dunger', 'gerund', 'greund', 'nudger'], + 'dungol': ['dungol', 'ungold'], + 'dungy': ['dungy', 'gundy'], + 'dunite': ['dunite', 'united', 'untied'], + 'dunlap': ['dunlap', 'upland'], + 'dunne': ['dunne', 'unden'], + 'dunner': ['dunner', 'undern'], + 'dunpickle': ['dunpickle', 'unpickled'], + 'dunstable': ['dunstable', 'unblasted', 'unstabled'], + 'dunt': ['dunt', 'tund'], + 'duny': ['duny', 'undy'], + 'duo': ['duo', 'udo'], + 'duodenal': ['duodenal', 'unloaded'], + 'duodenocholecystostomy': ['cholecystoduodenostomy', 'duodenocholecystostomy'], + 'duodenojejunal': ['duodenojejunal', 'jejunoduodenal'], + 'duodenopancreatectomy': ['duodenopancreatectomy', 'pancreatoduodenectomy'], + 'dup': ['dup', 'pud'], + 'duper': ['drupe', 'duper', 'perdu', 'prude', 'pured'], + 'dupion': ['dupion', 'unipod'], + 'dupla': ['dupla', 'plaud'], + 'duplone': ['duplone', 'unpoled'], + 'dura': ['ardu', 'daur', 'dura'], + 'durain': ['danuri', 'diurna', 'dunair', 'durain', 'durani', 'durian'], + 'duramen': ['duramen', 'maunder', 'unarmed'], + 'durance': ['durance', 'redunca', 'unraced'], + 'durango': ['aground', 'durango'], + 'durani': ['danuri', 'diurna', 'dunair', 'durain', 'durani', 'durian'], + 'durant': ['durant', 'tundra'], + 'durban': ['durban', 'undrab'], + 'durdenite': ['durdenite', 'undertide'], + 'dure': ['duer', 'dure', 'rude', 'urde'], + 'durene': ['durene', 'endure'], + 'durenol': ['durenol', 'lounder', 'roundel'], + 'durgan': ['durgan', 'undrag'], + 'durian': ['danuri', 'diurna', 'dunair', 'durain', 'durani', 'durian'], + 'during': ['during', 'ungird'], + 'durity': ['durity', 'rudity'], + 'durmast': ['durmast', 'mustard'], + 'duro': ['dour', 'duro', 'ordu', 'roud'], + 'dusken': ['dusken', 'sundek'], + 'dust': ['dust', 'stud'], + 'duster': ['derust', 'duster'], + 'dustin': ['dustin', 'nudist'], + 'dustpan': ['dustpan', 'upstand'], + 'dusty': ['dusty', 'study'], + 'duyker': ['dukery', 'duyker'], + 'dvaita': ['divata', 'dvaita'], + 'dwale': ['dwale', 'waled', 'weald'], + 'dwine': ['dwine', 'edwin', 'wendi', 'widen', 'wined'], + 'dyad': ['addy', 'dyad'], + 'dyas': ['days', 'dyas'], + 'dye': ['dey', 'dye', 'yed'], + 'dyehouse': ['deyhouse', 'dyehouse'], + 'dyeing': ['digeny', 'dyeing'], + 'dyer': ['dyer', 'yerd'], + 'dying': ['dingy', 'dying'], + 'dynamo': ['dynamo', 'monday'], + 'dynamoelectric': ['dynamoelectric', 'electrodynamic'], + 'dynamoelectrical': ['dynamoelectrical', 'electrodynamical'], + 'dynamotor': ['androtomy', 'dynamotor'], + 'dyne': ['deny', 'dyne'], + 'dyophone': ['dyophone', 'honeypod'], + 'dysluite': ['dysluite', 'sedulity'], + 'dysneuria': ['dasyurine', 'dysneuria'], + 'dysphoric': ['chrysopid', 'dysphoric'], + 'dysphrenia': ['dysphrenia', 'sphyraenid', 'sphyrnidae'], + 'dystome': ['dystome', 'modesty'], + 'dystrophia': ['diastrophy', 'dystrophia'], + 'ea': ['ae', 'ea'], + 'each': ['ache', 'each', 'haec'], + 'eager': ['agree', 'eager', 'eagre'], + 'eagle': ['aegle', 'eagle', 'galee'], + 'eagless': ['ageless', 'eagless'], + 'eaglet': ['eaglet', 'legate', 'teagle', 'telega'], + 'eagre': ['agree', 'eager', 'eagre'], + 'ean': ['ean', 'nae', 'nea'], + 'ear': ['aer', 'are', 'ear', 'era', 'rea'], + 'eared': ['eared', 'erade'], + 'earful': ['earful', 'farleu', 'ferula'], + 'earing': ['arenig', 'earing', 'gainer', 'reagin', 'regain'], + 'earl': ['earl', 'eral', 'lear', 'real'], + 'earlap': ['earlap', 'parale'], + 'earle': ['areel', 'earle'], + 'earlet': ['earlet', 'elater', 'relate'], + 'earliness': ['earliness', 'naileress'], + 'earlship': ['earlship', 'pearlish'], + 'early': ['early', 'layer', 'relay'], + 'earn': ['arne', 'earn', 'rane'], + 'earner': ['earner', 'ranere'], + 'earnest': ['earnest', 'eastern', 'nearest'], + 'earnestly': ['earnestly', 'easternly'], + 'earnful': ['earnful', 'funeral'], + 'earning': ['earning', 'engrain'], + 'earplug': ['earplug', 'graupel', 'plaguer'], + 'earring': ['earring', 'grainer'], + 'earringed': ['earringed', 'grenadier'], + 'earshot': ['asthore', 'earshot'], + 'eartab': ['abater', 'artabe', 'eartab', 'trabea'], + 'earth': ['earth', 'hater', 'heart', 'herat', 'rathe'], + 'earthborn': ['abhorrent', 'earthborn'], + 'earthed': ['earthed', 'hearted'], + 'earthen': ['earthen', 'enheart', 'hearten', 'naether', 'teheran', 'traheen'], + 'earthian': ['earthian', 'rhaetian'], + 'earthiness': ['earthiness', 'heartiness'], + 'earthless': ['earthless', 'heartless'], + 'earthling': ['earthling', 'heartling'], + 'earthly': ['earthly', 'heartly', 'lathery', 'rathely'], + 'earthnut': ['earthnut', 'heartnut'], + 'earthpea': ['earthpea', 'heartpea'], + 'earthquake': ['earthquake', 'heartquake'], + 'earthward': ['earthward', 'heartward'], + 'earthy': ['earthy', 'hearty', 'yearth'], + 'earwig': ['earwig', 'grewia'], + 'earwitness': ['earwitness', 'wateriness'], + 'easel': ['easel', 'lease'], + 'easement': ['easement', 'estamene'], + 'easer': ['easer', 'erase'], + 'easily': ['easily', 'elysia'], + 'easing': ['easing', 'sangei'], + 'east': ['ates', 'east', 'eats', 'sate', 'seat', 'seta'], + 'eastabout': ['aetobatus', 'eastabout'], + 'eastbound': ['eastbound', 'unboasted'], + 'easter': ['asteer', + 'easter', + 'eastre', + 'reseat', + 'saeter', + 'seater', + 'staree', + 'teaser', + 'teresa'], + 'easterling': ['easterling', 'generalist'], + 'eastern': ['earnest', 'eastern', 'nearest'], + 'easternly': ['earnestly', 'easternly'], + 'easting': ['easting', + 'gainset', + 'genista', + 'ingesta', + 'seating', + 'signate', + 'teasing'], + 'eastlake': ['alestake', 'eastlake'], + 'eastre': ['asteer', + 'easter', + 'eastre', + 'reseat', + 'saeter', + 'seater', + 'staree', + 'teaser', + 'teresa'], + 'easy': ['easy', 'eyas'], + 'eat': ['ate', 'eat', 'eta', 'tae', 'tea'], + 'eatberry': ['betrayer', 'eatberry', 'rebetray', 'teaberry'], + 'eaten': ['eaten', 'enate'], + 'eater': ['arete', 'eater', 'teaer'], + 'eating': ['eating', 'ingate', 'tangie'], + 'eats': ['ates', 'east', 'eats', 'sate', 'seat', 'seta'], + 'eave': ['eave', 'evea'], + 'eaved': ['deave', 'eaved', 'evade'], + 'eaver': ['eaver', 'reave'], + 'eaves': ['eaves', 'evase', 'seave'], + 'eben': ['been', 'bene', 'eben'], + 'ebenales': ['ebenales', 'lebanese'], + 'ebon': ['beno', 'bone', 'ebon'], + 'ebony': ['boney', 'ebony'], + 'ebriety': ['byerite', 'ebriety'], + 'eburna': ['eburna', 'unbare', 'unbear', 'urbane'], + 'eburnated': ['eburnated', 'underbeat', 'unrebated'], + 'eburnian': ['eburnian', 'inurbane'], + 'ecad': ['cade', 'dace', 'ecad'], + 'ecanda': ['adance', 'ecanda'], + 'ecardinal': ['ecardinal', 'lardacein'], + 'ecarinate': ['anaeretic', 'ecarinate'], + 'ecarte': ['cerate', 'create', 'ecarte'], + 'ecaudata': ['acaudate', 'ecaudata'], + 'ecclesiasticism': ['ecclesiasticism', 'misecclesiastic'], + 'eche': ['chee', 'eche'], + 'echelon': ['chelone', 'echelon'], + 'echeveria': ['echeveria', 'reachieve'], + 'echidna': ['chained', 'echidna'], + 'echinal': ['chilean', 'echinal', 'nichael'], + 'echinate': ['echinate', 'hecatine'], + 'echinital': ['echinital', 'inethical'], + 'echis': ['echis', 'shice'], + 'echoer': ['choree', 'cohere', 'echoer'], + 'echoic': ['choice', 'echoic'], + 'echoist': ['chitose', 'echoist'], + 'eciton': ['eciton', 'noetic', 'notice', 'octine'], + 'eckehart': ['eckehart', 'hacktree'], + 'eclair': ['carlie', 'claire', 'eclair', 'erical'], + 'eclat': ['cleat', 'eclat', 'ectal', 'lacet', 'tecla'], + 'eclipsable': ['eclipsable', 'spliceable'], + 'eclipser': ['eclipser', 'pericles', 'resplice'], + 'economics': ['economics', 'neocosmic'], + 'economism': ['economism', 'monoecism', 'monosemic'], + 'economist': ['economist', 'mesotonic'], + 'ecorticate': ['ecorticate', 'octaeteric'], + 'ecostate': ['coestate', 'ecostate'], + 'ecotonal': ['colonate', 'ecotonal'], + 'ecotype': ['ecotype', 'ocypete'], + 'ecrasite': ['ecrasite', 'sericate'], + 'ecru': ['cure', 'ecru', 'eruc'], + 'ectad': ['cadet', 'ectad'], + 'ectal': ['cleat', 'eclat', 'ectal', 'lacet', 'tecla'], + 'ectasis': ['ascites', 'ectasis'], + 'ectene': ['cetene', 'ectene'], + 'ectental': ['ectental', 'tentacle'], + 'ectiris': ['ectiris', 'eristic'], + 'ectocardia': ['coradicate', 'ectocardia'], + 'ectocranial': ['calonectria', 'ectocranial'], + 'ectoglia': ['ectoglia', 'geotical', 'goetical'], + 'ectomorph': ['ectomorph', 'topchrome'], + 'ectomorphic': ['cetomorphic', 'chemotropic', 'ectomorphic'], + 'ectomorphy': ['chromotype', 'cormophyte', 'ectomorphy'], + 'ectopia': ['ectopia', 'opacite'], + 'ectopy': ['cotype', 'ectopy'], + 'ectorhinal': ['chlorinate', 'ectorhinal', 'tornachile'], + 'ectosarc': ['ectosarc', 'reaccost'], + 'ectrogenic': ['ectrogenic', 'egocentric', 'geocentric'], + 'ectromelia': ['carmeloite', 'ectromelia', 'meteorical'], + 'ectropion': ['ectropion', 'neotropic'], + 'ed': ['de', 'ed'], + 'edda': ['dade', 'dead', 'edda'], + 'eddaic': ['caddie', 'eddaic'], + 'eddish': ['dished', 'eddish'], + 'eddo': ['dedo', 'dode', 'eddo'], + 'edema': ['adeem', 'ameed', 'edema'], + 'eden': ['dene', 'eden', 'need'], + 'edental': ['dalteen', 'dentale', 'edental'], + 'edentata': ['antedate', 'edentata'], + 'edessan': ['deaness', 'edessan'], + 'edestan': ['edestan', 'standee'], + 'edestin': ['destine', 'edestin'], + 'edgar': ['edgar', 'grade'], + 'edger': ['edger', 'greed'], + 'edgerman': ['edgerman', 'gendarme'], + 'edgrew': ['edgrew', 'wedger'], + 'edible': ['debile', 'edible'], + 'edict': ['cetid', 'edict'], + 'edictal': ['citadel', 'deltaic', 'dialect', 'edictal', 'lactide'], + 'edification': ['deification', 'edification'], + 'edificatory': ['deificatory', 'edificatory'], + 'edifier': ['deifier', 'edifier'], + 'edify': ['deify', 'edify'], + 'edit': ['diet', 'dite', 'edit', 'tide', 'tied'], + 'edital': ['detail', 'dietal', 'dilate', 'edital', 'tailed'], + 'edith': ['edith', 'ethid'], + 'edition': ['edition', 'odinite', 'otidine', 'tineoid'], + 'editor': ['editor', 'triode'], + 'editorial': ['editorial', 'radiolite'], + 'edmund': ['edmund', 'mudden'], + 'edna': ['ande', 'dane', 'dean', 'edna'], + 'edo': ['doe', 'edo', 'ode'], + 'edoni': ['deino', 'dione', 'edoni'], + 'education': ['coadunite', 'education', 'noctuidae'], + 'educe': ['deuce', 'educe'], + 'edward': ['edward', 'wadder', 'warded'], + 'edwin': ['dwine', 'edwin', 'wendi', 'widen', 'wined'], + 'eel': ['eel', 'lee'], + 'eelgrass': ['eelgrass', 'gearless', 'rageless'], + 'eelpot': ['eelpot', 'opelet'], + 'eelspear': ['eelspear', 'prelease'], + 'eely': ['eely', 'yeel'], + 'eer': ['eer', 'ere', 'ree'], + 'efik': ['efik', 'fike'], + 'eft': ['eft', 'fet'], + 'egad': ['aged', 'egad', 'gade'], + 'egba': ['egba', 'gabe'], + 'egbo': ['bego', 'egbo'], + 'egeran': ['egeran', 'enrage', 'ergane', 'genear', 'genera'], + 'egest': ['egest', 'geest', 'geste'], + 'egger': ['egger', 'grege'], + 'egghot': ['egghot', 'hogget'], + 'eggler': ['eggler', 'legger'], + 'eggy': ['eggy', 'yegg'], + 'eglantine': ['eglantine', 'inelegant', 'legantine'], + 'eglatere': ['eglatere', 'regelate', 'relegate'], + 'egma': ['egma', 'game', 'mage'], + 'ego': ['ego', 'geo'], + 'egocentric': ['ectrogenic', 'egocentric', 'geocentric'], + 'egoist': ['egoist', 'stogie'], + 'egol': ['egol', 'goel', 'loge', 'ogle', 'oleg'], + 'egotheism': ['egotheism', 'eightsome'], + 'egret': ['egret', 'greet', 'reget'], + 'eh': ['eh', 'he'], + 'ehretia': ['ehretia', 'etheria'], + 'eident': ['eident', 'endite'], + 'eidograph': ['eidograph', 'ideograph'], + 'eidology': ['eidology', 'ideology'], + 'eighth': ['eighth', 'height'], + 'eightsome': ['egotheism', 'eightsome'], + 'eigne': ['eigne', 'genie'], + 'eileen': ['eileen', 'lienee'], + 'ekaha': ['ekaha', 'hakea'], + 'eke': ['eke', 'kee'], + 'eker': ['eker', 'reek'], + 'ekoi': ['ekoi', 'okie'], + 'ekron': ['ekron', 'krone'], + 'ektene': ['ektene', 'ketene'], + 'elabrate': ['elabrate', 'tearable'], + 'elaidic': ['aedilic', 'elaidic'], + 'elaidin': ['anilide', 'elaidin'], + 'elain': ['alien', 'aline', 'anile', 'elain', 'elian', 'laine', 'linea'], + 'elaine': ['aileen', 'elaine'], + 'elamite': ['alemite', 'elamite'], + 'elance': ['elance', 'enlace'], + 'eland': ['eland', 'laden', 'lenad'], + 'elanet': ['elanet', 'lanete', 'lateen'], + 'elanus': ['elanus', 'unseal'], + 'elaphomyces': ['elaphomyces', 'mesocephaly'], + 'elaphurus': ['elaphurus', 'sulphurea'], + 'elapid': ['aliped', 'elapid'], + 'elapoid': ['elapoid', 'oedipal'], + 'elaps': ['elaps', + 'lapse', + 'lepas', + 'pales', + 'salep', + 'saple', + 'sepal', + 'slape', + 'spale', + 'speal'], + 'elapse': ['asleep', 'elapse', 'please'], + 'elastic': ['astelic', 'elastic', 'latices'], + 'elasticin': ['elasticin', 'inelastic', 'sciential'], + 'elastin': ['elastin', 'salient', 'saltine', 'slainte'], + 'elastomer': ['elastomer', 'salometer'], + 'elate': ['atlee', 'elate'], + 'elated': ['delate', 'elated'], + 'elater': ['earlet', 'elater', 'relate'], + 'elaterid': ['detailer', 'elaterid'], + 'elaterin': ['elaterin', 'entailer', 'treenail'], + 'elatha': ['althea', 'elatha'], + 'elatine': ['elatine', 'lineate'], + 'elation': ['alnoite', 'elation', 'toenail'], + 'elator': ['elator', 'lorate'], + 'elb': ['bel', 'elb'], + 'elbert': ['belter', 'elbert', 'treble'], + 'elberta': ['bearlet', 'bleater', 'elberta', 'retable'], + 'elbow': ['below', 'bowel', 'elbow'], + 'elbowed': ['boweled', 'elbowed'], + 'eld': ['del', 'eld', 'led'], + 'eldin': ['eldin', 'lined'], + 'elding': ['dingle', 'elding', 'engild', 'gilden'], + 'elean': ['anele', 'elean'], + 'election': ['coteline', 'election'], + 'elective': ['cleveite', 'elective'], + 'elector': ['elector', 'electro'], + 'electoral': ['electoral', 'recollate'], + 'electra': ['electra', 'treacle'], + 'electragy': ['electragy', 'glycerate'], + 'electret': ['electret', 'tercelet'], + 'electric': ['electric', 'lectrice'], + 'electrion': ['centriole', 'electrion', 'relection'], + 'electro': ['elector', 'electro'], + 'electrodynamic': ['dynamoelectric', 'electrodynamic'], + 'electrodynamical': ['dynamoelectrical', 'electrodynamical'], + 'electromagnetic': ['electromagnetic', 'magnetoelectric'], + 'electromagnetical': ['electromagnetical', 'magnetoelectrical'], + 'electrothermic': ['electrothermic', 'thermoelectric'], + 'electrothermometer': ['electrothermometer', 'thermoelectrometer'], + 'elegant': ['angelet', 'elegant'], + 'elegiambus': ['elegiambus', 'iambelegus'], + 'elegiast': ['elegiast', 'selagite'], + 'elemi': ['elemi', 'meile'], + 'elemin': ['elemin', 'meline'], + 'elephantic': ['elephantic', 'plancheite'], + 'elettaria': ['elettaria', 'retaliate'], + 'eleut': ['eleut', 'elute'], + 'elevator': ['elevator', 'overlate'], + 'elfin': ['elfin', 'nifle'], + 'elfishness': ['elfishness', 'fleshiness'], + 'elfkin': ['elfkin', 'finkel'], + 'elfwort': ['elfwort', 'felwort'], + 'eli': ['eli', 'lei', 'lie'], + 'elia': ['aiel', 'aile', 'elia'], + 'elian': ['alien', 'aline', 'anile', 'elain', 'elian', 'laine', 'linea'], + 'elias': ['aisle', 'elias'], + 'elicitor': ['elicitor', 'trioleic'], + 'eliminand': ['eliminand', 'mindelian'], + 'elinor': ['elinor', 'lienor', 'lorien', 'noiler'], + 'elinvar': ['elinvar', 'ravelin', 'reanvil', 'valerin'], + 'elisha': ['elisha', 'hailse', 'sheila'], + 'elisor': ['elisor', 'resoil'], + 'elissa': ['elissa', 'lassie'], + 'elite': ['elite', 'telei'], + 'eliza': ['aizle', 'eliza'], + 'elk': ['elk', 'lek'], + 'ella': ['alle', 'ella', 'leal'], + 'ellagate': ['allegate', 'ellagate'], + 'ellenyard': ['ellenyard', 'learnedly'], + 'ellick': ['ellick', 'illeck'], + 'elliot': ['elliot', 'oillet'], + 'elm': ['elm', 'mel'], + 'elmer': ['elmer', 'merel', 'merle'], + 'elmy': ['elmy', 'yelm'], + 'eloah': ['eloah', 'haole'], + 'elod': ['dole', 'elod', 'lode', 'odel'], + 'eloge': ['eloge', 'golee'], + 'elohimic': ['elohimic', 'hemiolic'], + 'elohist': ['elohist', 'hostile'], + 'eloign': ['eloign', 'gileno', 'legion'], + 'eloigner': ['eloigner', 'legioner'], + 'eloignment': ['eloignment', 'omnilegent'], + 'elon': ['elon', 'enol', 'leno', 'leon', 'lone', 'noel'], + 'elonite': ['elonite', 'leonite'], + 'elops': ['elops', 'slope', 'spole'], + 'elric': ['crile', 'elric', 'relic'], + 'els': ['els', 'les'], + 'elsa': ['elsa', 'sale', 'seal', 'slae'], + 'else': ['else', 'lees', 'seel', 'sele', 'slee'], + 'elsin': ['elsin', 'lenis', 'niels', 'silen', 'sline'], + 'elt': ['elt', 'let'], + 'eluate': ['aulete', 'eluate'], + 'eluder': ['dueler', 'eluder'], + 'elusion': ['elusion', 'luiseno'], + 'elusory': ['elusory', 'yoursel'], + 'elute': ['eleut', 'elute'], + 'elution': ['elution', 'outline'], + 'elutor': ['elutor', 'louter', 'outler'], + 'elvan': ['elvan', 'navel', 'venal'], + 'elvanite': ['elvanite', 'lavenite'], + 'elver': ['elver', 'lever', 'revel'], + 'elvet': ['elvet', 'velte'], + 'elvira': ['averil', 'elvira'], + 'elvis': ['elvis', 'levis', 'slive'], + 'elwood': ['dewool', 'elwood', 'wooled'], + 'elymi': ['elymi', 'emily', 'limey'], + 'elysia': ['easily', 'elysia'], + 'elytral': ['alertly', 'elytral'], + 'elytrin': ['elytrin', 'inertly', 'trinely'], + 'elytroposis': ['elytroposis', 'proteolysis'], + 'elytrous': ['elytrous', 'urostyle'], + 'em': ['em', 'me'], + 'emanate': ['emanate', 'manatee'], + 'emanation': ['amnionate', 'anamniote', 'emanation'], + 'emanatist': ['emanatist', 'staminate', 'tasmanite'], + 'embalmer': ['embalmer', 'emmarble'], + 'embar': ['amber', 'bearm', 'bemar', 'bream', 'embar'], + 'embargo': ['bergamo', 'embargo'], + 'embark': ['embark', 'markeb'], + 'embay': ['beamy', 'embay', 'maybe'], + 'ember': ['breme', 'ember'], + 'embind': ['embind', 'nimbed'], + 'embira': ['ambier', 'bremia', 'embira'], + 'embodier': ['demirobe', 'embodier'], + 'embody': ['beydom', 'embody'], + 'embole': ['bemole', 'embole'], + 'embraceor': ['cerebroma', 'embraceor'], + 'embrail': ['embrail', 'mirabel'], + 'embryoid': ['embryoid', 'reimbody'], + 'embus': ['embus', 'sebum'], + 'embusk': ['bemusk', 'embusk'], + 'emcee': ['emcee', 'meece'], + 'emeership': ['emeership', 'ephemeris'], + 'emend': ['emend', 'mende'], + 'emendation': ['denominate', 'emendation'], + 'emendator': ['emendator', 'ondameter'], + 'emerita': ['emerita', 'emirate'], + 'emerse': ['emerse', 'seemer'], + 'emersion': ['emersion', 'meriones'], + 'emersonian': ['emersonian', 'mansioneer'], + 'emesa': ['emesa', 'mease'], + 'emigrate': ['emigrate', 'remigate'], + 'emigration': ['emigration', 'remigation'], + 'emil': ['emil', 'lime', 'mile'], + 'emilia': ['emilia', 'mailie'], + 'emily': ['elymi', 'emily', 'limey'], + 'emim': ['emim', 'mime'], + 'emir': ['emir', 'imer', 'mire', 'reim', 'remi', 'riem', 'rime'], + 'emirate': ['emerita', 'emirate'], + 'emirship': ['emirship', 'imperish'], + 'emissary': ['emissary', 'missayer'], + 'emit': ['emit', 'item', 'mite', 'time'], + 'emitter': ['emitter', 'termite'], + 'emm': ['emm', 'mem'], + 'emmarble': ['embalmer', 'emmarble'], + 'emodin': ['domine', 'domnei', 'emodin', 'medino'], + 'emotion': ['emotion', 'moonite'], + 'empanel': ['empanel', 'emplane', 'peelman'], + 'empathic': ['empathic', 'emphatic'], + 'empathically': ['empathically', 'emphatically'], + 'emphasis': ['emphasis', 'misshape'], + 'emphatic': ['empathic', 'emphatic'], + 'emphatically': ['empathically', 'emphatically'], + 'empire': ['empire', 'epimer'], + 'empiricist': ['empiricist', 'empiristic'], + 'empiristic': ['empiricist', 'empiristic'], + 'emplane': ['empanel', 'emplane', 'peelman'], + 'employer': ['employer', 'polymere'], + 'emporia': ['emporia', 'meropia'], + 'emporial': ['emporial', 'proemial'], + 'emporium': ['emporium', 'pomerium', 'proemium'], + 'emprise': ['emprise', 'imprese', 'premise', 'spireme'], + 'empt': ['empt', 'temp'], + 'emptier': ['emptier', 'impetre'], + 'emption': ['emption', 'pimento'], + 'emptional': ['emptional', 'palmitone'], + 'emptor': ['emptor', 'trompe'], + 'empyesis': ['empyesis', 'pyemesis'], + 'emu': ['emu', 'ume'], + 'emulant': ['almuten', 'emulant'], + 'emulation': ['emulation', 'laumonite'], + 'emulsion': ['emulsion', 'solenium'], + 'emundation': ['emundation', 'mountained'], + 'emyd': ['demy', 'emyd'], + 'en': ['en', 'ne'], + 'enable': ['baleen', 'enable'], + 'enabler': ['enabler', 'renable'], + 'enaction': ['cetonian', 'enaction'], + 'enactor': ['enactor', 'necator', 'orcanet'], + 'enactory': ['enactory', 'octenary'], + 'enaena': ['aenean', 'enaena'], + 'enalid': ['aldine', 'daniel', 'delian', 'denial', 'enalid', 'leadin'], + 'enaliornis': ['enaliornis', 'rosaniline'], + 'enaluron': ['enaluron', 'neuronal'], + 'enam': ['amen', 'enam', 'mane', 'mean', 'name', 'nema'], + 'enamel': ['enamel', 'melena'], + 'enameling': ['enameling', 'malengine', 'meningeal'], + 'enamor': ['enamor', 'monera', 'oreman', 'romane'], + 'enamored': ['demeanor', 'enamored'], + 'enanthem': ['enanthem', 'menthane'], + 'enantiomer': ['enantiomer', 'renominate'], + 'enapt': ['enapt', 'paten', 'penta', 'tapen'], + 'enarch': ['enarch', 'ranche'], + 'enarm': ['enarm', 'namer', 'reman'], + 'enarme': ['enarme', 'meaner', 'rename'], + 'enarthrosis': ['enarthrosis', 'nearthrosis'], + 'enate': ['eaten', 'enate'], + 'enatic': ['acetin', 'actine', 'enatic'], + 'enation': ['enation', 'etonian'], + 'enbrave': ['enbrave', 'verbena'], + 'encapsule': ['encapsule', 'pelecanus'], + 'encase': ['encase', 'seance', 'seneca'], + 'encash': ['encash', 'sanche'], + 'encauma': ['cumaean', 'encauma'], + 'encaustes': ['acuteness', 'encaustes'], + 'encaustic': ['encaustic', 'succinate'], + 'encephalomeningitis': ['encephalomeningitis', 'meningoencephalitis'], + 'encephalomeningocele': ['encephalomeningocele', 'meningoencephalocele'], + 'encephalomyelitis': ['encephalomyelitis', 'myeloencephalitis'], + 'enchair': ['chainer', 'enchair', 'rechain'], + 'encharge': ['encharge', 'rechange'], + 'encharnel': ['channeler', 'encharnel'], + 'enchytrae': ['cytherean', 'enchytrae'], + 'encina': ['canine', 'encina', 'neanic'], + 'encinillo': ['encinillo', 'linolenic'], + 'encist': ['encist', 'incest', 'insect', 'scient'], + 'encitadel': ['declinate', 'encitadel'], + 'enclaret': ['celarent', 'centrale', 'enclaret'], + 'enclasp': ['enclasp', 'spancel'], + 'enclave': ['enclave', 'levance', 'valence'], + 'enclosure': ['enclosure', 'recounsel'], + 'encoignure': ['encoignure', 'neurogenic'], + 'encoil': ['clione', 'coelin', 'encoil', 'enolic'], + 'encomiastic': ['cosmetician', 'encomiastic'], + 'encomic': ['comenic', 'encomic', 'meconic'], + 'encomium': ['encomium', 'meconium'], + 'encoronal': ['encoronal', 'olecranon'], + 'encoronate': ['encoronate', 'entocornea'], + 'encradle': ['calender', 'encradle'], + 'encranial': ['carnelian', 'encranial'], + 'encratic': ['acentric', 'encratic', 'nearctic'], + 'encratism': ['encratism', 'miscreant'], + 'encraty': ['encraty', 'nectary'], + 'encreel': ['crenele', 'encreel'], + 'encrinital': ['encrinital', 'tricennial'], + 'encrisp': ['encrisp', 'pincers'], + 'encrust': ['encrust', 'uncrest'], + 'encurl': ['encurl', 'lucern'], + 'encurtain': ['encurtain', 'runcinate', 'uncertain'], + 'encyrtidae': ['encyrtidae', 'nycteridae'], + 'end': ['den', 'end', 'ned'], + 'endaortic': ['citronade', 'endaortic', 'redaction'], + 'endboard': ['deadborn', 'endboard'], + 'endear': ['deaner', 'endear'], + 'endeared': ['deadener', 'endeared'], + 'endearing': ['endearing', 'engrained', 'grenadine'], + 'endearingly': ['endearingly', 'engrainedly'], + 'endemial': ['endemial', 'madeline'], + 'endere': ['endere', 'needer', 'reeden'], + 'enderonic': ['enderonic', 'endocrine'], + 'endevil': ['develin', 'endevil'], + 'endew': ['endew', 'wende'], + 'ending': ['ending', 'ginned'], + 'endite': ['eident', 'endite'], + 'endive': ['endive', 'envied', 'veined'], + 'endoarteritis': ['endoarteritis', 'sideronatrite'], + 'endocline': ['endocline', 'indolence'], + 'endocrine': ['enderonic', 'endocrine'], + 'endome': ['endome', 'omened'], + 'endopathic': ['dictaphone', 'endopathic'], + 'endophasic': ['deaconship', 'endophasic'], + 'endoral': ['endoral', 'ladrone', 'leonard'], + 'endosarc': ['endosarc', 'secondar'], + 'endosome': ['endosome', 'moonseed'], + 'endosporium': ['endosporium', 'imponderous'], + 'endosteal': ['endosteal', 'leadstone'], + 'endothecial': ['chelidonate', 'endothecial'], + 'endothelia': ['endothelia', 'ethanediol', 'ethenoidal'], + 'endow': ['endow', 'nowed'], + 'endura': ['endura', 'neurad', 'undear', 'unread'], + 'endurably': ['endurably', 'undryable'], + 'endure': ['durene', 'endure'], + 'endurer': ['endurer', 'underer'], + 'enduring': ['enduring', 'unringed'], + 'enduringly': ['enduringly', 'underlying'], + 'endwise': ['endwise', 'sinewed'], + 'enema': ['ameen', 'amene', 'enema'], + 'enemy': ['enemy', 'yemen'], + 'energesis': ['energesis', 'regenesis'], + 'energeticist': ['energeticist', 'energetistic'], + 'energetistic': ['energeticist', 'energetistic'], + 'energic': ['energic', 'generic'], + 'energical': ['energical', 'generical'], + 'energid': ['energid', 'reeding'], + 'energist': ['energist', 'steering'], + 'energy': ['energy', 'greeny', 'gyrene'], + 'enervate': ['enervate', 'venerate'], + 'enervation': ['enervation', 'veneration'], + 'enervative': ['enervative', 'venerative'], + 'enervator': ['enervator', 'renovater', 'venerator'], + 'enfilade': ['alfenide', 'enfilade'], + 'enfile': ['enfile', 'enlief', 'enlife', 'feline'], + 'enflesh': ['enflesh', 'fleshen'], + 'enfoil': ['enfoil', 'olefin'], + 'enfold': ['enfold', 'folden', 'fondle'], + 'enforcer': ['confrere', 'enforcer', 'reconfer'], + 'enframe': ['enframe', 'freeman'], + 'engaol': ['angelo', 'engaol'], + 'engarb': ['banger', 'engarb', 'graben'], + 'engaud': ['augend', 'engaud', 'unaged'], + 'engild': ['dingle', 'elding', 'engild', 'gilden'], + 'engird': ['engird', 'ringed'], + 'engirdle': ['engirdle', 'reedling'], + 'engirt': ['engirt', 'tinger'], + 'englacial': ['angelical', 'englacial', 'galenical'], + 'englacially': ['angelically', 'englacially'], + 'englad': ['angled', 'dangle', 'englad', 'lagend'], + 'englander': ['englander', 'greenland'], + 'english': ['english', 'shingle'], + 'englisher': ['englisher', 'reshingle'], + 'englut': ['englut', 'gluten', 'ungelt'], + 'engobe': ['begone', 'engobe'], + 'engold': ['engold', 'golden'], + 'engrail': ['aligner', 'engrail', 'realign', 'reginal'], + 'engrailed': ['engrailed', 'geraldine'], + 'engrailment': ['engrailment', 'realignment'], + 'engrain': ['earning', 'engrain'], + 'engrained': ['endearing', 'engrained', 'grenadine'], + 'engrainedly': ['endearingly', 'engrainedly'], + 'engram': ['engram', 'german', 'manger'], + 'engraphic': ['engraphic', 'preaching'], + 'engrave': ['avenger', 'engrave'], + 'engross': ['engross', 'grossen'], + 'enhat': ['enhat', 'ethan', 'nathe', 'neath', 'thane'], + 'enheart': ['earthen', 'enheart', 'hearten', 'naether', 'teheran', 'traheen'], + 'enherit': ['enherit', 'etherin', 'neither', 'therein'], + 'enhydra': ['enhydra', 'henyard'], + 'eniac': ['anice', 'eniac'], + 'enicuridae': ['audiencier', 'enicuridae'], + 'enid': ['dine', 'enid', 'inde', 'nide'], + 'enif': ['enif', 'fine', 'neif', 'nife'], + 'enisle': ['enisle', 'ensile', 'senile', 'silene'], + 'enlace': ['elance', 'enlace'], + 'enlard': ['aldern', + 'darnel', + 'enlard', + 'lander', + 'lenard', + 'randle', + 'reland'], + 'enlarge': ['enlarge', 'general', 'gleaner'], + 'enleaf': ['enleaf', 'leafen'], + 'enlief': ['enfile', 'enlief', 'enlife', 'feline'], + 'enlife': ['enfile', 'enlief', 'enlife', 'feline'], + 'enlight': ['enlight', 'lighten'], + 'enlist': ['enlist', 'listen', 'silent', 'tinsel'], + 'enlisted': ['enlisted', 'lintseed'], + 'enlister': ['enlister', 'esterlin', 'listener', 'relisten'], + 'enmass': ['enmass', 'maness', 'messan'], + 'enneadic': ['cadinene', 'decennia', 'enneadic'], + 'ennobler': ['ennobler', 'nonrebel'], + 'ennoic': ['conine', 'connie', 'ennoic'], + 'ennomic': ['ennomic', 'meconin'], + 'enoch': ['cohen', 'enoch'], + 'enocyte': ['enocyte', 'neocyte'], + 'enodal': ['enodal', 'loaden'], + 'enoil': ['enoil', 'ileon', 'olein'], + 'enol': ['elon', 'enol', 'leno', 'leon', 'lone', 'noel'], + 'enolic': ['clione', 'coelin', 'encoil', 'enolic'], + 'enomania': ['enomania', 'maeonian'], + 'enomotarch': ['chromatone', 'enomotarch'], + 'enorganic': ['enorganic', 'ignorance'], + 'enorm': ['enorm', 'moner', 'morne'], + 'enormous': ['enormous', 'unmorose'], + 'enos': ['enos', 'nose'], + 'enostosis': ['enostosis', 'sootiness'], + 'enow': ['enow', 'owen', 'wone'], + 'enphytotic': ['enphytotic', 'entophytic'], + 'enrace': ['careen', 'carene', 'enrace'], + 'enrage': ['egeran', 'enrage', 'ergane', 'genear', 'genera'], + 'enraged': ['derange', 'enraged', 'gardeen', 'gerenda', 'grandee', 'grenade'], + 'enragedly': ['enragedly', 'legendary'], + 'enrapt': ['arpent', + 'enrapt', + 'entrap', + 'panter', + 'parent', + 'pretan', + 'trepan'], + 'enravish': ['enravish', 'ravenish', 'vanisher'], + 'enray': ['enray', 'yearn'], + 'enrib': ['brine', 'enrib'], + 'enrich': ['enrich', 'nicher', 'richen'], + 'enring': ['enring', 'ginner'], + 'enrive': ['enrive', 'envier', 'veiner', 'verine'], + 'enrobe': ['boreen', 'enrobe', 'neebor', 'rebone'], + 'enrol': ['enrol', 'loren'], + 'enrolled': ['enrolled', 'rondelle'], + 'enrough': ['enrough', 'roughen'], + 'enruin': ['enruin', 'neurin', 'unrein'], + 'enrut': ['enrut', 'tuner', 'urent'], + 'ens': ['ens', 'sen'], + 'ensaint': ['ensaint', 'stanine'], + 'ensate': ['ensate', 'enseat', 'santee', 'sateen', 'senate'], + 'ense': ['ense', 'esne', 'nese', 'seen', 'snee'], + 'enseam': ['enseam', 'semnae'], + 'enseat': ['ensate', 'enseat', 'santee', 'sateen', 'senate'], + 'ensepulcher': ['ensepulcher', 'ensepulchre'], + 'ensepulchre': ['ensepulcher', 'ensepulchre'], + 'enshade': ['dasheen', 'enshade'], + 'enshroud': ['enshroud', 'unshored'], + 'ensigncy': ['ensigncy', 'syngenic'], + 'ensilage': ['ensilage', 'genesial', 'signalee'], + 'ensile': ['enisle', 'ensile', 'senile', 'silene'], + 'ensilver': ['ensilver', 'sniveler'], + 'ensmall': ['ensmall', 'smallen'], + 'ensoul': ['ensoul', 'olenus', 'unsole'], + 'enspirit': ['enspirit', 'pristine'], + 'enstar': ['astern', 'enstar', 'stenar', 'sterna'], + 'enstatite': ['enstatite', 'intestate', 'satinette'], + 'enstool': ['enstool', 'olonets'], + 'enstore': ['enstore', 'estrone', 'storeen', 'tornese'], + 'ensue': ['ensue', 'seenu', 'unsee'], + 'ensuer': ['ensuer', 'ensure'], + 'ensure': ['ensuer', 'ensure'], + 'entablature': ['entablature', 'untreatable'], + 'entach': ['entach', 'netcha'], + 'entad': ['denat', 'entad'], + 'entada': ['adnate', 'entada'], + 'entail': ['entail', 'tineal'], + 'entailer': ['elaterin', 'entailer', 'treenail'], + 'ental': ['ental', 'laten', 'leant'], + 'entasia': ['anisate', 'entasia'], + 'entasis': ['entasis', 'sestian', 'sestina'], + 'entelam': ['entelam', 'leetman'], + 'enter': ['enter', 'neter', 'renet', 'terne', 'treen'], + 'enteral': ['alterne', 'enteral', 'eternal', 'teleran', 'teneral'], + 'enterer': ['enterer', 'terrene'], + 'enteria': ['enteria', 'trainee', 'triaene'], + 'enteric': ['citrene', 'enteric', 'enticer', 'tercine'], + 'enterocolitis': ['coloenteritis', 'enterocolitis'], + 'enterogastritis': ['enterogastritis', 'gastroenteritis'], + 'enteroid': ['enteroid', 'orendite'], + 'enteron': ['enteron', 'tenoner'], + 'enteropexy': ['enteropexy', 'oxyterpene'], + 'entertain': ['entertain', 'tarentine', 'terentian'], + 'entheal': ['entheal', 'lethean'], + 'enthraldom': ['enthraldom', 'motherland'], + 'enthuse': ['enthuse', 'unsheet'], + 'entia': ['entia', 'teian', 'tenai', 'tinea'], + 'enticer': ['citrene', 'enteric', 'enticer', 'tercine'], + 'entincture': ['entincture', 'unreticent'], + 'entire': ['entire', 'triene'], + 'entirely': ['entirely', 'lientery'], + 'entirety': ['entirety', 'eternity'], + 'entity': ['entity', 'tinety'], + 'entocoelic': ['coelection', 'entocoelic'], + 'entocornea': ['encoronate', 'entocornea'], + 'entohyal': ['entohyal', 'ethanoyl'], + 'entoil': ['entoil', 'lionet'], + 'entomeric': ['entomeric', 'intercome', 'morencite'], + 'entomic': ['centimo', 'entomic', 'tecomin'], + 'entomical': ['entomical', 'melanotic'], + 'entomion': ['entomion', 'noontime'], + 'entomoid': ['demotion', 'entomoid', 'moontide'], + 'entomophily': ['entomophily', 'monophylite'], + 'entomotomy': ['entomotomy', 'omentotomy'], + 'entoparasite': ['antiprotease', 'entoparasite'], + 'entophyte': ['entophyte', 'tenophyte'], + 'entophytic': ['enphytotic', 'entophytic'], + 'entopic': ['entopic', 'nepotic', 'pentoic'], + 'entoplastic': ['entoplastic', 'spinotectal', 'tectospinal', 'tenoplastic'], + 'entoretina': ['entoretina', 'tetraonine'], + 'entosarc': ['ancestor', 'entosarc'], + 'entotic': ['entotic', 'tonetic'], + 'entozoa': ['entozoa', 'ozonate'], + 'entozoic': ['entozoic', 'enzootic'], + 'entrail': ['entrail', + 'latiner', + 'latrine', + 'ratline', + 'reliant', + 'retinal', + 'trenail'], + 'entrain': ['entrain', 'teriann'], + 'entrance': ['centenar', 'entrance'], + 'entrap': ['arpent', + 'enrapt', + 'entrap', + 'panter', + 'parent', + 'pretan', + 'trepan'], + 'entreat': ['entreat', 'ratteen', 'tarente', 'ternate', 'tetrane'], + 'entreating': ['entreating', 'interagent'], + 'entree': ['entree', 'rentee', 'retene'], + 'entrepas': ['entrepas', 'septenar'], + 'entropion': ['entropion', 'pontonier', 'prenotion'], + 'entropium': ['entropium', 'importune'], + 'entrust': ['entrust', 'stunter', 'trusten'], + 'enumeration': ['enumeration', 'mountaineer'], + 'enunciation': ['enunciation', 'incuneation'], + 'enunciator': ['enunciator', 'uncreation'], + 'enure': ['enure', 'reune'], + 'envelope': ['envelope', 'ovenpeel'], + 'enverdure': ['enverdure', 'unrevered'], + 'envied': ['endive', 'envied', 'veined'], + 'envier': ['enrive', 'envier', 'veiner', 'verine'], + 'envious': ['envious', 'niveous', 'veinous'], + 'envoy': ['envoy', 'nevoy', 'yoven'], + 'enwood': ['enwood', 'wooden'], + 'enwound': ['enwound', 'unowned'], + 'enwrap': ['enwrap', 'pawner', 'repawn'], + 'enwrite': ['enwrite', 'retwine'], + 'enzootic': ['entozoic', 'enzootic'], + 'eoan': ['aeon', 'eoan'], + 'eogaean': ['eogaean', 'neogaea'], + 'eolithic': ['chiolite', 'eolithic'], + 'eon': ['eon', 'neo', 'one'], + 'eonism': ['eonism', 'mesion', 'oneism', 'simeon'], + 'eophyton': ['eophyton', 'honeypot'], + 'eosaurus': ['eosaurus', 'rousseau'], + 'eosin': ['eosin', 'noise'], + 'eosinoblast': ['bosselation', 'eosinoblast'], + 'epacrid': ['epacrid', 'peracid', 'preacid'], + 'epacris': ['epacris', 'scrapie', 'serapic'], + 'epactal': ['epactal', 'placate'], + 'eparch': ['aperch', 'eparch', 'percha', 'preach'], + 'eparchial': ['eparchial', 'raphaelic'], + 'eparchy': ['eparchy', 'preachy'], + 'epha': ['epha', 'heap'], + 'epharmonic': ['epharmonic', 'pinachrome'], + 'ephemeris': ['emeership', 'ephemeris'], + 'ephod': ['depoh', 'ephod', 'hoped'], + 'ephor': ['ephor', 'hoper'], + 'ephorus': ['ephorus', 'orpheus', 'upshore'], + 'epibasal': ['ablepsia', 'epibasal'], + 'epibole': ['epibole', 'epilobe'], + 'epic': ['epic', 'pice'], + 'epical': ['epical', 'piacle', 'plaice'], + 'epicarp': ['crappie', 'epicarp'], + 'epicentral': ['epicentral', 'parentelic'], + 'epiceratodus': ['dipteraceous', 'epiceratodus'], + 'epichorial': ['aerophilic', 'epichorial'], + 'epicly': ['epicly', 'pyelic'], + 'epicostal': ['alopecist', 'altiscope', 'epicostal', 'scapolite'], + 'epicotyl': ['epicotyl', 'lipocyte'], + 'epicranial': ['epicranial', 'periacinal'], + 'epiderm': ['demirep', 'epiderm', 'impeder', 'remiped'], + 'epiderma': ['epiderma', 'premedia'], + 'epidermal': ['epidermal', 'impleader', 'premedial'], + 'epidermis': ['dispireme', 'epidermis'], + 'epididymovasostomy': ['epididymovasostomy', 'vasoepididymostomy'], + 'epidural': ['dipleura', 'epidural'], + 'epigram': ['epigram', 'primage'], + 'epilabrum': ['epilabrum', 'impuberal'], + 'epilachna': ['cephalina', 'epilachna'], + 'epilate': ['epilate', 'epitela', 'pileate'], + 'epilation': ['epilation', 'polianite'], + 'epilatory': ['epilatory', 'petiolary'], + 'epilobe': ['epibole', 'epilobe'], + 'epimer': ['empire', 'epimer'], + 'epiotic': ['epiotic', 'poietic'], + 'epipactis': ['epipactis', 'epipastic'], + 'epipastic': ['epipactis', 'epipastic'], + 'epiplasm': ['epiplasm', 'palmipes'], + 'epiploic': ['epiploic', 'epipolic'], + 'epipolic': ['epiploic', 'epipolic'], + 'epirotic': ['epirotic', 'periotic'], + 'episclera': ['episclera', 'periclase'], + 'episematic': ['episematic', 'septicemia'], + 'episodal': ['episodal', 'lapidose', 'sepaloid'], + 'episodial': ['apsidiole', 'episodial'], + 'epistatic': ['epistatic', 'pistacite'], + 'episternal': ['alpestrine', 'episternal', 'interlapse', 'presential'], + 'episternum': ['episternum', 'uprisement'], + 'epistlar': ['epistlar', 'pilaster', 'plaister', 'priestal'], + 'epistle': ['epistle', 'septile'], + 'epistler': ['epistler', 'spirelet'], + 'epistoler': ['epistoler', 'peristole', 'perseitol', 'pistoleer'], + 'epistoma': ['epistoma', 'metopias'], + 'epistome': ['epistome', 'epsomite'], + 'epistroma': ['epistroma', 'peristoma'], + 'epitela': ['epilate', 'epitela', 'pileate'], + 'epithecal': ['epithecal', 'petechial', 'phacelite'], + 'epithecate': ['epithecate', 'petechiate'], + 'epithet': ['epithet', 'heptite'], + 'epithyme': ['epithyme', 'hemitype'], + 'epitomizer': ['epitomizer', 'peritomize'], + 'epizoal': ['epizoal', 'lopezia', 'opalize'], + 'epoch': ['epoch', 'poche'], + 'epodic': ['copied', 'epodic'], + 'epornitic': ['epornitic', 'proteinic'], + 'epos': ['epos', 'peso', 'pose', 'sope'], + 'epsilon': ['epsilon', 'sinople'], + 'epsomite': ['epistome', 'epsomite'], + 'epulis': ['epulis', 'pileus'], + 'epulo': ['epulo', 'loupe'], + 'epuloid': ['epuloid', 'euploid'], + 'epulosis': ['epulosis', 'pelusios'], + 'epulotic': ['epulotic', 'poultice'], + 'epural': ['epural', 'perula', 'pleura'], + 'epuration': ['epuration', 'eupatorin'], + 'equal': ['equal', 'quale', 'queal'], + 'equalable': ['aquabelle', 'equalable'], + 'equiangle': ['angelique', 'equiangle'], + 'equinity': ['equinity', 'inequity'], + 'equip': ['equip', 'pique'], + 'equitable': ['equitable', 'quietable'], + 'equitist': ['equitist', 'quietist'], + 'equus': ['equus', 'usque'], + 'er': ['er', 're'], + 'era': ['aer', 'are', 'ear', 'era', 'rea'], + 'erade': ['eared', 'erade'], + 'eradicant': ['carinated', 'eradicant'], + 'eradicator': ['corradiate', 'cortaderia', 'eradicator'], + 'eral': ['earl', 'eral', 'lear', 'real'], + 'eranist': ['asterin', 'eranist', 'restain', 'stainer', 'starnie', 'stearin'], + 'erase': ['easer', 'erase'], + 'erased': ['erased', 'reseda', 'seared'], + 'eraser': ['eraser', 'searer'], + 'erasmian': ['erasmian', 'raiseman'], + 'erasmus': ['assumer', 'erasmus', 'masseur'], + 'erastian': ['artesian', 'asterina', 'asternia', 'erastian', 'seatrain'], + 'erastus': ['erastus', 'ressaut'], + 'erava': ['avera', 'erava'], + 'erbia': ['barie', 'beira', 'erbia', 'rebia'], + 'erbium': ['erbium', 'imbrue'], + 'erd': ['erd', 'red'], + 'ere': ['eer', 'ere', 'ree'], + 'erect': ['crete', 'erect'], + 'erectable': ['celebrate', 'erectable'], + 'erecting': ['erecting', 'gentrice'], + 'erection': ['erection', 'neoteric', 'nocerite', 'renotice'], + 'eremic': ['eremic', 'merice'], + 'eremital': ['eremital', 'materiel'], + 'erept': ['erept', 'peter', 'petre'], + 'ereptic': ['ereptic', 'precite', 'receipt'], + 'ereption': ['ereption', 'tropeine'], + 'erethic': ['erethic', 'etheric', 'heretic', 'heteric', 'teicher'], + 'erethism': ['erethism', 'etherism', 'heterism'], + 'erethismic': ['erethismic', 'hetericism'], + 'erethistic': ['erethistic', 'hetericist'], + 'eretrian': ['arretine', 'eretrian', 'eritrean', 'retainer'], + 'erg': ['erg', 'ger', 'reg'], + 'ergal': ['argel', 'ergal', 'garle', 'glare', 'lager', 'large', 'regal'], + 'ergamine': ['ergamine', 'merginae'], + 'ergane': ['egeran', 'enrage', 'ergane', 'genear', 'genera'], + 'ergastic': ['agrestic', 'ergastic'], + 'ergates': ['ergates', 'gearset', 'geaster'], + 'ergoism': ['ergoism', 'ogreism'], + 'ergomaniac': ['ergomaniac', 'grecomania'], + 'ergon': ['ergon', 'genro', 'goner', 'negro'], + 'ergot': ['ergot', 'rotge'], + 'ergotamine': ['angiometer', 'ergotamine', 'geometrina'], + 'ergotin': ['ergotin', 'genitor', 'negrito', 'ogtiern', 'trigone'], + 'ergusia': ['ergusia', 'gerusia', 'sarigue'], + 'eria': ['aire', 'eria'], + 'erian': ['erian', 'irena', 'reina'], + 'eric': ['eric', 'rice'], + 'erica': ['acier', 'aeric', 'ceria', 'erica'], + 'ericad': ['acider', 'ericad'], + 'erical': ['carlie', 'claire', 'eclair', 'erical'], + 'erichtoid': ['dichroite', 'erichtoid', 'theriodic'], + 'erigenia': ['aegirine', 'erigenia'], + 'erigeron': ['erigeron', 'reignore'], + 'erik': ['erik', 'kier', 'reki'], + 'erineum': ['erineum', 'unireme'], + 'erinose': ['erinose', 'roseine'], + 'eristalis': ['eristalis', 'serialist'], + 'eristic': ['ectiris', 'eristic'], + 'eristical': ['eristical', 'realistic'], + 'erithacus': ['erithacus', 'eucharist'], + 'eritrean': ['arretine', 'eretrian', 'eritrean', 'retainer'], + 'erma': ['erma', 'mare', 'rame', 'ream'], + 'ermani': ['ermani', 'marine', 'remain'], + 'ermines': ['ermines', 'inermes'], + 'erne': ['erne', 'neer', 'reen'], + 'ernest': ['ernest', 'nester', 'resent', 'streen'], + 'ernie': ['ernie', 'ierne', 'irene'], + 'ernst': ['ernst', 'stern'], + 'erode': ['doree', 'erode'], + 'eros': ['eros', 'rose', 'sero', 'sore'], + 'erose': ['erose', 'soree'], + 'erotesis': ['erotesis', 'isostere'], + 'erotic': ['erotic', 'tercio'], + 'erotical': ['calorite', 'erotical', 'loricate'], + 'eroticism': ['eroticism', 'isometric', 'meroistic', 'trioecism'], + 'erotism': ['erotism', 'mortise', 'trisome'], + 'erotogenic': ['erotogenic', 'geocronite', 'orogenetic'], + 'errabund': ['errabund', 'unbarred'], + 'errand': ['darner', 'darren', 'errand', 'rander', 'redarn'], + 'errant': ['arrent', 'errant', 'ranter', 'ternar'], + 'errantia': ['artarine', 'errantia'], + 'erratic': ['cartier', 'cirrate', 'erratic'], + 'erratum': ['erratum', 'maturer'], + 'erring': ['erring', 'rering', 'ringer'], + 'errite': ['errite', 'reiter', 'retier', 'retire', 'tierer'], + 'ers': ['ers', 'ser'], + 'ersar': ['ersar', 'raser', 'serra'], + 'erse': ['erse', 'rees', 'seer', 'sere'], + 'erthen': ['erthen', 'henter', 'nether', 'threne'], + 'eruc': ['cure', 'ecru', 'eruc'], + 'eruciform': ['eruciform', 'urceiform'], + 'erucin': ['curine', 'erucin', 'neuric'], + 'erucivorous': ['erucivorous', 'overcurious'], + 'eruct': ['cruet', 'eruct', 'recut', 'truce'], + 'eruction': ['eruction', 'neurotic'], + 'erugate': ['erugate', 'guetare'], + 'erumpent': ['erumpent', 'untemper'], + 'eruption': ['eruption', 'unitrope'], + 'erwin': ['erwin', 'rewin', 'winer'], + 'eryngium': ['eryngium', 'gynerium'], + 'eryon': ['eryon', 'onery'], + 'eryops': ['eryops', 'osprey'], + 'erythea': ['erythea', 'hetaery', 'yeather'], + 'erythrin': ['erythrin', 'tyrrheni'], + 'erythrophage': ['erythrophage', 'heterography'], + 'erythrophyllin': ['erythrophyllin', 'phylloerythrin'], + 'erythropia': ['erythropia', 'pyrotheria'], + 'es': ['es', 'se'], + 'esca': ['case', 'esca'], + 'escalan': ['escalan', 'scalena'], + 'escalin': ['celsian', 'escalin', 'sanicle', 'secalin'], + 'escaloped': ['copleased', 'escaloped'], + 'escapement': ['escapement', 'espacement'], + 'escaper': ['escaper', 'respace'], + 'escarp': ['casper', 'escarp', 'parsec', 'scrape', 'secpar', 'spacer'], + 'eschar': ['arches', 'chaser', 'eschar', 'recash', 'search'], + 'eschara': ['asearch', 'eschara'], + 'escheator': ['escheator', 'tocharese'], + 'escobilla': ['escobilla', 'obeliscal'], + 'escolar': ['escolar', 'solacer'], + 'escort': ['corset', 'cortes', 'coster', 'escort', 'scoter', 'sector'], + 'escortment': ['centermost', 'escortment'], + 'escrol': ['closer', 'cresol', 'escrol'], + 'escropulo': ['escropulo', 'supercool'], + 'esculent': ['esculent', 'unselect'], + 'esculin': ['esculin', 'incluse'], + 'esere': ['esere', 'reese', 'resee'], + 'esexual': ['esexual', 'sexuale'], + 'eshin': ['eshin', 'shine'], + 'esiphonal': ['esiphonal', 'phaseolin'], + 'esker': ['esker', 'keres', 'reesk', 'seker', 'skeer', 'skere'], + 'eskualdun': ['eskualdun', 'euskaldun'], + 'eskuara': ['eskuara', 'euskara'], + 'esne': ['ense', 'esne', 'nese', 'seen', 'snee'], + 'esophagogastrostomy': ['esophagogastrostomy', 'gastroesophagostomy'], + 'esopus': ['esopus', 'spouse'], + 'esoterical': ['cesarolite', 'esoterical'], + 'esoterist': ['esoterist', 'trisetose'], + 'esotrope': ['esotrope', 'proteose'], + 'esotropia': ['aportoise', 'esotropia'], + 'espacement': ['escapement', 'espacement'], + 'espadon': ['espadon', 'spadone'], + 'esparto': ['esparto', 'petrosa', 'seaport'], + 'esperantic': ['esperantic', 'interspace'], + 'esperantido': ['desperation', 'esperantido'], + 'esperantism': ['esperantism', 'strepsinema'], + 'esperanto': ['esperanto', 'personate'], + 'espial': ['espial', 'lipase', 'pelias'], + 'espier': ['espier', 'peiser'], + 'espinal': ['espinal', 'pinales', 'spaniel'], + 'espino': ['espino', 'sepion'], + 'espringal': ['espringal', 'presignal', 'relapsing'], + 'esquire': ['esquire', 'risquee'], + 'essence': ['essence', 'senesce'], + 'essenism': ['essenism', 'messines'], + 'essie': ['essie', 'seise'], + 'essling': ['essling', 'singles'], + 'essoin': ['essoin', 'ossein'], + 'essonite': ['essonite', 'ossetine'], + 'essorant': ['assentor', 'essorant', 'starnose'], + 'estamene': ['easement', 'estamene'], + 'esteem': ['esteem', 'mestee'], + 'estella': ['estella', 'sellate'], + 'ester': ['ester', + 'estre', + 'reest', + 'reset', + 'steer', + 'stere', + 'stree', + 'terse', + 'tsere'], + 'esterlin': ['enlister', 'esterlin', 'listener', 'relisten'], + 'esterling': ['esterling', 'steerling'], + 'estevin': ['estevin', 'tensive'], + 'esth': ['esth', 'hest', 'seth'], + 'esther': ['esther', 'hester', 'theres'], + 'estivage': ['estivage', 'vegasite'], + 'estoc': ['coset', 'estoc', 'scote'], + 'estonian': ['estonian', 'nasonite'], + 'estop': ['estop', 'stoep', 'stope'], + 'estradiol': ['estradiol', 'idolaster'], + 'estrange': ['estrange', 'segreant', 'sergeant', 'sternage'], + 'estray': ['atresy', 'estray', 'reasty', 'stayer'], + 'estre': ['ester', + 'estre', + 'reest', + 'reset', + 'steer', + 'stere', + 'stree', + 'terse', + 'tsere'], + 'estreat': ['estreat', 'restate', 'retaste'], + 'estrepe': ['estrepe', 'resteep', 'steeper'], + 'estriate': ['estriate', 'treatise'], + 'estrin': ['estrin', 'insert', 'sinter', 'sterin', 'triens'], + 'estriol': ['estriol', 'torsile'], + 'estrogen': ['estrogen', 'gerontes'], + 'estrone': ['enstore', 'estrone', 'storeen', 'tornese'], + 'estrous': ['estrous', 'oestrus', 'sestuor', 'tussore'], + 'estrual': ['arustle', 'estrual', 'saluter', 'saulter'], + 'estufa': ['estufa', 'fusate'], + 'eta': ['ate', 'eat', 'eta', 'tae', 'tea'], + 'etacism': ['cameist', 'etacism', 'sematic'], + 'etacist': ['etacist', 'statice'], + 'etalon': ['etalon', 'tolane'], + 'etamin': ['etamin', 'inmate', 'taimen', 'tamein'], + 'etamine': ['amenite', 'etamine', 'matinee'], + 'etch': ['chet', 'etch', 'tche', 'tech'], + 'etcher': ['cherte', 'etcher'], + 'eternal': ['alterne', 'enteral', 'eternal', 'teleran', 'teneral'], + 'eternalism': ['eternalism', 'streamline'], + 'eternity': ['entirety', 'eternity'], + 'etesian': ['etesian', 'senaite'], + 'ethal': ['ethal', 'lathe', 'leath'], + 'ethan': ['enhat', 'ethan', 'nathe', 'neath', 'thane'], + 'ethanal': ['anthela', 'ethanal'], + 'ethane': ['ethane', 'taheen'], + 'ethanediol': ['endothelia', 'ethanediol', 'ethenoidal'], + 'ethanim': ['ethanim', 'hematin'], + 'ethanoyl': ['entohyal', 'ethanoyl'], + 'ethel': ['ethel', 'lethe'], + 'ethenoidal': ['endothelia', 'ethanediol', 'ethenoidal'], + 'ether': ['ether', 'rethe', 'theer', 'there', 'three'], + 'etheria': ['ehretia', 'etheria'], + 'etheric': ['erethic', 'etheric', 'heretic', 'heteric', 'teicher'], + 'etherin': ['enherit', 'etherin', 'neither', 'therein'], + 'etherion': ['etherion', 'hereinto', 'heronite'], + 'etherism': ['erethism', 'etherism', 'heterism'], + 'etherization': ['etherization', 'heterization'], + 'etherize': ['etherize', 'heterize'], + 'ethicism': ['ethicism', 'shemitic'], + 'ethicist': ['ethicist', 'thecitis', 'theistic'], + 'ethics': ['ethics', 'sethic'], + 'ethid': ['edith', 'ethid'], + 'ethine': ['ethine', 'theine'], + 'ethiop': ['ethiop', 'ophite', 'peitho'], + 'ethmoidal': ['ethmoidal', 'oldhamite'], + 'ethmosphenoid': ['ethmosphenoid', 'sphenoethmoid'], + 'ethmosphenoidal': ['ethmosphenoidal', 'sphenoethmoidal'], + 'ethnal': ['ethnal', 'hantle', 'lathen', 'thenal'], + 'ethnical': ['chainlet', 'ethnical'], + 'ethnological': ['allothogenic', 'ethnological'], + 'ethnos': ['ethnos', 'honest'], + 'ethography': ['ethography', 'hyetograph'], + 'ethologic': ['ethologic', 'theologic'], + 'ethological': ['ethological', 'lethologica', 'theological'], + 'ethology': ['ethology', 'theology'], + 'ethos': ['ethos', 'shote', 'those'], + 'ethylic': ['ethylic', 'techily'], + 'ethylin': ['ethylin', 'thienyl'], + 'etna': ['ante', 'aten', 'etna', 'nate', 'neat', 'taen', 'tane', 'tean'], + 'etnean': ['etnean', 'neaten'], + 'etonian': ['enation', 'etonian'], + 'etruscan': ['etruscan', 'recusant'], + 'etta': ['etta', 'tate', 'teat'], + 'ettarre': ['ettarre', 'retreat', 'treater'], + 'ettle': ['ettle', 'tetel'], + 'etua': ['aute', 'etua'], + 'euaster': ['austere', 'euaster'], + 'eucalypteol': ['eucalypteol', 'eucalyptole'], + 'eucalyptole': ['eucalypteol', 'eucalyptole'], + 'eucatropine': ['eucatropine', 'neurectopia'], + 'eucharis': ['acheirus', 'eucharis'], + 'eucharist': ['erithacus', 'eucharist'], + 'euchlaena': ['acheulean', 'euchlaena'], + 'eulogism': ['eulogism', 'uglisome'], + 'eumolpus': ['eumolpus', 'plumeous'], + 'eunomia': ['eunomia', 'moineau'], + 'eunomy': ['eunomy', 'euonym'], + 'euonym': ['eunomy', 'euonym'], + 'eupatorin': ['epuration', 'eupatorin'], + 'euplastic': ['euplastic', 'spiculate'], + 'euploid': ['epuloid', 'euploid'], + 'euproctis': ['crepitous', 'euproctis', 'uroseptic'], + 'eurindic': ['dineuric', 'eurindic'], + 'eurus': ['eurus', 'usure'], + 'euscaro': ['acerous', 'carouse', 'euscaro'], + 'euskaldun': ['eskualdun', 'euskaldun'], + 'euskara': ['eskuara', 'euskara'], + 'eusol': ['eusol', 'louse'], + 'eutannin': ['eutannin', 'uninnate'], + 'eutaxic': ['auxetic', 'eutaxic'], + 'eutheria': ['eutheria', 'hauerite'], + 'eutropic': ['eutropic', 'outprice'], + 'eva': ['ave', 'eva'], + 'evade': ['deave', 'eaved', 'evade'], + 'evader': ['evader', 'verdea'], + 'evadne': ['advene', 'evadne'], + 'evan': ['evan', 'nave', 'vane'], + 'evanish': ['evanish', 'inshave'], + 'evase': ['eaves', 'evase', 'seave'], + 'eve': ['eve', 'vee'], + 'evea': ['eave', 'evea'], + 'evection': ['civetone', 'evection'], + 'evejar': ['evejar', 'rajeev'], + 'evelyn': ['evelyn', 'evenly'], + 'even': ['even', 'neve', 'veen'], + 'evener': ['evener', 'veneer'], + 'evenly': ['evelyn', 'evenly'], + 'evens': ['evens', 'seven'], + 'eveque': ['eveque', 'queeve'], + 'ever': ['ever', 'reve', 'veer'], + 'evert': ['evert', 'revet'], + 'everwhich': ['everwhich', 'whichever'], + 'everwho': ['everwho', 'however', 'whoever'], + 'every': ['every', 'veery'], + 'evestar': ['evestar', 'versate'], + 'evict': ['civet', 'evict'], + 'evil': ['evil', 'levi', 'live', 'veil', 'vile', 'vlei'], + 'evildoer': ['evildoer', 'overidle'], + 'evilhearted': ['evilhearted', 'vilehearted'], + 'evilly': ['evilly', 'lively', 'vilely'], + 'evilness': ['evilness', 'liveness', 'veinless', 'vileness', 'vineless'], + 'evince': ['cevine', 'evince', 'venice'], + 'evisite': ['evisite', 'visitee'], + 'evitation': ['evitation', 'novitiate'], + 'evocator': ['evocator', 'overcoat'], + 'evodia': ['evodia', 'ovidae'], + 'evoker': ['evoker', 'revoke'], + 'evolver': ['evolver', 'revolve'], + 'ewder': ['dewer', 'ewder', 'rewed'], + 'ewe': ['ewe', 'wee'], + 'ewer': ['ewer', 'were'], + 'exacter': ['exacter', 'excreta'], + 'exalt': ['exalt', 'latex'], + 'exam': ['amex', 'exam', 'xema'], + 'examinate': ['examinate', 'exanimate', 'metaxenia'], + 'examination': ['examination', 'exanimation'], + 'exanimate': ['examinate', 'exanimate', 'metaxenia'], + 'exanimation': ['examination', 'exanimation'], + 'exasperation': ['exasperation', 'xenoparasite'], + 'exaudi': ['adieux', 'exaudi'], + 'excarnation': ['centraxonia', 'excarnation'], + 'excecation': ['cacoxenite', 'excecation'], + 'except': ['except', 'expect'], + 'exceptant': ['exceptant', 'expectant'], + 'exceptive': ['exceptive', 'expective'], + 'excitation': ['excitation', 'intoxicate'], + 'excitor': ['excitor', 'xerotic'], + 'excreta': ['exacter', 'excreta'], + 'excurse': ['excurse', 'excuser'], + 'excuser': ['excurse', 'excuser'], + 'exert': ['exert', 'exter'], + 'exhilarate': ['exhilarate', 'heteraxial'], + 'exist': ['exist', 'sixte'], + 'exocarp': ['exocarp', 'praecox'], + 'exon': ['exon', 'oxen'], + 'exordia': ['exordia', 'exradio'], + 'exotic': ['coxite', 'exotic'], + 'expatiater': ['expatiater', 'expatriate'], + 'expatriate': ['expatiater', 'expatriate'], + 'expect': ['except', 'expect'], + 'expectant': ['exceptant', 'expectant'], + 'expective': ['exceptive', 'expective'], + 'expirator': ['expirator', 'operatrix'], + 'expiree': ['expiree', 'peixere'], + 'explicator': ['explicator', 'extropical'], + 'expressionism': ['expressionism', 'misexpression'], + 'exradio': ['exordia', 'exradio'], + 'extend': ['dentex', 'extend'], + 'exter': ['exert', 'exter'], + 'exterminate': ['antiextreme', 'exterminate'], + 'extirpationist': ['extirpationist', 'sextipartition'], + 'extra': ['extra', 'retax', 'taxer'], + 'extradural': ['dextraural', 'extradural'], + 'extropical': ['explicator', 'extropical'], + 'exultancy': ['exultancy', 'unexactly'], + 'ey': ['ey', 'ye'], + 'eyah': ['ahey', 'eyah', 'yeah'], + 'eyas': ['easy', 'eyas'], + 'eye': ['eye', 'yee'], + 'eyed': ['eyed', 'yede'], + 'eyen': ['eyen', 'eyne'], + 'eyer': ['eyer', 'eyre', 'yere'], + 'eyn': ['eyn', 'nye', 'yen'], + 'eyne': ['eyen', 'eyne'], + 'eyot': ['eyot', 'yote'], + 'eyra': ['aery', 'eyra', 'yare', 'year'], + 'eyre': ['eyer', 'eyre', 'yere'], + 'ezba': ['baze', 'ezba'], + 'ezra': ['ezra', 'raze'], + 'facebread': ['barefaced', 'facebread'], + 'facer': ['facer', 'farce'], + 'faciend': ['faciend', 'fancied'], + 'facile': ['facile', 'filace'], + 'faciobrachial': ['brachiofacial', 'faciobrachial'], + 'faciocervical': ['cervicofacial', 'faciocervical'], + 'factable': ['factable', 'labefact'], + 'factional': ['factional', 'falcation'], + 'factish': ['catfish', 'factish'], + 'facture': ['facture', 'furcate'], + 'facula': ['facula', 'faucal'], + 'fade': ['deaf', 'fade'], + 'fader': ['fader', 'farde'], + 'faery': ['faery', 'freya'], + 'fagoter': ['aftergo', 'fagoter'], + 'faience': ['faience', 'fiancee'], + 'fail': ['alif', 'fail'], + 'fain': ['fain', 'naif'], + 'fainly': ['fainly', 'naifly'], + 'faint': ['faint', 'fanti'], + 'fair': ['fair', 'fiar', 'raif'], + 'fake': ['fake', 'feak'], + 'faker': ['faker', 'freak'], + 'fakery': ['fakery', 'freaky'], + 'fakir': ['fakir', 'fraik', 'kafir', 'rafik'], + 'falcation': ['factional', 'falcation'], + 'falco': ['falco', 'focal'], + 'falconet': ['conflate', 'falconet'], + 'fallback': ['backfall', 'fallback'], + 'faller': ['faller', 'refall'], + 'fallfish': ['fallfish', 'fishfall'], + 'fallible': ['fallible', 'fillable'], + 'falling': ['falling', 'fingall'], + 'falser': ['falser', 'flaser'], + 'faltboat': ['faltboat', 'flatboat'], + 'falutin': ['falutin', 'flutina'], + 'falx': ['falx', 'flax'], + 'fameless': ['fameless', 'selfsame'], + 'famelessness': ['famelessness', 'selfsameness'], + 'famine': ['famine', 'infame'], + 'fancied': ['faciend', 'fancied'], + 'fangle': ['fangle', 'flange'], + 'fannia': ['fannia', 'fianna'], + 'fanti': ['faint', 'fanti'], + 'far': ['far', 'fra'], + 'farad': ['daraf', 'farad'], + 'farce': ['facer', 'farce'], + 'farcetta': ['afteract', 'artefact', 'farcetta', 'farctate'], + 'farctate': ['afteract', 'artefact', 'farcetta', 'farctate'], + 'farde': ['fader', 'farde'], + 'fardel': ['alfred', 'fardel'], + 'fare': ['fare', 'fear', 'frae', 'rafe'], + 'farfel': ['farfel', 'raffle'], + 'faring': ['faring', 'frangi'], + 'farl': ['farl', 'ralf'], + 'farleu': ['earful', 'farleu', 'ferula'], + 'farm': ['farm', 'fram'], + 'farmable': ['farmable', 'framable'], + 'farmer': ['farmer', 'framer'], + 'farming': ['farming', 'framing'], + 'farnesol': ['farnesol', 'forensal'], + 'faro': ['faro', 'fora'], + 'farolito': ['farolito', 'footrail'], + 'farse': ['farse', 'frase'], + 'farset': ['farset', 'faster', 'strafe'], + 'farsi': ['farsi', 'sarif'], + 'fascio': ['fascio', 'fiasco'], + 'fasher': ['afresh', 'fasher', 'ferash'], + 'fashioner': ['fashioner', 'refashion'], + 'fast': ['fast', 'saft'], + 'fasten': ['fasten', 'nefast', 'stefan'], + 'fastener': ['fastener', 'fenestra', 'refasten'], + 'faster': ['farset', 'faster', 'strafe'], + 'fasthold': ['fasthold', 'holdfast'], + 'fastland': ['fastland', 'landfast'], + 'fat': ['aft', 'fat'], + 'fatal': ['aflat', 'fatal'], + 'fate': ['atef', 'fate', 'feat'], + 'fated': ['defat', 'fated'], + 'father': ['father', 'freath', 'hafter'], + 'faucal': ['facula', 'faucal'], + 'faucet': ['faucet', 'fucate'], + 'faulter': ['faulter', 'refutal', 'tearful'], + 'faultfind': ['faultfind', 'findfault'], + 'faunish': ['faunish', 'nusfiah'], + 'faunist': ['faunist', 'fustian', 'infaust'], + 'favorer': ['favorer', 'overfar', 'refavor'], + 'fayles': ['fayles', 'safely'], + 'feague': ['feague', 'feuage'], + 'feak': ['fake', 'feak'], + 'feal': ['alef', 'feal', 'flea', 'leaf'], + 'fealty': ['fealty', 'featly'], + 'fear': ['fare', 'fear', 'frae', 'rafe'], + 'feastful': ['feastful', 'sufflate'], + 'feat': ['atef', 'fate', 'feat'], + 'featherbed': ['befathered', 'featherbed'], + 'featherer': ['featherer', 'hereafter'], + 'featly': ['fealty', 'featly'], + 'feckly': ['feckly', 'flecky'], + 'fecundate': ['fecundate', 'unfaceted'], + 'fecundator': ['fecundator', 'unfactored'], + 'federate': ['defeater', 'federate', 'redefeat'], + 'feeder': ['feeder', 'refeed'], + 'feeding': ['feeding', 'feigned'], + 'feel': ['feel', 'flee'], + 'feeler': ['feeler', 'refeel', 'reflee'], + 'feer': ['feer', 'free', 'reef'], + 'feering': ['feering', 'feigner', 'freeing', 'reefing', 'refeign'], + 'feetless': ['feetless', 'feteless'], + 'fei': ['fei', 'fie', 'ife'], + 'feif': ['feif', 'fife'], + 'feigned': ['feeding', 'feigned'], + 'feigner': ['feering', 'feigner', 'freeing', 'reefing', 'refeign'], + 'feil': ['feil', 'file', 'leif', 'lief', 'life'], + 'feint': ['feint', 'fient'], + 'feis': ['feis', 'fise', 'sife'], + 'feist': ['feist', 'stife'], + 'felapton': ['felapton', 'pantofle'], + 'felid': ['felid', 'field'], + 'feline': ['enfile', 'enlief', 'enlife', 'feline'], + 'felinity': ['felinity', 'finitely'], + 'fels': ['fels', 'self'], + 'felt': ['felt', 'flet', 'left'], + 'felter': ['felter', 'telfer', 'trefle'], + 'felting': ['felting', 'neftgil'], + 'feltness': ['feltness', 'leftness'], + 'felwort': ['elfwort', 'felwort'], + 'feminal': ['feminal', 'inflame'], + 'femora': ['femora', 'foamer'], + 'femorocaudal': ['caudofemoral', 'femorocaudal'], + 'femorotibial': ['femorotibial', 'tibiofemoral'], + 'femur': ['femur', 'fumer'], + 'fen': ['fen', 'nef'], + 'fender': ['fender', 'ferned'], + 'fenestra': ['fastener', 'fenestra', 'refasten'], + 'feodary': ['feodary', 'foreday'], + 'feral': ['feral', 'flare'], + 'ferash': ['afresh', 'fasher', 'ferash'], + 'feria': ['afire', 'feria'], + 'ferine': ['ferine', 'refine'], + 'ferison': ['ferison', 'foresin'], + 'ferity': ['ferity', 'freity'], + 'ferk': ['ferk', 'kerf'], + 'ferling': ['ferling', 'flinger', 'refling'], + 'ferly': ['ferly', 'flyer', 'refly'], + 'fermail': ['fermail', 'fermila'], + 'fermenter': ['fermenter', 'referment'], + 'fermila': ['fermail', 'fermila'], + 'ferned': ['fender', 'ferned'], + 'ferri': ['ferri', 'firer', 'freir', 'frier'], + 'ferrihydrocyanic': ['ferrihydrocyanic', 'hydroferricyanic'], + 'ferrohydrocyanic': ['ferrohydrocyanic', 'hydroferrocyanic'], + 'ferry': ['ferry', 'freyr', 'fryer'], + 'fertil': ['fertil', 'filter', 'lifter', 'relift', 'trifle'], + 'ferula': ['earful', 'farleu', 'ferula'], + 'ferule': ['ferule', 'fueler', 'refuel'], + 'ferulic': ['ferulic', 'lucifer'], + 'fervidity': ['devitrify', 'fervidity'], + 'festination': ['festination', 'infestation', 'sinfonietta'], + 'fet': ['eft', 'fet'], + 'fetal': ['aleft', 'alfet', 'fetal', 'fleta'], + 'fetcher': ['fetcher', 'refetch'], + 'feteless': ['feetless', 'feteless'], + 'fetial': ['fetial', 'filate', 'lafite', 'leafit'], + 'fetish': ['fetish', 'fishet'], + 'fetor': ['fetor', 'forte', 'ofter'], + 'fetter': ['fetter', 'frette'], + 'feuage': ['feague', 'feuage'], + 'feudalism': ['feudalism', 'sulfamide'], + 'feudally': ['delayful', 'feudally'], + 'feulamort': ['feulamort', 'formulate'], + 'fi': ['fi', 'if'], + 'fiance': ['fiance', 'inface'], + 'fiancee': ['faience', 'fiancee'], + 'fianna': ['fannia', 'fianna'], + 'fiar': ['fair', 'fiar', 'raif'], + 'fiard': ['fiard', 'fraid'], + 'fiasco': ['fascio', 'fiasco'], + 'fiber': ['bifer', 'brief', 'fiber'], + 'fibered': ['debrief', 'defiber', 'fibered'], + 'fiberless': ['briefless', 'fiberless', 'fibreless'], + 'fiberware': ['fiberware', 'fibreware'], + 'fibreless': ['briefless', 'fiberless', 'fibreless'], + 'fibreware': ['fiberware', 'fibreware'], + 'fibroadenoma': ['adenofibroma', 'fibroadenoma'], + 'fibroangioma': ['angiofibroma', 'fibroangioma'], + 'fibrochondroma': ['chondrofibroma', 'fibrochondroma'], + 'fibrocystoma': ['cystofibroma', 'fibrocystoma'], + 'fibrolipoma': ['fibrolipoma', 'lipofibroma'], + 'fibromucous': ['fibromucous', 'mucofibrous'], + 'fibromyoma': ['fibromyoma', 'myofibroma'], + 'fibromyxoma': ['fibromyxoma', 'myxofibroma'], + 'fibromyxosarcoma': ['fibromyxosarcoma', 'myxofibrosarcoma'], + 'fibroneuroma': ['fibroneuroma', 'neurofibroma'], + 'fibroserous': ['fibroserous', 'serofibrous'], + 'fiche': ['chief', 'fiche'], + 'fickleness': ['fickleness', 'fleckiness'], + 'fickly': ['fickly', 'flicky'], + 'fico': ['coif', 'fico', 'foci'], + 'fictional': ['cliftonia', 'fictional'], + 'ficula': ['ficula', 'fulica'], + 'fiddler': ['fiddler', 'flidder'], + 'fidele': ['defile', 'fidele'], + 'fidget': ['fidget', 'gifted'], + 'fidicula': ['fidicula', 'fiducial'], + 'fiducial': ['fidicula', 'fiducial'], + 'fie': ['fei', 'fie', 'ife'], + 'fiedlerite': ['fiedlerite', 'friedelite'], + 'field': ['felid', 'field'], + 'fielded': ['defiled', 'fielded'], + 'fielder': ['defiler', 'fielder'], + 'fieldman': ['fieldman', 'inflamed'], + 'fiendish': ['fiendish', 'finished'], + 'fient': ['feint', 'fient'], + 'fiery': ['fiery', 'reify'], + 'fife': ['feif', 'fife'], + 'fifteener': ['fifteener', 'teneriffe'], + 'fifty': ['fifty', 'tiffy'], + 'fig': ['fig', 'gif'], + 'fighter': ['fighter', 'freight', 'refight'], + 'figurate': ['figurate', 'fruitage'], + 'fike': ['efik', 'fike'], + 'filace': ['facile', 'filace'], + 'filago': ['filago', 'gifola'], + 'filao': ['filao', 'folia'], + 'filar': ['filar', 'flair', 'frail'], + 'filate': ['fetial', 'filate', 'lafite', 'leafit'], + 'file': ['feil', 'file', 'leif', 'lief', 'life'], + 'filelike': ['filelike', 'lifelike'], + 'filer': ['filer', 'flier', 'lifer', 'rifle'], + 'filet': ['filet', 'flite'], + 'fillable': ['fallible', 'fillable'], + 'filler': ['filler', 'refill'], + 'filo': ['filo', 'foil', 'lifo'], + 'filter': ['fertil', 'filter', 'lifter', 'relift', 'trifle'], + 'filterer': ['filterer', 'refilter'], + 'filthless': ['filthless', 'shelflist'], + 'filtrable': ['filtrable', 'flirtable'], + 'filtration': ['filtration', 'flirtation'], + 'finale': ['afenil', 'finale'], + 'finder': ['finder', 'friend', 'redfin', 'refind'], + 'findfault': ['faultfind', 'findfault'], + 'fine': ['enif', 'fine', 'neif', 'nife'], + 'finely': ['finely', 'lenify'], + 'finer': ['finer', 'infer'], + 'finesser': ['finesser', 'rifeness'], + 'fingall': ['falling', 'fingall'], + 'finger': ['finger', 'fringe'], + 'fingerer': ['fingerer', 'refinger'], + 'fingerflower': ['fingerflower', 'fringeflower'], + 'fingerless': ['fingerless', 'fringeless'], + 'fingerlet': ['fingerlet', 'fringelet'], + 'fingu': ['fingu', 'fungi'], + 'finical': ['finical', 'lanific'], + 'finished': ['fiendish', 'finished'], + 'finisher': ['finisher', 'refinish'], + 'finitely': ['felinity', 'finitely'], + 'finkel': ['elfkin', 'finkel'], + 'finlet': ['finlet', 'infelt'], + 'finner': ['finner', 'infern'], + 'firca': ['afric', 'firca'], + 'fire': ['fire', 'reif', 'rife'], + 'fireable': ['afebrile', 'balefire', 'fireable'], + 'firearm': ['firearm', 'marfire'], + 'fireback': ['backfire', 'fireback'], + 'fireburn': ['burnfire', 'fireburn'], + 'fired': ['fired', 'fried'], + 'fireplug': ['fireplug', 'gripeful'], + 'firer': ['ferri', 'firer', 'freir', 'frier'], + 'fireshaft': ['fireshaft', 'tasheriff'], + 'firestone': ['firestone', 'forestine'], + 'firetop': ['firetop', 'potifer'], + 'firm': ['firm', 'frim'], + 'first': ['first', 'frist'], + 'firth': ['firth', 'frith'], + 'fise': ['feis', 'fise', 'sife'], + 'fishbone': ['bonefish', 'fishbone'], + 'fisheater': ['fisheater', 'sherifate'], + 'fisher': ['fisher', 'sherif'], + 'fishery': ['fishery', 'sherify'], + 'fishet': ['fetish', 'fishet'], + 'fishfall': ['fallfish', 'fishfall'], + 'fishlet': ['fishlet', 'leftish'], + 'fishpond': ['fishpond', 'pondfish'], + 'fishpool': ['fishpool', 'foolship'], + 'fishwood': ['fishwood', 'woodfish'], + 'fissury': ['fissury', 'russify'], + 'fist': ['fist', 'sift'], + 'fisted': ['fisted', 'sifted'], + 'fister': ['fister', 'resift', 'sifter', 'strife'], + 'fisting': ['fisting', 'sifting'], + 'fitout': ['fitout', 'outfit'], + 'fitter': ['fitter', 'tifter'], + 'fixer': ['fixer', 'refix'], + 'flageolet': ['flageolet', 'folletage'], + 'flair': ['filar', 'flair', 'frail'], + 'flamant': ['flamant', 'flatman'], + 'flame': ['flame', 'fleam'], + 'flamed': ['flamed', 'malfed'], + 'flandowser': ['flandowser', 'sandflower'], + 'flange': ['fangle', 'flange'], + 'flare': ['feral', 'flare'], + 'flaser': ['falser', 'flaser'], + 'flasher': ['flasher', 'reflash'], + 'flatboat': ['faltboat', 'flatboat'], + 'flatman': ['flamant', 'flatman'], + 'flatwise': ['flatwise', 'saltwife'], + 'flaunt': ['flaunt', 'unflat'], + 'flax': ['falx', 'flax'], + 'flea': ['alef', 'feal', 'flea', 'leaf'], + 'fleam': ['flame', 'fleam'], + 'fleay': ['fleay', 'leafy'], + 'fleche': ['fleche', 'fleech'], + 'flecker': ['flecker', 'freckle'], + 'fleckiness': ['fickleness', 'fleckiness'], + 'flecky': ['feckly', 'flecky'], + 'fled': ['delf', 'fled'], + 'flee': ['feel', 'flee'], + 'fleech': ['fleche', 'fleech'], + 'fleer': ['fleer', 'refel'], + 'flemish': ['flemish', 'himself'], + 'flenser': ['flenser', 'fresnel'], + 'flesh': ['flesh', 'shelf'], + 'fleshed': ['deflesh', 'fleshed'], + 'fleshen': ['enflesh', 'fleshen'], + 'flesher': ['flesher', 'herself'], + 'fleshful': ['fleshful', 'shelfful'], + 'fleshiness': ['elfishness', 'fleshiness'], + 'fleshy': ['fleshy', 'shelfy'], + 'flet': ['felt', 'flet', 'left'], + 'fleta': ['aleft', 'alfet', 'fetal', 'fleta'], + 'fleuret': ['fleuret', 'treeful'], + 'flew': ['flew', 'welf'], + 'flexed': ['deflex', 'flexed'], + 'flexured': ['flexured', 'refluxed'], + 'flicky': ['fickly', 'flicky'], + 'flidder': ['fiddler', 'flidder'], + 'flier': ['filer', 'flier', 'lifer', 'rifle'], + 'fligger': ['fligger', 'friggle'], + 'flinger': ['ferling', 'flinger', 'refling'], + 'flingy': ['flingy', 'flying'], + 'flirtable': ['filtrable', 'flirtable'], + 'flirtation': ['filtration', 'flirtation'], + 'flirter': ['flirter', 'trifler'], + 'flirting': ['flirting', 'trifling'], + 'flirtingly': ['flirtingly', 'triflingly'], + 'flit': ['flit', 'lift'], + 'flite': ['filet', 'flite'], + 'fliting': ['fliting', 'lifting'], + 'flitter': ['flitter', 'triflet'], + 'flo': ['flo', 'lof'], + 'float': ['aloft', 'float', 'flota'], + 'floater': ['floater', 'florate', 'refloat'], + 'flobby': ['bobfly', 'flobby'], + 'flodge': ['flodge', 'fodgel'], + 'floe': ['floe', 'fole'], + 'flog': ['flog', 'golf'], + 'flogger': ['flogger', 'frogleg'], + 'floodable': ['bloodleaf', 'floodable'], + 'flooder': ['flooder', 'reflood'], + 'floodwater': ['floodwater', 'toadflower', 'waterflood'], + 'floorer': ['floorer', 'refloor'], + 'florate': ['floater', 'florate', 'refloat'], + 'florentine': ['florentine', 'nonfertile'], + 'floret': ['floret', 'forlet', 'lofter', 'torfel'], + 'floria': ['floria', 'foliar'], + 'floriate': ['floriate', 'foralite'], + 'florican': ['florican', 'fornical'], + 'floridan': ['floridan', 'florinda'], + 'florinda': ['floridan', 'florinda'], + 'flot': ['flot', 'loft'], + 'flota': ['aloft', 'float', 'flota'], + 'flounder': ['flounder', 'reunfold', 'unfolder'], + 'flour': ['flour', 'fluor'], + 'flourisher': ['flourisher', 'reflourish'], + 'flouting': ['flouting', 'outfling'], + 'flow': ['flow', 'fowl', 'wolf'], + 'flower': ['flower', 'fowler', 'reflow', 'wolfer'], + 'flowered': ['deflower', 'flowered'], + 'flowerer': ['flowerer', 'reflower'], + 'flowery': ['flowery', 'fowlery'], + 'flowing': ['flowing', 'fowling'], + 'floyd': ['floyd', 'foldy'], + 'fluavil': ['fluavil', 'fluvial', 'vialful'], + 'flucan': ['canful', 'flucan'], + 'fluctuant': ['fluctuant', 'untactful'], + 'flue': ['flue', 'fuel'], + 'fluent': ['fluent', 'netful', 'unfelt', 'unleft'], + 'fluidly': ['dullify', 'fluidly'], + 'flukewort': ['flukewort', 'flutework'], + 'fluor': ['flour', 'fluor'], + 'fluorate': ['fluorate', 'outflare'], + 'fluorinate': ['antifouler', 'fluorinate', 'uniflorate'], + 'fluorine': ['fluorine', 'neurofil'], + 'fluorobenzene': ['benzofluorene', 'fluorobenzene'], + 'flusher': ['flusher', 'reflush'], + 'flushing': ['flushing', 'lungfish'], + 'fluster': ['fluster', 'restful'], + 'flustra': ['flustra', 'starful'], + 'flutework': ['flukewort', 'flutework'], + 'flutina': ['falutin', 'flutina'], + 'fluvial': ['fluavil', 'fluvial', 'vialful'], + 'fluxer': ['fluxer', 'reflux'], + 'flyblow': ['blowfly', 'flyblow'], + 'flyer': ['ferly', 'flyer', 'refly'], + 'flying': ['flingy', 'flying'], + 'fo': ['fo', 'of'], + 'foal': ['foal', 'loaf', 'olaf'], + 'foamer': ['femora', 'foamer'], + 'focal': ['falco', 'focal'], + 'foci': ['coif', 'fico', 'foci'], + 'focuser': ['focuser', 'refocus'], + 'fodge': ['defog', 'fodge'], + 'fodgel': ['flodge', 'fodgel'], + 'fogeater': ['fogeater', 'foregate'], + 'fogo': ['fogo', 'goof'], + 'foil': ['filo', 'foil', 'lifo'], + 'foister': ['foister', 'forties'], + 'folden': ['enfold', 'folden', 'fondle'], + 'folder': ['folder', 'refold'], + 'foldy': ['floyd', 'foldy'], + 'fole': ['floe', 'fole'], + 'folia': ['filao', 'folia'], + 'foliar': ['floria', 'foliar'], + 'foliature': ['foliature', 'toluifera'], + 'folletage': ['flageolet', 'folletage'], + 'fomenter': ['fomenter', 'refoment'], + 'fondle': ['enfold', 'folden', 'fondle'], + 'fondu': ['fondu', 'found'], + 'foo': ['foo', 'ofo'], + 'fool': ['fool', 'loof', 'olof'], + 'foolship': ['fishpool', 'foolship'], + 'footer': ['footer', 'refoot'], + 'foothot': ['foothot', 'hotfoot'], + 'footler': ['footler', 'rooflet'], + 'footpad': ['footpad', 'padfoot'], + 'footrail': ['farolito', 'footrail'], + 'foots': ['foots', 'sfoot', 'stoof'], + 'footsore': ['footsore', 'sorefoot'], + 'foppish': ['foppish', 'fopship'], + 'fopship': ['foppish', 'fopship'], + 'for': ['for', 'fro', 'orf'], + 'fora': ['faro', 'fora'], + 'foralite': ['floriate', 'foralite'], + 'foramen': ['foramen', 'foreman'], + 'forcemeat': ['aftercome', 'forcemeat'], + 'forcement': ['coferment', 'forcement'], + 'fore': ['fore', 'froe', 'ofer'], + 'forecast': ['cofaster', 'forecast'], + 'forecaster': ['forecaster', 'reforecast'], + 'forecover': ['forecover', 'overforce'], + 'foreday': ['feodary', 'foreday'], + 'forefit': ['forefit', 'forfeit'], + 'foregate': ['fogeater', 'foregate'], + 'foregirth': ['foregirth', 'foreright'], + 'forego': ['forego', 'goofer'], + 'forel': ['forel', 'rolfe'], + 'forelive': ['forelive', 'overfile'], + 'foreman': ['foramen', 'foreman'], + 'foremean': ['foremean', 'forename'], + 'forename': ['foremean', 'forename'], + 'forensal': ['farnesol', 'forensal'], + 'forensic': ['forensic', 'forinsec'], + 'forepart': ['forepart', 'prefator'], + 'foreright': ['foregirth', 'foreright'], + 'foresend': ['defensor', 'foresend'], + 'foresign': ['foresign', 'foresing'], + 'foresin': ['ferison', 'foresin'], + 'foresing': ['foresign', 'foresing'], + 'forest': ['forest', 'forset', 'foster'], + 'forestage': ['forestage', 'fosterage'], + 'forestal': ['astrofel', 'forestal'], + 'forestate': ['forestate', 'foretaste'], + 'forested': ['deforest', 'forested'], + 'forestem': ['forestem', 'fretsome'], + 'forester': ['forester', 'fosterer', 'reforest'], + 'forestine': ['firestone', 'forestine'], + 'foretaste': ['forestate', 'foretaste'], + 'foreutter': ['foreutter', 'outferret'], + 'forfeit': ['forefit', 'forfeit'], + 'forfeiter': ['forfeiter', 'reforfeit'], + 'forgeman': ['forgeman', 'formagen'], + 'forinsec': ['forensic', 'forinsec'], + 'forint': ['forint', 'fortin'], + 'forlet': ['floret', 'forlet', 'lofter', 'torfel'], + 'form': ['form', 'from'], + 'formagen': ['forgeman', 'formagen'], + 'formalin': ['formalin', 'informal', 'laniform'], + 'formally': ['formally', 'formylal'], + 'formed': ['deform', 'formed'], + 'former': ['former', 'reform'], + 'formica': ['aciform', 'formica'], + 'formicina': ['aciniform', 'formicina'], + 'formicoidea': ['aecidioform', 'formicoidea'], + 'formin': ['formin', 'inform'], + 'forminate': ['forminate', 'fremontia', 'taeniform'], + 'formulae': ['formulae', 'fumarole'], + 'formulaic': ['cauliform', 'formulaic', 'fumarolic'], + 'formulate': ['feulamort', 'formulate'], + 'formulator': ['formulator', 'torulaform'], + 'formylal': ['formally', 'formylal'], + 'fornical': ['florican', 'fornical'], + 'fornicated': ['deforciant', 'fornicated'], + 'forpit': ['forpit', 'profit'], + 'forritsome': ['forritsome', 'ostreiform'], + 'forrue': ['forrue', 'fourer', 'fourre', 'furore'], + 'forset': ['forest', 'forset', 'foster'], + 'forst': ['forst', 'frost'], + 'fort': ['fort', 'frot'], + 'forte': ['fetor', 'forte', 'ofter'], + 'forth': ['forth', 'froth'], + 'forthcome': ['forthcome', 'homecroft'], + 'forthy': ['forthy', 'frothy'], + 'forties': ['foister', 'forties'], + 'fortin': ['forint', 'fortin'], + 'forward': ['forward', 'froward'], + 'forwarder': ['forwarder', 'reforward'], + 'forwardly': ['forwardly', 'frowardly'], + 'forwardness': ['forwardness', 'frowardness'], + 'foster': ['forest', 'forset', 'foster'], + 'fosterage': ['forestage', 'fosterage'], + 'fosterer': ['forester', 'fosterer', 'reforest'], + 'fot': ['fot', 'oft'], + 'fou': ['fou', 'ouf'], + 'fouler': ['fouler', 'furole'], + 'found': ['fondu', 'found'], + 'foundationer': ['foundationer', 'refoundation'], + 'founder': ['founder', 'refound'], + 'foundling': ['foundling', 'unfolding'], + 'fourble': ['beflour', 'fourble'], + 'fourer': ['forrue', 'fourer', 'fourre', 'furore'], + 'fourre': ['forrue', 'fourer', 'fourre', 'furore'], + 'fowl': ['flow', 'fowl', 'wolf'], + 'fowler': ['flower', 'fowler', 'reflow', 'wolfer'], + 'fowlery': ['flowery', 'fowlery'], + 'fowling': ['flowing', 'fowling'], + 'fra': ['far', 'fra'], + 'frache': ['chafer', 'frache'], + 'frae': ['fare', 'fear', 'frae', 'rafe'], + 'fraghan': ['fraghan', 'harfang'], + 'fraid': ['fiard', 'fraid'], + 'fraik': ['fakir', 'fraik', 'kafir', 'rafik'], + 'frail': ['filar', 'flair', 'frail'], + 'fraiser': ['fraiser', 'frasier'], + 'fram': ['farm', 'fram'], + 'framable': ['farmable', 'framable'], + 'frame': ['frame', 'fream'], + 'framer': ['farmer', 'framer'], + 'framing': ['farming', 'framing'], + 'frangi': ['faring', 'frangi'], + 'frantic': ['frantic', 'infarct', 'infract'], + 'frase': ['farse', 'frase'], + 'frasier': ['fraiser', 'frasier'], + 'frat': ['frat', 'raft'], + 'fratcheous': ['fratcheous', 'housecraft'], + 'frater': ['frater', 'rafter'], + 'frayed': ['defray', 'frayed'], + 'freak': ['faker', 'freak'], + 'freaky': ['fakery', 'freaky'], + 'fream': ['frame', 'fream'], + 'freath': ['father', 'freath', 'hafter'], + 'freckle': ['flecker', 'freckle'], + 'free': ['feer', 'free', 'reef'], + 'freed': ['defer', 'freed'], + 'freeing': ['feering', 'feigner', 'freeing', 'reefing', 'refeign'], + 'freeman': ['enframe', 'freeman'], + 'freer': ['freer', 'refer'], + 'fregata': ['fregata', 'raftage'], + 'fregatae': ['afterage', 'fregatae'], + 'freight': ['fighter', 'freight', 'refight'], + 'freir': ['ferri', 'firer', 'freir', 'frier'], + 'freit': ['freit', 'refit'], + 'freity': ['ferity', 'freity'], + 'fremontia': ['forminate', 'fremontia', 'taeniform'], + 'frenetic': ['frenetic', 'infecter', 'reinfect'], + 'freshener': ['freshener', 'refreshen'], + 'fresnel': ['flenser', 'fresnel'], + 'fret': ['fret', 'reft', 'tref'], + 'fretful': ['fretful', 'truffle'], + 'fretsome': ['forestem', 'fretsome'], + 'frette': ['fetter', 'frette'], + 'freya': ['faery', 'freya'], + 'freyr': ['ferry', 'freyr', 'fryer'], + 'fried': ['fired', 'fried'], + 'friedelite': ['fiedlerite', 'friedelite'], + 'friend': ['finder', 'friend', 'redfin', 'refind'], + 'frier': ['ferri', 'firer', 'freir', 'frier'], + 'friesic': ['friesic', 'serific'], + 'friggle': ['fligger', 'friggle'], + 'frightener': ['frightener', 'refrighten'], + 'frigolabile': ['frigolabile', 'glorifiable'], + 'frike': ['frike', 'kefir'], + 'frim': ['firm', 'frim'], + 'fringe': ['finger', 'fringe'], + 'fringeflower': ['fingerflower', 'fringeflower'], + 'fringeless': ['fingerless', 'fringeless'], + 'fringelet': ['fingerlet', 'fringelet'], + 'frist': ['first', 'frist'], + 'frit': ['frit', 'rift'], + 'frith': ['firth', 'frith'], + 'friulian': ['friulian', 'unifilar'], + 'fro': ['for', 'fro', 'orf'], + 'froe': ['fore', 'froe', 'ofer'], + 'frogleg': ['flogger', 'frogleg'], + 'from': ['form', 'from'], + 'fronter': ['fronter', 'refront'], + 'frontonasal': ['frontonasal', 'nasofrontal'], + 'frontooccipital': ['frontooccipital', 'occipitofrontal'], + 'frontoorbital': ['frontoorbital', 'orbitofrontal'], + 'frontoparietal': ['frontoparietal', 'parietofrontal'], + 'frontotemporal': ['frontotemporal', 'temporofrontal'], + 'frontpiece': ['frontpiece', 'perfection'], + 'frost': ['forst', 'frost'], + 'frosted': ['defrost', 'frosted'], + 'frot': ['fort', 'frot'], + 'froth': ['forth', 'froth'], + 'frothy': ['forthy', 'frothy'], + 'froward': ['forward', 'froward'], + 'frowardly': ['forwardly', 'frowardly'], + 'frowardness': ['forwardness', 'frowardness'], + 'fruitage': ['figurate', 'fruitage'], + 'fruitless': ['fruitless', 'resistful'], + 'frush': ['frush', 'shurf'], + 'frustule': ['frustule', 'sulfuret'], + 'fruticulose': ['fruticulose', 'luctiferous'], + 'fryer': ['ferry', 'freyr', 'fryer'], + 'fucales': ['caseful', 'fucales'], + 'fucate': ['faucet', 'fucate'], + 'fuel': ['flue', 'fuel'], + 'fueler': ['ferule', 'fueler', 'refuel'], + 'fuerte': ['fuerte', 'refute'], + 'fuirena': ['fuirena', 'unafire'], + 'fulcrate': ['crateful', 'fulcrate'], + 'fulica': ['ficula', 'fulica'], + 'fulmar': ['armful', 'fulmar'], + 'fulminatory': ['fulminatory', 'unformality'], + 'fulminous': ['fulminous', 'sulfonium'], + 'fulwa': ['awful', 'fulwa'], + 'fumarole': ['formulae', 'fumarole'], + 'fumarolic': ['cauliform', 'formulaic', 'fumarolic'], + 'fumble': ['beflum', 'fumble'], + 'fumer': ['femur', 'fumer'], + 'fundable': ['fundable', 'unfabled'], + 'funder': ['funder', 'refund'], + 'funebrial': ['funebrial', 'unfriable'], + 'funeral': ['earnful', 'funeral'], + 'fungal': ['fungal', 'unflag'], + 'fungi': ['fingu', 'fungi'], + 'funori': ['funori', 'furoin'], + 'fur': ['fur', 'urf'], + 'fural': ['alfur', 'fural'], + 'furan': ['furan', 'unfar'], + 'furbish': ['burfish', 'furbish'], + 'furbisher': ['furbisher', 'refurbish'], + 'furcal': ['carful', 'furcal'], + 'furcate': ['facture', 'furcate'], + 'furler': ['furler', 'refurl'], + 'furnish': ['furnish', 'runfish'], + 'furnisher': ['furnisher', 'refurnish'], + 'furoin': ['funori', 'furoin'], + 'furole': ['fouler', 'furole'], + 'furore': ['forrue', 'fourer', 'fourre', 'furore'], + 'furstone': ['furstone', 'unforest'], + 'fusate': ['estufa', 'fusate'], + 'fusteric': ['fusteric', 'scutifer'], + 'fustian': ['faunist', 'fustian', 'infaust'], + 'gab': ['bag', 'gab'], + 'gabbler': ['gabbler', 'grabble'], + 'gabe': ['egba', 'gabe'], + 'gabelle': ['gabelle', 'gelable'], + 'gabelled': ['gabelled', 'geldable'], + 'gabi': ['agib', 'biga', 'gabi'], + 'gabion': ['bagnio', 'gabion', 'gobian'], + 'gabioned': ['badigeon', 'gabioned'], + 'gable': ['bagel', 'belga', 'gable', 'gleba'], + 'gablock': ['backlog', 'gablock'], + 'gaboon': ['abongo', 'gaboon'], + 'gad': ['dag', 'gad'], + 'gadaba': ['badaga', 'dagaba', 'gadaba'], + 'gadder': ['gadder', 'graded'], + 'gaddi': ['gaddi', 'gadid'], + 'gade': ['aged', 'egad', 'gade'], + 'gadger': ['dagger', 'gadger', 'ragged'], + 'gadget': ['gadget', 'tagged'], + 'gadid': ['gaddi', 'gadid'], + 'gadinine': ['gadinine', 'indigena'], + 'gadolinite': ['deligation', 'gadolinite', 'gelatinoid'], + 'gadroon': ['dragoon', 'gadroon'], + 'gadroonage': ['dragoonage', 'gadroonage'], + 'gaduin': ['anguid', 'gaduin'], + 'gael': ['gael', 'gale', 'geal'], + 'gaen': ['agen', 'gaen', 'gane', 'gean', 'gena'], + 'gaet': ['gaet', 'gate', 'geat', 'geta'], + 'gaetulan': ['angulate', 'gaetulan'], + 'gager': ['agger', 'gager', 'regga'], + 'gahnite': ['gahnite', 'heating'], + 'gahrwali': ['gahrwali', 'garhwali'], + 'gaiassa': ['assagai', 'gaiassa'], + 'gail': ['gail', 'gali', 'gila', 'glia'], + 'gain': ['gain', 'inga', 'naig', 'ngai'], + 'gaincall': ['gaincall', 'gallican'], + 'gaine': ['angie', 'gaine'], + 'gainer': ['arenig', 'earing', 'gainer', 'reagin', 'regain'], + 'gainless': ['gainless', 'glassine'], + 'gainly': ['gainly', 'laying'], + 'gainsayer': ['asynergia', 'gainsayer'], + 'gainset': ['easting', + 'gainset', + 'genista', + 'ingesta', + 'seating', + 'signate', + 'teasing'], + 'gainstrive': ['gainstrive', 'vinegarist'], + 'gainturn': ['gainturn', 'naturing'], + 'gaiter': ['gaiter', 'tairge', 'triage'], + 'gaize': ['gaize', 'ziega'], + 'gaj': ['gaj', 'jag'], + 'gal': ['gal', 'lag'], + 'gala': ['agal', 'agla', 'alga', 'gala'], + 'galactonic': ['cognatical', 'galactonic'], + 'galatae': ['galatae', 'galatea'], + 'galatea': ['galatae', 'galatea'], + 'gale': ['gael', 'gale', 'geal'], + 'galea': ['algae', 'galea'], + 'galee': ['aegle', 'eagle', 'galee'], + 'galei': ['agiel', 'agile', 'galei'], + 'galeid': ['algedi', 'galeid'], + 'galen': ['agnel', 'angel', 'angle', 'galen', 'genal', 'glean', 'lagen'], + 'galena': ['alnage', 'angela', 'galena', 'lagena'], + 'galenian': ['alangine', 'angelina', 'galenian'], + 'galenic': ['angelic', 'galenic'], + 'galenical': ['angelical', 'englacial', 'galenical'], + 'galenist': ['galenist', 'genitals', 'stealing'], + 'galenite': ['galenite', 'legatine'], + 'galeoid': ['galeoid', 'geoidal'], + 'galera': ['aglare', 'alegar', 'galera', 'laager'], + 'galet': ['aglet', 'galet'], + 'galewort': ['galewort', 'waterlog'], + 'galey': ['agley', 'galey'], + 'galga': ['galga', 'glaga'], + 'gali': ['gail', 'gali', 'gila', 'glia'], + 'galidia': ['agialid', 'galidia'], + 'galik': ['galik', 'glaik'], + 'galilean': ['galilean', 'gallinae'], + 'galiot': ['galiot', 'latigo'], + 'galla': ['algal', 'galla'], + 'gallate': ['gallate', 'tallage'], + 'gallein': ['gallein', 'galline', 'nigella'], + 'galleria': ['allergia', 'galleria'], + 'gallery': ['allergy', 'gallery', 'largely', 'regally'], + 'galli': ['galli', 'glial'], + 'gallican': ['gaincall', 'gallican'], + 'gallicole': ['collegial', 'gallicole'], + 'gallinae': ['galilean', 'gallinae'], + 'galline': ['gallein', 'galline', 'nigella'], + 'gallnut': ['gallnut', 'nutgall'], + 'galloper': ['galloper', 'regallop'], + 'gallotannate': ['gallotannate', 'tannogallate'], + 'gallotannic': ['gallotannic', 'tannogallic'], + 'gallstone': ['gallstone', 'stonegall'], + 'gallybagger': ['gallybagger', 'gallybeggar'], + 'gallybeggar': ['gallybagger', 'gallybeggar'], + 'galore': ['galore', 'gaoler'], + 'galtonia': ['galtonia', 'notalgia'], + 'galvanopsychic': ['galvanopsychic', 'psychogalvanic'], + 'galvanothermometer': ['galvanothermometer', 'thermogalvanometer'], + 'gam': ['gam', 'mag'], + 'gamaliel': ['gamaliel', 'melalgia'], + 'gamashes': ['gamashes', 'smashage'], + 'gamasid': ['gamasid', 'magadis'], + 'gambado': ['dagomba', 'gambado'], + 'gambier': ['gambier', 'imbarge'], + 'gambler': ['gambler', 'gambrel'], + 'gambrel': ['gambler', 'gambrel'], + 'game': ['egma', 'game', 'mage'], + 'gamely': ['gamely', 'gleamy', 'mygale'], + 'gamene': ['gamene', 'manege', 'menage'], + 'gamete': ['gamete', 'metage'], + 'gametogenic': ['gametogenic', 'gamogenetic', 'geomagnetic'], + 'gamic': ['gamic', 'magic'], + 'gamin': ['gamin', 'mangi'], + 'gaming': ['gaming', 'gigman'], + 'gamma': ['gamma', 'magma'], + 'gammer': ['gammer', 'gramme'], + 'gamogenetic': ['gametogenic', 'gamogenetic', 'geomagnetic'], + 'gamori': ['gamori', 'gomari', 'gromia'], + 'gan': ['gan', 'nag'], + 'ganam': ['amang', 'ganam', 'manga'], + 'ganch': ['chang', 'ganch'], + 'gander': ['danger', 'gander', 'garden', 'ranged'], + 'gandul': ['gandul', 'unglad'], + 'gane': ['agen', 'gaen', 'gane', 'gean', 'gena'], + 'gangan': ['gangan', 'nagnag'], + 'ganger': ['ganger', 'grange', 'nagger'], + 'ganging': ['ganging', 'nagging'], + 'gangism': ['gangism', 'gigsman'], + 'ganglioneuron': ['ganglioneuron', 'neuroganglion'], + 'gangly': ['gangly', 'naggly'], + 'ganguela': ['ganguela', 'language'], + 'gangway': ['gangway', 'waygang'], + 'ganister': ['astringe', 'ganister', 'gantries'], + 'ganoidal': ['diagonal', 'ganoidal', 'gonadial'], + 'ganoidean': ['ganoidean', 'indogaean'], + 'ganoidian': ['agoniadin', 'anangioid', 'ganoidian'], + 'ganosis': ['agnosis', 'ganosis'], + 'gansel': ['angles', 'gansel'], + 'gant': ['gant', 'gnat', 'tang'], + 'ganta': ['ganta', 'tanga'], + 'ganton': ['ganton', 'tongan'], + 'gantries': ['astringe', 'ganister', 'gantries'], + 'gantry': ['gantry', 'gyrant'], + 'ganymede': ['ganymede', 'megadyne'], + 'ganzie': ['agnize', 'ganzie'], + 'gaol': ['gaol', 'goal', 'gola', 'olga'], + 'gaoler': ['galore', 'gaoler'], + 'gaon': ['agon', 'ango', 'gaon', 'goan', 'gona'], + 'gaonic': ['agonic', 'angico', 'gaonic', 'goniac'], + 'gapa': ['gapa', 'paga'], + 'gape': ['gape', 'page', 'peag', 'pega'], + 'gaper': ['gaper', 'grape', 'pager', 'parge'], + 'gar': ['gar', 'gra', 'rag'], + 'gara': ['agar', 'agra', 'gara', 'raga'], + 'garamond': ['dragoman', 'garamond', 'ondagram'], + 'garance': ['carnage', 'cranage', 'garance'], + 'garb': ['brag', 'garb', 'grab'], + 'garbel': ['garbel', 'garble'], + 'garble': ['garbel', 'garble'], + 'garbless': ['bragless', 'garbless'], + 'garce': ['cager', 'garce', 'grace'], + 'garcinia': ['agaricin', 'garcinia'], + 'gardeen': ['derange', 'enraged', 'gardeen', 'gerenda', 'grandee', 'grenade'], + 'garden': ['danger', 'gander', 'garden', 'ranged'], + 'gardened': ['deranged', 'gardened'], + 'gardener': ['deranger', 'gardener'], + 'gardenful': ['dangerful', 'gardenful'], + 'gardenia': ['drainage', 'gardenia'], + 'gardenin': ['gardenin', 'grenadin'], + 'gardenless': ['dangerless', 'gardenless'], + 'gare': ['ager', 'agre', 'gare', 'gear', 'rage'], + 'gareh': ['gareh', 'gerah'], + 'garetta': ['garetta', 'rattage', 'regatta'], + 'garewaite': ['garewaite', 'waiterage'], + 'garfish': ['garfish', 'ragfish'], + 'garget': ['garget', 'tagger'], + 'gargety': ['gargety', 'raggety'], + 'gargle': ['gargle', 'gregal', 'lagger', 'raggle'], + 'garhwali': ['gahrwali', 'garhwali'], + 'garial': ['argali', 'garial'], + 'garle': ['argel', 'ergal', 'garle', 'glare', 'lager', 'large', 'regal'], + 'garment': ['garment', 'margent'], + 'garmenture': ['garmenture', 'reargument'], + 'garn': ['garn', 'gnar', 'rang'], + 'garnel': ['angler', 'arleng', 'garnel', 'largen', 'rangle', 'regnal'], + 'garner': ['garner', 'ranger'], + 'garnet': ['argent', 'garnet', 'garten', 'tanger'], + 'garneter': ['argenter', 'garneter'], + 'garnetiferous': ['argentiferous', 'garnetiferous'], + 'garnets': ['angster', 'garnets', 'nagster', 'strange'], + 'garnett': ['garnett', 'gnatter', 'gratten', 'tergant'], + 'garnice': ['anergic', 'garnice', 'garniec', 'geranic', 'grecian'], + 'garniec': ['anergic', 'garnice', 'garniec', 'geranic', 'grecian'], + 'garnish': ['garnish', 'rashing'], + 'garnished': ['degarnish', 'garnished'], + 'garnisher': ['garnisher', 'regarnish'], + 'garo': ['argo', 'garo', 'gora'], + 'garran': ['garran', 'ragnar'], + 'garret': ['garret', 'garter', 'grater', 'targer'], + 'garreted': ['garreted', 'gartered'], + 'garroter': ['garroter', 'regrator'], + 'garten': ['argent', 'garnet', 'garten', 'tanger'], + 'garter': ['garret', 'garter', 'grater', 'targer'], + 'gartered': ['garreted', 'gartered'], + 'gartering': ['gartering', 'regrating'], + 'garum': ['garum', 'murga'], + 'gary': ['gary', 'gray'], + 'gas': ['gas', 'sag'], + 'gasan': ['gasan', 'sanga'], + 'gash': ['gash', 'shag'], + 'gasless': ['gasless', 'glasses', 'sagless'], + 'gaslit': ['algist', 'gaslit'], + 'gasoliner': ['gasoliner', 'seignoral'], + 'gasper': ['gasper', 'sparge'], + 'gast': ['gast', 'stag'], + 'gaster': ['gaster', 'stager'], + 'gastrin': ['gastrin', 'staring'], + 'gastroenteritis': ['enterogastritis', 'gastroenteritis'], + 'gastroesophagostomy': ['esophagogastrostomy', 'gastroesophagostomy'], + 'gastrohepatic': ['gastrohepatic', 'hepatogastric'], + 'gastronomic': ['gastronomic', 'monogastric'], + 'gastropathic': ['gastropathic', 'graphostatic'], + 'gastrophrenic': ['gastrophrenic', 'nephrogastric', 'phrenogastric'], + 'gastrular': ['gastrular', 'stragular'], + 'gat': ['gat', 'tag'], + 'gate': ['gaet', 'gate', 'geat', 'geta'], + 'gateman': ['gateman', 'magenta', 'magnate', 'magneta'], + 'gater': ['gater', 'grate', 'great', 'greta', 'retag', 'targe'], + 'gateward': ['drawgate', 'gateward'], + 'gateway': ['gateway', 'getaway', 'waygate'], + 'gatherer': ['gatherer', 'regather'], + 'gator': ['argot', 'gator', 'gotra', 'groat'], + 'gatter': ['gatter', 'target'], + 'gaucho': ['gaucho', 'guacho'], + 'gaufer': ['agrufe', 'gaufer', 'gaufre'], + 'gauffer': ['gauffer', 'gauffre'], + 'gauffre': ['gauffer', 'gauffre'], + 'gaufre': ['agrufe', 'gaufer', 'gaufre'], + 'gaul': ['gaul', 'gula'], + 'gaulin': ['gaulin', 'lingua'], + 'gaulter': ['gaulter', 'tegular'], + 'gaum': ['gaum', 'muga'], + 'gaun': ['gaun', 'guan', 'guna', 'uang'], + 'gaunt': ['gaunt', 'tunga'], + 'gaur': ['gaur', 'guar', 'ruga'], + 'gaura': ['gaura', 'guara'], + 'gaurian': ['anguria', 'gaurian', 'guarani'], + 'gave': ['gave', 'vage', 'vega'], + 'gavyuti': ['gavyuti', 'vaguity'], + 'gaw': ['gaw', 'wag'], + 'gawn': ['gawn', 'gnaw', 'wang'], + 'gay': ['agy', 'gay'], + 'gaz': ['gaz', 'zag'], + 'gazel': ['gazel', 'glaze'], + 'gazer': ['gazer', 'graze'], + 'gazon': ['gazon', 'zogan'], + 'gazy': ['gazy', 'zyga'], + 'geal': ['gael', 'gale', 'geal'], + 'gean': ['agen', 'gaen', 'gane', 'gean', 'gena'], + 'gear': ['ager', 'agre', 'gare', 'gear', 'rage'], + 'geared': ['agreed', 'geared'], + 'gearless': ['eelgrass', 'gearless', 'rageless'], + 'gearman': ['gearman', 'manager'], + 'gearset': ['ergates', 'gearset', 'geaster'], + 'geaster': ['ergates', 'gearset', 'geaster'], + 'geat': ['gaet', 'gate', 'geat', 'geta'], + 'gebur': ['bugre', 'gebur'], + 'ged': ['deg', 'ged'], + 'gedder': ['dredge', 'gedder'], + 'geest': ['egest', 'geest', 'geste'], + 'gegger': ['gegger', 'gregge'], + 'geheimrat': ['geheimrat', 'hermitage'], + 'gein': ['gein', 'gien'], + 'geira': ['geira', 'regia'], + 'geison': ['geison', 'isogen'], + 'geissospermine': ['geissospermine', 'spermiogenesis'], + 'gel': ['gel', 'leg'], + 'gelable': ['gabelle', 'gelable'], + 'gelasian': ['anglaise', 'gelasian'], + 'gelastic': ['gelastic', 'gestical'], + 'gelatin': ['atingle', 'gelatin', 'genital', 'langite', 'telinga'], + 'gelatinate': ['gelatinate', 'nagatelite'], + 'gelatined': ['delignate', 'gelatined'], + 'gelatinizer': ['gelatinizer', 'integralize'], + 'gelatinoid': ['deligation', 'gadolinite', 'gelatinoid'], + 'gelation': ['gelation', 'lagonite', 'legation'], + 'gelatose': ['gelatose', 'segolate'], + 'geldable': ['gabelled', 'geldable'], + 'gelder': ['gelder', 'ledger', 'redleg'], + 'gelding': ['gelding', 'ledging'], + 'gelid': ['gelid', 'glide'], + 'gelidness': ['gelidness', 'glideness'], + 'gelosin': ['gelosin', 'lignose'], + 'gem': ['gem', 'meg'], + 'gemara': ['gemara', 'ramage'], + 'gemaric': ['gemaric', 'grimace', 'megaric'], + 'gemarist': ['gemarist', 'magister', 'sterigma'], + 'gematria': ['gematria', 'maritage'], + 'gemul': ['gemul', 'glume'], + 'gena': ['agen', 'gaen', 'gane', 'gean', 'gena'], + 'genal': ['agnel', 'angel', 'angle', 'galen', 'genal', 'glean', 'lagen'], + 'genarch': ['changer', 'genarch'], + 'gendarme': ['edgerman', 'gendarme'], + 'genear': ['egeran', 'enrage', 'ergane', 'genear', 'genera'], + 'geneat': ['geneat', 'negate', 'tegean'], + 'genera': ['egeran', 'enrage', 'ergane', 'genear', 'genera'], + 'generable': ['generable', 'greenable'], + 'general': ['enlarge', 'general', 'gleaner'], + 'generalist': ['easterling', 'generalist'], + 'generall': ['allergen', 'generall'], + 'generation': ['generation', 'renegation'], + 'generic': ['energic', 'generic'], + 'generical': ['energical', 'generical'], + 'genesiac': ['agenesic', 'genesiac'], + 'genesial': ['ensilage', 'genesial', 'signalee'], + 'genetical': ['clientage', 'genetical'], + 'genetta': ['genetta', 'tentage'], + 'geneura': ['geneura', 'uneager'], + 'geneva': ['avenge', 'geneva', 'vangee'], + 'genial': ['algine', 'genial', 'linage'], + 'genicular': ['genicular', 'neuralgic'], + 'genie': ['eigne', 'genie'], + 'genion': ['genion', 'inogen'], + 'genipa': ['genipa', 'piegan'], + 'genista': ['easting', + 'gainset', + 'genista', + 'ingesta', + 'seating', + 'signate', + 'teasing'], + 'genistein': ['genistein', 'gentisein'], + 'genital': ['atingle', 'gelatin', 'genital', 'langite', 'telinga'], + 'genitals': ['galenist', 'genitals', 'stealing'], + 'genitival': ['genitival', 'vigilante'], + 'genitocrural': ['crurogenital', 'genitocrural'], + 'genitor': ['ergotin', 'genitor', 'negrito', 'ogtiern', 'trigone'], + 'genitorial': ['genitorial', 'religation'], + 'genitory': ['genitory', 'ortygine'], + 'genitourinary': ['genitourinary', 'urinogenitary'], + 'geniture': ['geniture', 'guerinet'], + 'genizero': ['genizero', 'negroize'], + 'genoa': ['agone', 'genoa'], + 'genoblastic': ['blastogenic', 'genoblastic'], + 'genocidal': ['algedonic', 'genocidal'], + 'genom': ['genom', 'gnome'], + 'genotypical': ['genotypical', 'ptyalogenic'], + 'genre': ['genre', 'green', 'neger', 'reneg'], + 'genro': ['ergon', 'genro', 'goner', 'negro'], + 'gent': ['gent', 'teng'], + 'gentes': ['gentes', 'gesten'], + 'genthite': ['genthite', 'teething'], + 'gentian': ['antigen', 'gentian'], + 'gentianic': ['antigenic', 'gentianic'], + 'gentisein': ['genistein', 'gentisein'], + 'gentle': ['gentle', 'telegn'], + 'gentrice': ['erecting', 'gentrice'], + 'genua': ['augen', 'genua'], + 'genual': ['genual', 'leguan'], + 'genuine': ['genuine', 'ingenue'], + 'genus': ['genus', 'negus'], + 'geo': ['ego', 'geo'], + 'geocentric': ['ectrogenic', 'egocentric', 'geocentric'], + 'geocratic': ['categoric', 'geocratic'], + 'geocronite': ['erotogenic', 'geocronite', 'orogenetic'], + 'geodal': ['algedo', 'geodal'], + 'geode': ['geode', 'ogeed'], + 'geodiatropism': ['diageotropism', 'geodiatropism'], + 'geoduck': ['geoduck', 'goeduck'], + 'geohydrology': ['geohydrology', 'hydrogeology'], + 'geoid': ['diego', 'dogie', 'geoid'], + 'geoidal': ['galeoid', 'geoidal'], + 'geoisotherm': ['geoisotherm', 'isogeotherm'], + 'geomagnetic': ['gametogenic', 'gamogenetic', 'geomagnetic'], + 'geomant': ['geomant', 'magneto', 'megaton', 'montage'], + 'geomantic': ['atmogenic', 'geomantic'], + 'geometrical': ['geometrical', 'glaciometer'], + 'geometrina': ['angiometer', 'ergotamine', 'geometrina'], + 'geon': ['geon', 'gone'], + 'geonim': ['geonim', 'imogen'], + 'georama': ['georama', 'roamage'], + 'geotectonic': ['geotectonic', 'tocogenetic'], + 'geotic': ['geotic', 'goetic'], + 'geotical': ['ectoglia', 'geotical', 'goetical'], + 'geotonic': ['geotonic', 'otogenic'], + 'geoty': ['geoty', 'goety'], + 'ger': ['erg', 'ger', 'reg'], + 'gerah': ['gareh', 'gerah'], + 'geraldine': ['engrailed', 'geraldine'], + 'geranial': ['algerian', 'geranial', 'regalian'], + 'geranic': ['anergic', 'garnice', 'garniec', 'geranic', 'grecian'], + 'geraniol': ['geraniol', 'regional'], + 'geranomorph': ['geranomorph', 'monographer', 'nomographer'], + 'geranyl': ['angerly', 'geranyl'], + 'gerard': ['darger', 'gerard', 'grader', 'redrag', 'regard'], + 'gerastian': ['agrestian', 'gerastian', 'stangeria'], + 'geraty': ['geraty', 'gyrate'], + 'gerb': ['berg', 'gerb'], + 'gerbe': ['gerbe', 'grebe', 'rebeg'], + 'gerbera': ['bargeer', 'gerbera'], + 'gerenda': ['derange', 'enraged', 'gardeen', 'gerenda', 'grandee', 'grenade'], + 'gerendum': ['gerendum', 'unmerged'], + 'gerent': ['gerent', 'regent'], + 'gerenuk': ['gerenuk', 'greenuk'], + 'gerim': ['gerim', 'grime'], + 'gerip': ['gerip', 'gripe'], + 'german': ['engram', 'german', 'manger'], + 'germania': ['germania', 'megarian'], + 'germanics': ['germanics', 'screaming'], + 'germanification': ['germanification', 'remagnification'], + 'germanify': ['germanify', 'remagnify'], + 'germanious': ['germanious', 'gramineous', 'marigenous'], + 'germanist': ['germanist', 'streaming'], + 'germanite': ['germanite', 'germinate', 'gramenite', 'mangerite'], + 'germanly': ['germanly', 'germanyl'], + 'germanyl': ['germanly', 'germanyl'], + 'germinal': ['germinal', 'maligner', 'malinger'], + 'germinant': ['germinant', 'minargent'], + 'germinate': ['germanite', 'germinate', 'gramenite', 'mangerite'], + 'germon': ['germon', 'monger', 'morgen'], + 'geronomite': ['geronomite', 'goniometer'], + 'geront': ['geront', 'tonger'], + 'gerontal': ['argentol', 'gerontal'], + 'gerontes': ['estrogen', 'gerontes'], + 'gerontic': ['gerontic', 'negrotic'], + 'gerontism': ['gerontism', 'monergist'], + 'gerres': ['gerres', 'serger'], + 'gersum': ['gersum', 'mergus'], + 'gerund': ['dunger', 'gerund', 'greund', 'nudger'], + 'gerundive': ['gerundive', 'ungrieved'], + 'gerusia': ['ergusia', 'gerusia', 'sarigue'], + 'gervas': ['gervas', 'graves'], + 'gervase': ['gervase', 'greaves', 'servage'], + 'ges': ['ges', 'seg'], + 'gesan': ['agnes', 'gesan'], + 'gesith': ['gesith', 'steigh'], + 'gesning': ['gesning', 'ginseng'], + 'gest': ['gest', 'steg'], + 'gestapo': ['gestapo', 'postage'], + 'gestate': ['gestate', 'tagetes'], + 'geste': ['egest', 'geest', 'geste'], + 'gesten': ['gentes', 'gesten'], + 'gestical': ['gelastic', 'gestical'], + 'gesticular': ['gesticular', 'scutigeral'], + 'gesture': ['gesture', 'guester'], + 'get': ['get', 'teg'], + 'geta': ['gaet', 'gate', 'geat', 'geta'], + 'getaway': ['gateway', 'getaway', 'waygate'], + 'gettable': ['begettal', 'gettable'], + 'getup': ['getup', 'upget'], + 'geyerite': ['geyerite', 'tigereye'], + 'ghaist': ['ghaist', 'tagish'], + 'ghent': ['ghent', 'thegn'], + 'ghosty': ['ghosty', 'hogsty'], + 'ghoul': ['ghoul', 'lough'], + 'giansar': ['giansar', 'sarangi'], + 'giant': ['giant', 'tangi', 'tiang'], + 'gib': ['big', 'gib'], + 'gibbon': ['gibbon', 'gobbin'], + 'gibel': ['bilge', 'gibel'], + 'gibing': ['biggin', 'gibing'], + 'gid': ['dig', 'gid'], + 'gideonite': ['diogenite', 'gideonite'], + 'gien': ['gein', 'gien'], + 'gienah': ['gienah', 'hangie'], + 'gif': ['fig', 'gif'], + 'gifola': ['filago', 'gifola'], + 'gifted': ['fidget', 'gifted'], + 'gigman': ['gaming', 'gigman'], + 'gigsman': ['gangism', 'gigsman'], + 'gila': ['gail', 'gali', 'gila', 'glia'], + 'gilaki': ['gilaki', 'giliak'], + 'gilbertese': ['gilbertese', 'selbergite'], + 'gilden': ['dingle', 'elding', 'engild', 'gilden'], + 'gilder': ['gilder', 'girdle', 'glider', 'regild', 'ridgel'], + 'gilding': ['gilding', 'gliding'], + 'gileno': ['eloign', 'gileno', 'legion'], + 'giles': ['giles', 'gilse'], + 'giliak': ['gilaki', 'giliak'], + 'giller': ['giller', 'grille', 'regill'], + 'gilo': ['gilo', 'goli'], + 'gilpy': ['gilpy', 'pigly'], + 'gilse': ['giles', 'gilse'], + 'gim': ['gim', 'mig'], + 'gimel': ['gimel', 'glime'], + 'gimmer': ['gimmer', 'grimme', 'megrim'], + 'gimper': ['gimper', 'impreg'], + 'gin': ['gin', 'ing', 'nig'], + 'ginger': ['ginger', 'nigger'], + 'gingery': ['gingery', 'niggery'], + 'ginglymodi': ['ginglymodi', 'ginglymoid'], + 'ginglymoid': ['ginglymodi', 'ginglymoid'], + 'gink': ['gink', 'king'], + 'ginned': ['ending', 'ginned'], + 'ginner': ['enring', 'ginner'], + 'ginney': ['ginney', 'nignye'], + 'ginseng': ['gesning', 'ginseng'], + 'ginward': ['drawing', 'ginward', 'warding'], + 'gio': ['gio', 'goi'], + 'giornata': ['giornata', 'gratiano'], + 'giornatate': ['giornatate', 'tetragonia'], + 'gip': ['gip', 'pig'], + 'gipper': ['gipper', 'grippe'], + 'girandole': ['girandole', 'negroidal'], + 'girasole': ['girasole', 'seraglio'], + 'girba': ['bragi', 'girba'], + 'gird': ['gird', 'grid'], + 'girder': ['girder', 'ridger'], + 'girding': ['girding', 'ridging'], + 'girdingly': ['girdingly', 'ridgingly'], + 'girdle': ['gilder', 'girdle', 'glider', 'regild', 'ridgel'], + 'girdler': ['dirgler', 'girdler'], + 'girdling': ['girdling', 'ridgling'], + 'girling': ['girling', 'rigling'], + 'girn': ['girn', 'grin', 'ring'], + 'girny': ['girny', 'ringy'], + 'girondin': ['girondin', 'nonrigid'], + 'girsle': ['girsle', 'gisler', 'glires', 'grilse'], + 'girt': ['girt', 'grit', 'trig'], + 'girth': ['girth', 'grith', 'right'], + 'gish': ['gish', 'sigh'], + 'gisla': ['gisla', 'ligas', 'sigla'], + 'gisler': ['girsle', 'gisler', 'glires', 'grilse'], + 'git': ['git', 'tig'], + 'gitalin': ['gitalin', 'tailing'], + 'gith': ['gith', 'thig'], + 'gitksan': ['gitksan', 'skating', 'takings'], + 'gittern': ['gittern', 'gritten', 'retting'], + 'giustina': ['giustina', 'ignatius'], + 'giver': ['giver', 'vergi'], + 'glaceing': ['cageling', 'glaceing'], + 'glacier': ['glacier', 'gracile'], + 'glaciometer': ['geometrical', 'glaciometer'], + 'gladdener': ['gladdener', 'glandered', 'regladden'], + 'glaga': ['galga', 'glaga'], + 'glaik': ['galik', 'glaik'], + 'glaiket': ['glaiket', 'taglike'], + 'glair': ['argil', 'glair', 'grail'], + 'glaireous': ['aligerous', 'glaireous'], + 'glaister': ['glaister', 'regalist'], + 'glaive': ['glaive', 'vagile'], + 'glance': ['cangle', 'glance'], + 'glancer': ['cangler', 'glancer', 'reclang'], + 'glancingly': ['clangingly', 'glancingly'], + 'glandered': ['gladdener', 'glandered', 'regladden'], + 'glans': ['glans', 'slang'], + 'glare': ['argel', 'ergal', 'garle', 'glare', 'lager', 'large', 'regal'], + 'glariness': ['glariness', 'grainless'], + 'glary': ['glary', 'gyral'], + 'glasser': ['glasser', 'largess'], + 'glasses': ['gasless', 'glasses', 'sagless'], + 'glassie': ['algesis', 'glassie'], + 'glassine': ['gainless', 'glassine'], + 'glaucin': ['glaucin', 'glucina'], + 'glaucine': ['cuailnge', 'glaucine'], + 'glaum': ['algum', 'almug', 'glaum', 'gluma', 'mulga'], + 'glaur': ['glaur', 'gular'], + 'glaury': ['glaury', 'raguly'], + 'glaver': ['glaver', 'gravel'], + 'glaze': ['gazel', 'glaze'], + 'glazy': ['glazy', 'zygal'], + 'gleamy': ['gamely', 'gleamy', 'mygale'], + 'glean': ['agnel', 'angel', 'angle', 'galen', 'genal', 'glean', 'lagen'], + 'gleaner': ['enlarge', 'general', 'gleaner'], + 'gleary': ['argyle', 'gleary'], + 'gleba': ['bagel', 'belga', 'gable', 'gleba'], + 'glebal': ['begall', 'glebal'], + 'glede': ['glede', 'gleed', 'ledge'], + 'gledy': ['gledy', 'ledgy'], + 'gleed': ['glede', 'gleed', 'ledge'], + 'gleeman': ['gleeman', 'melange'], + 'glia': ['gail', 'gali', 'gila', 'glia'], + 'gliadin': ['dialing', 'gliadin'], + 'glial': ['galli', 'glial'], + 'glibness': ['beslings', 'blessing', 'glibness'], + 'glidder': ['glidder', 'griddle'], + 'glide': ['gelid', 'glide'], + 'glideness': ['gelidness', 'glideness'], + 'glider': ['gilder', 'girdle', 'glider', 'regild', 'ridgel'], + 'gliding': ['gilding', 'gliding'], + 'glime': ['gimel', 'glime'], + 'glink': ['glink', 'kling'], + 'glires': ['girsle', 'gisler', 'glires', 'grilse'], + 'glisten': ['glisten', 'singlet'], + 'glister': ['glister', 'gristle'], + 'glitnir': ['glitnir', 'ritling'], + 'glitter': ['glitter', 'grittle'], + 'gloater': ['argolet', 'gloater', 'legator'], + 'gloating': ['gloating', 'goatling'], + 'globate': ['boltage', 'globate'], + 'globe': ['bogle', 'globe'], + 'globin': ['globin', 'goblin', 'lobing'], + 'gloea': ['gloea', 'legoa'], + 'glome': ['glome', 'golem', 'molge'], + 'glomerate': ['algometer', 'glomerate'], + 'glore': ['glore', 'ogler'], + 'gloria': ['gloria', 'larigo', 'logria'], + 'gloriana': ['argolian', 'gloriana'], + 'gloriette': ['gloriette', 'rigolette'], + 'glorifiable': ['frigolabile', 'glorifiable'], + 'glossed': ['dogless', 'glossed', 'godless'], + 'glosser': ['glosser', 'regloss'], + 'glossitic': ['glossitic', 'logistics'], + 'glossohyal': ['glossohyal', 'hyoglossal'], + 'glossolabial': ['glossolabial', 'labioglossal'], + 'glossolabiolaryngeal': ['glossolabiolaryngeal', 'labioglossolaryngeal'], + 'glossolabiopharyngeal': ['glossolabiopharyngeal', 'labioglossopharyngeal'], + 'glottid': ['glottid', 'goldtit'], + 'glover': ['glover', 'grovel'], + 'gloveress': ['gloveress', 'groveless'], + 'glow': ['glow', 'gowl'], + 'glower': ['glower', 'reglow'], + 'gloy': ['gloy', 'logy'], + 'glucemia': ['glucemia', 'mucilage'], + 'glucina': ['glaucin', 'glucina'], + 'glucine': ['glucine', 'lucigen'], + 'glucinum': ['cingulum', 'glucinum'], + 'glucosane': ['consulage', 'glucosane'], + 'glue': ['glue', 'gule', 'luge'], + 'gluer': ['gluer', 'gruel', 'luger'], + 'gluma': ['algum', 'almug', 'glaum', 'gluma', 'mulga'], + 'glume': ['gemul', 'glume'], + 'glumose': ['glumose', 'lugsome'], + 'gluten': ['englut', 'gluten', 'ungelt'], + 'glutin': ['glutin', 'luting', 'ungilt'], + 'glutter': ['glutter', 'guttler'], + 'glycerate': ['electragy', 'glycerate'], + 'glycerinize': ['glycerinize', 'glycerizine'], + 'glycerizine': ['glycerinize', 'glycerizine'], + 'glycerophosphate': ['glycerophosphate', 'phosphoglycerate'], + 'glycocin': ['glycocin', 'glyconic'], + 'glyconic': ['glycocin', 'glyconic'], + 'glycosine': ['glycosine', 'lysogenic'], + 'glycosuria': ['glycosuria', 'graciously'], + 'gnaeus': ['gnaeus', 'unsage'], + 'gnaphalium': ['gnaphalium', 'phalangium'], + 'gnar': ['garn', 'gnar', 'rang'], + 'gnarled': ['dangler', 'gnarled'], + 'gnash': ['gnash', 'shang'], + 'gnat': ['gant', 'gnat', 'tang'], + 'gnatho': ['gnatho', 'thonga'], + 'gnathotheca': ['chaetognath', 'gnathotheca'], + 'gnatling': ['gnatling', 'tangling'], + 'gnatter': ['garnett', 'gnatter', 'gratten', 'tergant'], + 'gnaw': ['gawn', 'gnaw', 'wang'], + 'gnetum': ['gnetum', 'nutmeg'], + 'gnome': ['genom', 'gnome'], + 'gnomic': ['coming', 'gnomic'], + 'gnomist': ['gnomist', 'mosting'], + 'gnomonic': ['gnomonic', 'oncoming'], + 'gnomonical': ['cognominal', 'gnomonical'], + 'gnostic': ['costing', 'gnostic'], + 'gnostical': ['gnostical', 'nostalgic'], + 'gnu': ['gnu', 'gun'], + 'go': ['go', 'og'], + 'goa': ['ago', 'goa'], + 'goad': ['dago', 'goad'], + 'goal': ['gaol', 'goal', 'gola', 'olga'], + 'goan': ['agon', 'ango', 'gaon', 'goan', 'gona'], + 'goat': ['goat', 'toag', 'toga'], + 'goatee': ['goatee', 'goetae'], + 'goatlike': ['goatlike', 'togalike'], + 'goatling': ['gloating', 'goatling'], + 'goatly': ['goatly', 'otalgy'], + 'gob': ['bog', 'gob'], + 'goban': ['bogan', 'goban'], + 'gobbe': ['bebog', 'begob', 'gobbe'], + 'gobbin': ['gibbon', 'gobbin'], + 'gobelin': ['gobelin', 'gobline', 'ignoble', 'inglobe'], + 'gobian': ['bagnio', 'gabion', 'gobian'], + 'goblet': ['boglet', 'goblet'], + 'goblin': ['globin', 'goblin', 'lobing'], + 'gobline': ['gobelin', 'gobline', 'ignoble', 'inglobe'], + 'goblinry': ['boringly', 'goblinry'], + 'gobo': ['bogo', 'gobo'], + 'goby': ['bogy', 'bygo', 'goby'], + 'goclenian': ['congenial', 'goclenian'], + 'god': ['dog', 'god'], + 'goddam': ['goddam', 'mogdad'], + 'gode': ['doeg', 'doge', 'gode'], + 'godhead': ['doghead', 'godhead'], + 'godhood': ['doghood', 'godhood'], + 'godless': ['dogless', 'glossed', 'godless'], + 'godlike': ['doglike', 'godlike'], + 'godling': ['godling', 'lodging'], + 'godly': ['dogly', 'godly', 'goldy'], + 'godship': ['dogship', 'godship'], + 'godwinian': ['downingia', 'godwinian'], + 'goeduck': ['geoduck', 'goeduck'], + 'goel': ['egol', 'goel', 'loge', 'ogle', 'oleg'], + 'goer': ['goer', 'gore', 'ogre'], + 'goes': ['goes', 'sego'], + 'goetae': ['goatee', 'goetae'], + 'goetic': ['geotic', 'goetic'], + 'goetical': ['ectoglia', 'geotical', 'goetical'], + 'goety': ['geoty', 'goety'], + 'goglet': ['goglet', 'toggel', 'toggle'], + 'goi': ['gio', 'goi'], + 'goidel': ['goidel', 'goldie'], + 'goitral': ['goitral', 'larigot', 'ligator'], + 'gol': ['gol', 'log'], + 'gola': ['gaol', 'goal', 'gola', 'olga'], + 'golden': ['engold', 'golden'], + 'goldenmouth': ['goldenmouth', 'longmouthed'], + 'golder': ['golder', 'lodger'], + 'goldie': ['goidel', 'goldie'], + 'goldtit': ['glottid', 'goldtit'], + 'goldy': ['dogly', 'godly', 'goldy'], + 'golee': ['eloge', 'golee'], + 'golem': ['glome', 'golem', 'molge'], + 'golf': ['flog', 'golf'], + 'golfer': ['golfer', 'reflog'], + 'goli': ['gilo', 'goli'], + 'goliard': ['argolid', 'goliard'], + 'golo': ['golo', 'gool'], + 'goma': ['goma', 'ogam'], + 'gomari': ['gamori', 'gomari', 'gromia'], + 'gomart': ['gomart', 'margot'], + 'gomphrena': ['gomphrena', 'nephogram'], + 'gon': ['gon', 'nog'], + 'gona': ['agon', 'ango', 'gaon', 'goan', 'gona'], + 'gonad': ['donga', 'gonad'], + 'gonadial': ['diagonal', 'ganoidal', 'gonadial'], + 'gonal': ['along', 'gonal', 'lango', 'longa', 'nogal'], + 'gond': ['dong', 'gond'], + 'gondi': ['dingo', 'doing', 'gondi', 'gonid'], + 'gondola': ['dongola', 'gondola'], + 'gondolier': ['gondolier', 'negroloid'], + 'gone': ['geon', 'gone'], + 'goner': ['ergon', 'genro', 'goner', 'negro'], + 'gonesome': ['gonesome', 'osmogene'], + 'gongoresque': ['gongoresque', 'gorgonesque'], + 'gonia': ['gonia', 'ngaio', 'nogai'], + 'goniac': ['agonic', 'angico', 'gaonic', 'goniac'], + 'goniale': ['goniale', 'noilage'], + 'goniaster': ['goniaster', 'orangeist'], + 'goniatitid': ['digitation', 'goniatitid'], + 'gonid': ['dingo', 'doing', 'gondi', 'gonid'], + 'gonidia': ['angioid', 'gonidia'], + 'gonidiferous': ['gonidiferous', 'indigoferous'], + 'goniometer': ['geronomite', 'goniometer'], + 'gonomery': ['gonomery', 'merogony'], + 'gonosome': ['gonosome', 'mongoose'], + 'gonyocele': ['coelogyne', 'gonyocele'], + 'gonys': ['gonys', 'songy'], + 'goober': ['booger', 'goober'], + 'goodyear': ['goodyear', 'goodyera'], + 'goodyera': ['goodyear', 'goodyera'], + 'goof': ['fogo', 'goof'], + 'goofer': ['forego', 'goofer'], + 'gool': ['golo', 'gool'], + 'gools': ['gools', 'logos'], + 'goop': ['goop', 'pogo'], + 'gor': ['gor', 'rog'], + 'gora': ['argo', 'garo', 'gora'], + 'goral': ['algor', 'argol', 'goral', 'largo'], + 'goran': ['angor', + 'argon', + 'goran', + 'grano', + 'groan', + 'nagor', + 'orang', + 'organ', + 'rogan', + 'ronga'], + 'gorb': ['borg', 'brog', 'gorb'], + 'gorbal': ['brolga', 'gorbal'], + 'gorce': ['corge', 'gorce'], + 'gordian': ['gordian', 'idorgan', 'roading'], + 'gordon': ['drongo', 'gordon'], + 'gordonia': ['gordonia', 'organoid', 'rigadoon'], + 'gore': ['goer', 'gore', 'ogre'], + 'gorer': ['gorer', 'roger'], + 'gorge': ['gorge', 'grego'], + 'gorged': ['dogger', 'gorged'], + 'gorger': ['gorger', 'gregor'], + 'gorgerin': ['gorgerin', 'ringgoer'], + 'gorgonesque': ['gongoresque', 'gorgonesque'], + 'goric': ['corgi', 'goric', 'orgic'], + 'goring': ['goring', 'gringo'], + 'gorse': ['gorse', 'soger'], + 'gortonian': ['gortonian', 'organotin'], + 'gory': ['gory', 'gyro', 'orgy'], + 'gos': ['gos', 'sog'], + 'gosain': ['gosain', 'isagon', 'sagoin'], + 'gosh': ['gosh', 'shog'], + 'gospel': ['gospel', 'spogel'], + 'gossipry': ['gossipry', 'gryposis'], + 'got': ['got', 'tog'], + 'gotra': ['argot', 'gator', 'gotra', 'groat'], + 'goup': ['goup', 'ogpu', 'upgo'], + 'gourde': ['drogue', 'gourde'], + 'gout': ['gout', 'toug'], + 'goutish': ['goutish', 'outsigh'], + 'gowan': ['gowan', 'wagon', 'wonga'], + 'gowdnie': ['gowdnie', 'widgeon'], + 'gowl': ['glow', 'gowl'], + 'gown': ['gown', 'wong'], + 'goyin': ['goyin', 'yogin'], + 'gra': ['gar', 'gra', 'rag'], + 'grab': ['brag', 'garb', 'grab'], + 'grabble': ['gabbler', 'grabble'], + 'graben': ['banger', 'engarb', 'graben'], + 'grace': ['cager', 'garce', 'grace'], + 'gracile': ['glacier', 'gracile'], + 'graciously': ['glycosuria', 'graciously'], + 'grad': ['darg', 'drag', 'grad'], + 'gradation': ['gradation', 'indagator', 'tanagroid'], + 'grade': ['edgar', 'grade'], + 'graded': ['gadder', 'graded'], + 'grader': ['darger', 'gerard', 'grader', 'redrag', 'regard'], + 'gradient': ['gradient', 'treading'], + 'gradienter': ['gradienter', 'intergrade'], + 'gradientia': ['gradientia', 'grantiidae'], + 'gradin': ['daring', 'dingar', 'gradin'], + 'gradine': ['degrain', 'deraign', 'deringa', 'gradine', 'grained', 'reading'], + 'grading': ['grading', 'niggard'], + 'graeae': ['aerage', 'graeae'], + 'graeme': ['graeme', 'meager', 'meagre'], + 'grafter': ['grafter', 'regraft'], + 'graian': ['graian', 'nagari'], + 'grail': ['argil', 'glair', 'grail'], + 'grailer': ['grailer', 'reglair'], + 'grain': ['agrin', 'grain'], + 'grained': ['degrain', 'deraign', 'deringa', 'gradine', 'grained', 'reading'], + 'grainer': ['earring', 'grainer'], + 'grainless': ['glariness', 'grainless'], + 'graith': ['aright', 'graith'], + 'grallina': ['grallina', 'granilla'], + 'gralline': ['allergin', 'gralline'], + 'grame': ['grame', 'marge', 'regma'], + 'gramenite': ['germanite', 'germinate', 'gramenite', 'mangerite'], + 'gramineous': ['germanious', 'gramineous', 'marigenous'], + 'graminiform': ['graminiform', 'marginiform'], + 'graminous': ['graminous', 'ignoramus'], + 'gramme': ['gammer', 'gramme'], + 'gramophonic': ['gramophonic', 'monographic', 'nomographic', 'phonogramic'], + 'gramophonical': ['gramophonical', 'monographical', 'nomographical'], + 'gramophonically': ['gramophonically', + 'monographically', + 'nomographically', + 'phonogramically'], + 'gramophonist': ['gramophonist', 'monographist'], + 'granadine': ['granadine', 'grenadian'], + 'granate': ['argante', 'granate', 'tanager'], + 'granatum': ['armgaunt', 'granatum'], + 'grand': ['drang', 'grand'], + 'grandam': ['dragman', 'grandam', 'grandma'], + 'grandee': ['derange', 'enraged', 'gardeen', 'gerenda', 'grandee', 'grenade'], + 'grandeeism': ['grandeeism', 'renegadism'], + 'grandeur': ['grandeur', 'unregard'], + 'grandeval': ['grandeval', 'landgrave'], + 'grandiose': ['grandiose', 'sargonide'], + 'grandma': ['dragman', 'grandam', 'grandma'], + 'grandparental': ['grandparental', 'grandpaternal'], + 'grandpaternal': ['grandparental', 'grandpaternal'], + 'grane': ['anger', 'areng', 'grane', 'range'], + 'grange': ['ganger', 'grange', 'nagger'], + 'grangousier': ['grangousier', 'gregarinous'], + 'granilla': ['grallina', 'granilla'], + 'granite': ['angrite', 'granite', 'ingrate', 'tangier', 'tearing', 'tigrean'], + 'granivore': ['granivore', 'overgrain'], + 'grano': ['angor', + 'argon', + 'goran', + 'grano', + 'groan', + 'nagor', + 'orang', + 'organ', + 'rogan', + 'ronga'], + 'granophyre': ['granophyre', 'renography'], + 'grantee': ['grantee', 'greaten', 'reagent', 'rentage'], + 'granter': ['granter', 'regrant'], + 'granth': ['granth', 'thrang'], + 'grantiidae': ['gradientia', 'grantiidae'], + 'granula': ['angular', 'granula'], + 'granule': ['granule', 'unlarge', 'unregal'], + 'granulite': ['granulite', 'traguline'], + 'grape': ['gaper', 'grape', 'pager', 'parge'], + 'graperoot': ['graperoot', 'prorogate'], + 'graphical': ['algraphic', 'graphical'], + 'graphically': ['calligraphy', 'graphically'], + 'graphologic': ['graphologic', 'logographic'], + 'graphological': ['graphological', 'logographical'], + 'graphology': ['graphology', 'logography'], + 'graphometer': ['graphometer', 'meteorgraph'], + 'graphophonic': ['graphophonic', 'phonographic'], + 'graphostatic': ['gastropathic', 'graphostatic'], + 'graphotypic': ['graphotypic', 'pictography', 'typographic'], + 'grapsidae': ['disparage', 'grapsidae'], + 'grasp': ['grasp', 'sprag'], + 'grasper': ['grasper', 'regrasp', 'sparger'], + 'grasser': ['grasser', 'regrass'], + 'grasshopper': ['grasshopper', 'hoppergrass'], + 'grassman': ['grassman', 'mangrass'], + 'grat': ['grat', 'trag'], + 'grate': ['gater', 'grate', 'great', 'greta', 'retag', 'targe'], + 'grateman': ['grateman', 'mangrate', 'mentagra', 'targeman'], + 'grater': ['garret', 'garter', 'grater', 'targer'], + 'gratiano': ['giornata', 'gratiano'], + 'graticule': ['curtilage', 'cutigeral', 'graticule'], + 'gratiolin': ['gratiolin', 'largition', 'tailoring'], + 'gratis': ['gratis', 'striga'], + 'gratten': ['garnett', 'gnatter', 'gratten', 'tergant'], + 'graupel': ['earplug', 'graupel', 'plaguer'], + 'gravamen': ['gravamen', 'graveman'], + 'gravel': ['glaver', 'gravel'], + 'graveman': ['gravamen', 'graveman'], + 'graves': ['gervas', 'graves'], + 'gravure': ['gravure', 'verruga'], + 'gray': ['gary', 'gray'], + 'grayling': ['grayling', 'ragingly'], + 'graze': ['gazer', 'graze'], + 'greaser': ['argeers', 'greaser', 'serrage'], + 'great': ['gater', 'grate', 'great', 'greta', 'retag', 'targe'], + 'greaten': ['grantee', 'greaten', 'reagent', 'rentage'], + 'greater': ['greater', 'regrate', 'terrage'], + 'greaves': ['gervase', 'greaves', 'servage'], + 'grebe': ['gerbe', 'grebe', 'rebeg'], + 'grecian': ['anergic', 'garnice', 'garniec', 'geranic', 'grecian'], + 'grecomania': ['ergomaniac', 'grecomania'], + 'greed': ['edger', 'greed'], + 'green': ['genre', 'green', 'neger', 'reneg'], + 'greenable': ['generable', 'greenable'], + 'greener': ['greener', 'regreen', 'reneger'], + 'greenish': ['greenish', 'sheering'], + 'greenland': ['englander', 'greenland'], + 'greenuk': ['gerenuk', 'greenuk'], + 'greeny': ['energy', 'greeny', 'gyrene'], + 'greet': ['egret', 'greet', 'reget'], + 'greeter': ['greeter', 'regreet'], + 'gregal': ['gargle', 'gregal', 'lagger', 'raggle'], + 'gregarian': ['gregarian', 'gregarina'], + 'gregarina': ['gregarian', 'gregarina'], + 'gregarinous': ['grangousier', 'gregarinous'], + 'grege': ['egger', 'grege'], + 'gregge': ['gegger', 'gregge'], + 'grego': ['gorge', 'grego'], + 'gregor': ['gorger', 'gregor'], + 'greige': ['greige', 'reggie'], + 'grein': ['grein', 'inger', 'nigre', 'regin', 'reign', 'ringe'], + 'gremial': ['gremial', 'lamiger'], + 'gremlin': ['gremlin', 'mingler'], + 'grenade': ['derange', 'enraged', 'gardeen', 'gerenda', 'grandee', 'grenade'], + 'grenadian': ['granadine', 'grenadian'], + 'grenadier': ['earringed', 'grenadier'], + 'grenadin': ['gardenin', 'grenadin'], + 'grenadine': ['endearing', 'engrained', 'grenadine'], + 'greta': ['gater', 'grate', 'great', 'greta', 'retag', 'targe'], + 'gretel': ['gretel', 'reglet'], + 'greund': ['dunger', 'gerund', 'greund', 'nudger'], + 'grewia': ['earwig', 'grewia'], + 'grey': ['grey', 'gyre'], + 'grid': ['gird', 'grid'], + 'griddle': ['glidder', 'griddle'], + 'gride': ['dirge', 'gride', 'redig', 'ridge'], + 'gridelin': ['dreiling', 'gridelin'], + 'grieve': ['grieve', 'regive'], + 'grieved': ['diverge', 'grieved'], + 'grille': ['giller', 'grille', 'regill'], + 'grilse': ['girsle', 'gisler', 'glires', 'grilse'], + 'grimace': ['gemaric', 'grimace', 'megaric'], + 'grime': ['gerim', 'grime'], + 'grimme': ['gimmer', 'grimme', 'megrim'], + 'grin': ['girn', 'grin', 'ring'], + 'grinder': ['grinder', 'regrind'], + 'grindle': ['dringle', 'grindle'], + 'gringo': ['goring', 'gringo'], + 'grip': ['grip', 'prig'], + 'gripe': ['gerip', 'gripe'], + 'gripeful': ['fireplug', 'gripeful'], + 'griper': ['griper', 'regrip'], + 'gripman': ['gripman', 'prigman', 'ramping'], + 'grippe': ['gipper', 'grippe'], + 'grisounite': ['grisounite', 'grisoutine', 'integrious'], + 'grisoutine': ['grisounite', 'grisoutine', 'integrious'], + 'grist': ['grist', 'grits', 'strig'], + 'gristle': ['glister', 'gristle'], + 'grit': ['girt', 'grit', 'trig'], + 'grith': ['girth', 'grith', 'right'], + 'grits': ['grist', 'grits', 'strig'], + 'gritten': ['gittern', 'gritten', 'retting'], + 'grittle': ['glitter', 'grittle'], + 'grivna': ['grivna', 'raving'], + 'grizzel': ['grizzel', 'grizzle'], + 'grizzle': ['grizzel', 'grizzle'], + 'groan': ['angor', + 'argon', + 'goran', + 'grano', + 'groan', + 'nagor', + 'orang', + 'organ', + 'rogan', + 'ronga'], + 'groaner': ['groaner', 'oranger', 'organer'], + 'groaning': ['groaning', 'organing'], + 'groat': ['argot', 'gator', 'gotra', 'groat'], + 'grobian': ['biorgan', 'grobian'], + 'groined': ['groined', 'negroid'], + 'gromia': ['gamori', 'gomari', 'gromia'], + 'groove': ['groove', 'overgo'], + 'grope': ['grope', 'porge'], + 'groper': ['groper', 'porger'], + 'groset': ['groset', 'storge'], + 'grossen': ['engross', 'grossen'], + 'grot': ['grot', 'trog'], + 'grotian': ['grotian', 'trigona'], + 'grotto': ['grotto', 'torgot'], + 'grounded': ['grounded', 'underdog', 'undergod'], + 'grouper': ['grouper', 'regroup'], + 'grouse': ['grouse', 'rugose'], + 'grousy': ['grousy', 'gyrous'], + 'grovel': ['glover', 'grovel'], + 'groveless': ['gloveress', 'groveless'], + 'growan': ['awrong', 'growan'], + 'grower': ['grower', 'regrow'], + 'grown': ['grown', 'wrong'], + 'grub': ['burg', 'grub'], + 'grudge': ['grudge', 'rugged'], + 'grudger': ['drugger', 'grudger'], + 'grudgery': ['druggery', 'grudgery'], + 'grue': ['grue', 'urge'], + 'gruel': ['gluer', 'gruel', 'luger'], + 'gruelly': ['gruelly', 'gullery'], + 'grues': ['grues', 'surge'], + 'grun': ['grun', 'rung'], + 'grush': ['grush', 'shrug'], + 'grusinian': ['grusinian', 'unarising'], + 'grutten': ['grutten', 'turgent'], + 'gryposis': ['gossipry', 'gryposis'], + 'guacho': ['gaucho', 'guacho'], + 'guan': ['gaun', 'guan', 'guna', 'uang'], + 'guanamine': ['guanamine', 'guineaman'], + 'guanine': ['anguine', 'guanine', 'guinean'], + 'guar': ['gaur', 'guar', 'ruga'], + 'guara': ['gaura', 'guara'], + 'guarani': ['anguria', 'gaurian', 'guarani'], + 'guarantorship': ['guarantorship', 'uranographist'], + 'guardeen': ['dungaree', 'guardeen', 'unagreed', 'underage', 'ungeared'], + 'guarder': ['guarder', 'reguard'], + 'guatusan': ['augustan', 'guatusan'], + 'gud': ['dug', 'gud'], + 'gude': ['degu', 'gude'], + 'guenon': ['guenon', 'ungone'], + 'guepard': ['guepard', 'upgrade'], + 'guerdon': ['guerdon', 'undergo', 'ungored'], + 'guerdoner': ['guerdoner', 'reundergo', 'undergoer', 'undergore'], + 'guerinet': ['geniture', 'guerinet'], + 'guester': ['gesture', 'guester'], + 'guetar': ['argute', 'guetar', 'rugate', 'tuareg'], + 'guetare': ['erugate', 'guetare'], + 'guha': ['augh', 'guha'], + 'guiana': ['guiana', 'iguana'], + 'guib': ['bugi', 'guib'], + 'guineaman': ['guanamine', 'guineaman'], + 'guinean': ['anguine', 'guanine', 'guinean'], + 'guiser': ['guiser', 'sergiu'], + 'gul': ['gul', 'lug'], + 'gula': ['gaul', 'gula'], + 'gulae': ['gulae', 'legua'], + 'gular': ['glaur', 'gular'], + 'gularis': ['agrilus', 'gularis'], + 'gulden': ['gulden', 'lunged'], + 'gule': ['glue', 'gule', 'luge'], + 'gules': ['gules', 'gusle'], + 'gullery': ['gruelly', 'gullery'], + 'gullible': ['bluegill', 'gullible'], + 'gulonic': ['gulonic', 'unlogic'], + 'gulp': ['gulp', 'plug'], + 'gulpin': ['gulpin', 'puling'], + 'gum': ['gum', 'mug'], + 'gumbo': ['bogum', 'gumbo'], + 'gumshoe': ['gumshoe', 'hugsome'], + 'gumweed': ['gumweed', 'mugweed'], + 'gun': ['gnu', 'gun'], + 'guna': ['gaun', 'guan', 'guna', 'uang'], + 'gunate': ['gunate', 'tangue'], + 'gundi': ['gundi', 'undig'], + 'gundy': ['dungy', 'gundy'], + 'gunk': ['gunk', 'kung'], + 'gunl': ['gunl', 'lung'], + 'gunnership': ['gunnership', 'unsphering'], + 'gunreach': ['gunreach', 'uncharge'], + 'gunsel': ['gunsel', 'selung', 'slunge'], + 'gunshot': ['gunshot', 'shotgun', 'uhtsong'], + 'gunster': ['gunster', 'surgent'], + 'gunter': ['gunter', 'gurnet', 'urgent'], + 'gup': ['gup', 'pug'], + 'gur': ['gur', 'rug'], + 'gurgeon': ['gurgeon', 'ungorge'], + 'gurgle': ['gurgle', 'lugger', 'ruggle'], + 'gurian': ['gurian', 'ugrian'], + 'guric': ['guric', 'ugric'], + 'gurl': ['gurl', 'lurg'], + 'gurnard': ['drungar', 'gurnard'], + 'gurnet': ['gunter', 'gurnet', 'urgent'], + 'gurt': ['gurt', 'trug'], + 'gush': ['gush', 'shug', 'sugh'], + 'gusher': ['gusher', 'regush'], + 'gusle': ['gules', 'gusle'], + 'gust': ['gust', 'stug'], + 'gut': ['gut', 'tug'], + 'gutless': ['gutless', 'tugless'], + 'gutlike': ['gutlike', 'tuglike'], + 'gutnish': ['gutnish', 'husting', 'unsight'], + 'guttler': ['glutter', 'guttler'], + 'guttular': ['guttular', 'guttural'], + 'guttural': ['guttular', 'guttural'], + 'gweed': ['gweed', 'wedge'], + 'gymnasic': ['gymnasic', 'syngamic'], + 'gymnastic': ['gymnastic', 'nystagmic'], + 'gynandrous': ['androgynus', 'gynandrous'], + 'gynerium': ['eryngium', 'gynerium'], + 'gynospore': ['gynospore', 'sporogeny'], + 'gypsine': ['gypsine', 'pigsney'], + 'gyral': ['glary', 'gyral'], + 'gyrant': ['gantry', 'gyrant'], + 'gyrate': ['geraty', 'gyrate'], + 'gyration': ['gyration', 'organity', 'ortygian'], + 'gyre': ['grey', 'gyre'], + 'gyrene': ['energy', 'greeny', 'gyrene'], + 'gyro': ['gory', 'gyro', 'orgy'], + 'gyroma': ['gyroma', 'morgay'], + 'gyromitra': ['gyromitra', 'migratory'], + 'gyrophora': ['gyrophora', 'orography'], + 'gyrous': ['grousy', 'gyrous'], + 'gyrus': ['gyrus', 'surgy'], + 'ha': ['ah', 'ha'], + 'haberdine': ['haberdine', 'hebridean'], + 'habile': ['habile', 'halebi'], + 'habiri': ['bihari', 'habiri'], + 'habiru': ['brahui', 'habiru'], + 'habit': ['baith', 'habit'], + 'habitan': ['abthain', 'habitan'], + 'habitat': ['habitat', 'tabitha'], + 'habited': ['habited', 'thebaid'], + 'habitus': ['habitus', 'ushabti'], + 'habnab': ['babhan', 'habnab'], + 'hacienda': ['chanidae', 'hacienda'], + 'hackin': ['hackin', 'kachin'], + 'hackle': ['hackle', 'lekach'], + 'hackler': ['chalker', 'hackler'], + 'hackly': ['chalky', 'hackly'], + 'hacktree': ['eckehart', 'hacktree'], + 'hackwood': ['hackwood', 'woodhack'], + 'hacky': ['chyak', 'hacky'], + 'had': ['dah', 'dha', 'had'], + 'hadden': ['hadden', 'handed'], + 'hade': ['hade', 'head'], + 'hades': ['deash', 'hades', 'sadhe', 'shade'], + 'hadji': ['hadji', 'jihad'], + 'haec': ['ache', 'each', 'haec'], + 'haem': ['ahem', 'haem', 'hame'], + 'haet': ['ahet', 'haet', 'hate', 'heat', 'thea'], + 'hafgan': ['afghan', 'hafgan'], + 'hafter': ['father', 'freath', 'hafter'], + 'hageen': ['hageen', 'hangee'], + 'hailse': ['elisha', 'hailse', 'sheila'], + 'hainan': ['hainan', 'nahani'], + 'hair': ['ahir', 'hair'], + 'hairband': ['bhandari', 'hairband'], + 'haired': ['dehair', 'haired'], + 'hairen': ['hairen', 'hernia'], + 'hairlet': ['hairlet', 'therial'], + 'hairstone': ['hairstone', 'hortensia'], + 'hairup': ['hairup', 'rupiah'], + 'hak': ['hak', 'kha'], + 'hakam': ['hakam', 'makah'], + 'hakea': ['ekaha', 'hakea'], + 'hakim': ['hakim', 'khami'], + 'haku': ['haku', 'kahu'], + 'halal': ['allah', 'halal'], + 'halbert': ['blather', 'halbert'], + 'hale': ['hale', 'heal', 'leah'], + 'halebi': ['habile', 'halebi'], + 'halenia': ['ainaleh', 'halenia'], + 'halesome': ['halesome', 'healsome'], + 'halicore': ['halicore', 'heroical'], + 'haliotidae': ['aethalioid', 'haliotidae'], + 'hallan': ['hallan', 'nallah'], + 'hallower': ['hallower', 'rehallow'], + 'halma': ['halma', 'hamal'], + 'halogeton': ['halogeton', 'theogonal'], + 'haloid': ['dihalo', 'haloid'], + 'halophile': ['halophile', 'philohela'], + 'halophytism': ['halophytism', 'hylopathism'], + 'hals': ['hals', 'lash'], + 'halse': ['halse', 'leash', 'selah', 'shale', 'sheal', 'shela'], + 'halsen': ['halsen', 'hansel', 'lanseh'], + 'halt': ['halt', 'lath'], + 'halter': ['arthel', 'halter', 'lather', 'thaler'], + 'halterbreak': ['halterbreak', 'leatherbark'], + 'halting': ['halting', 'lathing', 'thingal'], + 'halve': ['halve', 'havel'], + 'halver': ['halver', 'lavehr'], + 'ham': ['ham', 'mah'], + 'hamal': ['halma', 'hamal'], + 'hame': ['ahem', 'haem', 'hame'], + 'hameil': ['hameil', 'hiemal'], + 'hamel': ['hamel', 'hemal'], + 'hamfatter': ['aftermath', 'hamfatter'], + 'hami': ['hami', 'hima', 'mahi'], + 'hamital': ['hamital', 'thalami'], + 'hamites': ['atheism', 'hamites'], + 'hamlet': ['hamlet', 'malthe'], + 'hammerer': ['hammerer', 'rehammer'], + 'hamsa': ['hamsa', 'masha', 'shama'], + 'hamulites': ['hamulites', 'shulamite'], + 'hamus': ['hamus', 'musha'], + 'hanaster': ['hanaster', 'sheratan'], + 'hance': ['achen', 'chane', 'chena', 'hance'], + 'hand': ['dhan', 'hand'], + 'handbook': ['bandhook', 'handbook'], + 'handed': ['hadden', 'handed'], + 'hander': ['hander', 'harden'], + 'handicapper': ['handicapper', 'prehandicap'], + 'handscrape': ['handscrape', 'scaphander'], + 'handstone': ['handstone', 'stonehand'], + 'handwork': ['handwork', 'workhand'], + 'hangar': ['arghan', 'hangar'], + 'hangby': ['banghy', 'hangby'], + 'hangee': ['hageen', 'hangee'], + 'hanger': ['hanger', 'rehang'], + 'hangie': ['gienah', 'hangie'], + 'hangnail': ['hangnail', 'langhian'], + 'hangout': ['hangout', 'tohunga'], + 'hank': ['ankh', 'hank', 'khan'], + 'hano': ['hano', 'noah'], + 'hans': ['hans', 'nash', 'shan'], + 'hansa': ['ahsan', 'hansa', 'hasan'], + 'hanse': ['ashen', 'hanse', 'shane', 'shean'], + 'hanseatic': ['anchistea', 'hanseatic'], + 'hansel': ['halsen', 'hansel', 'lanseh'], + 'hant': ['hant', 'tanh', 'than'], + 'hantle': ['ethnal', 'hantle', 'lathen', 'thenal'], + 'hao': ['aho', 'hao'], + 'haole': ['eloah', 'haole'], + 'haoma': ['haoma', 'omaha'], + 'haori': ['haori', 'iroha'], + 'hap': ['hap', 'pah'], + 'hapalotis': ['hapalotis', 'sapotilha'], + 'hapi': ['hapi', 'pahi'], + 'haplodoci': ['chilopoda', 'haplodoci'], + 'haplont': ['haplont', 'naphtol'], + 'haplosis': ['alphosis', 'haplosis'], + 'haply': ['haply', 'phyla'], + 'happiest': ['happiest', 'peatship'], + 'haptene': ['haptene', 'heptane', 'phenate'], + 'haptenic': ['haptenic', 'pantheic', 'pithecan'], + 'haptere': ['haptere', 'preheat'], + 'haptic': ['haptic', 'pathic'], + 'haptics': ['haptics', 'spathic'], + 'haptometer': ['amphorette', 'haptometer'], + 'haptophoric': ['haptophoric', 'pathophoric'], + 'haptophorous': ['haptophorous', 'pathophorous'], + 'haptotropic': ['haptotropic', 'protopathic'], + 'hapu': ['hapu', 'hupa'], + 'harass': ['harass', 'hassar'], + 'harb': ['bhar', 'harb'], + 'harborer': ['abhorrer', 'harborer'], + 'harden': ['hander', 'harden'], + 'hardener': ['hardener', 'reharden'], + 'hardenite': ['hardenite', 'herniated'], + 'hardtail': ['hardtail', 'thaliard'], + 'hardy': ['hardy', 'hydra'], + 'hare': ['hare', 'hear', 'rhea'], + 'harebrain': ['harebrain', 'herbarian'], + 'harem': ['harem', 'herma', 'rhema'], + 'haremism': ['ashimmer', 'haremism'], + 'harfang': ['fraghan', 'harfang'], + 'haricot': ['chariot', 'haricot'], + 'hark': ['hark', 'khar', 'rakh'], + 'harka': ['harka', 'kahar'], + 'harlot': ['harlot', 'orthal', 'thoral'], + 'harmala': ['harmala', 'marhala'], + 'harman': ['amhran', 'harman', 'mahran'], + 'harmer': ['harmer', 'reharm'], + 'harmine': ['harmine', 'hireman'], + 'harmonic': ['choirman', 'harmonic', 'omniarch'], + 'harmonical': ['harmonical', 'monarchial'], + 'harmonics': ['anorchism', 'harmonics'], + 'harmonistic': ['anchoritism', 'chiromantis', 'chrismation', 'harmonistic'], + 'harnesser': ['harnesser', 'reharness'], + 'harold': ['harold', 'holard'], + 'harpa': ['aphra', 'harpa', 'parah'], + 'harpings': ['harpings', 'phrasing'], + 'harpist': ['harpist', 'traship'], + 'harpless': ['harpless', 'splasher'], + 'harris': ['arrish', 'harris', 'rarish', 'sirrah'], + 'harrower': ['harrower', 'reharrow'], + 'hart': ['hart', 'rath', 'tahr', 'thar', 'trah'], + 'hartin': ['hartin', 'thrain'], + 'hartite': ['hartite', 'rathite'], + 'haruspices': ['chuprassie', 'haruspices'], + 'harvester': ['harvester', 'reharvest'], + 'hasan': ['ahsan', 'hansa', 'hasan'], + 'hash': ['hash', 'sahh', 'shah'], + 'hasher': ['hasher', 'rehash'], + 'hasidic': ['hasidic', 'sahidic'], + 'hasidim': ['hasidim', 'maidish'], + 'hasky': ['hasky', 'shaky'], + 'haslet': ['haslet', 'lesath', 'shelta'], + 'hasp': ['hasp', 'pash', 'psha', 'shap'], + 'hassar': ['harass', 'hassar'], + 'hassel': ['hassel', 'hassle'], + 'hassle': ['hassel', 'hassle'], + 'haste': ['ashet', 'haste', 'sheat'], + 'hasten': ['athens', 'hasten', 'snathe', 'sneath'], + 'haster': ['haster', 'hearst', 'hearts'], + 'hastilude': ['hastilude', 'lustihead'], + 'hastler': ['hastler', 'slather'], + 'hasty': ['hasty', 'yasht'], + 'hat': ['aht', 'hat', 'tha'], + 'hatchery': ['hatchery', 'thearchy'], + 'hate': ['ahet', 'haet', 'hate', 'heat', 'thea'], + 'hateable': ['hateable', 'heatable'], + 'hateful': ['hateful', 'heatful'], + 'hateless': ['hateless', 'heatless'], + 'hater': ['earth', 'hater', 'heart', 'herat', 'rathe'], + 'hati': ['hati', 'thai'], + 'hatred': ['dearth', 'hatred', 'rathed', 'thread'], + 'hatress': ['hatress', 'shaster'], + 'hatt': ['hatt', 'tath', 'that'], + 'hattemist': ['hattemist', 'thematist'], + 'hatter': ['hatter', 'threat'], + 'hattery': ['hattery', 'theatry'], + 'hattic': ['chatti', 'hattic'], + 'hattock': ['hattock', 'totchka'], + 'hau': ['ahu', 'auh', 'hau'], + 'hauerite': ['eutheria', 'hauerite'], + 'haul': ['haul', 'hula'], + 'hauler': ['hauler', 'rehaul'], + 'haunt': ['ahunt', 'haunt', 'thuan', 'unhat'], + 'haunter': ['haunter', 'nauther', 'unearth', 'unheart', 'urethan'], + 'hauntingly': ['hauntingly', 'unhatingly'], + 'haurient': ['haurient', 'huterian'], + 'havel': ['halve', 'havel'], + 'havers': ['havers', 'shaver', 'shrave'], + 'haw': ['haw', 'hwa', 'wah', 'wha'], + 'hawer': ['hawer', 'whare'], + 'hawm': ['hawm', 'wham'], + 'hawse': ['hawse', 'shewa', 'whase'], + 'hawser': ['hawser', 'rewash', 'washer'], + 'hay': ['hay', 'yah'], + 'haya': ['ayah', 'haya'], + 'hayz': ['hayz', 'hazy'], + 'hazarder': ['hazarder', 'rehazard'], + 'hazel': ['hazel', 'hazle'], + 'hazle': ['hazel', 'hazle'], + 'hazy': ['hayz', 'hazy'], + 'he': ['eh', 'he'], + 'head': ['hade', 'head'], + 'headbander': ['barehanded', 'bradenhead', 'headbander'], + 'headboard': ['broadhead', 'headboard'], + 'header': ['adhere', 'header', 'hedera', 'rehead'], + 'headily': ['headily', 'hylidae'], + 'headlight': ['headlight', 'lighthead'], + 'headlong': ['headlong', 'longhead'], + 'headman': ['headman', 'manhead'], + 'headmaster': ['headmaster', 'headstream', 'streamhead'], + 'headnote': ['headnote', 'notehead'], + 'headrail': ['headrail', 'railhead'], + 'headrent': ['adherent', 'headrent', 'neatherd', 'threaden'], + 'headring': ['headring', 'ringhead'], + 'headset': ['headset', 'sethead'], + 'headskin': ['headskin', 'nakedish', 'sinkhead'], + 'headspring': ['headspring', 'springhead'], + 'headstone': ['headstone', 'stonehead'], + 'headstream': ['headmaster', 'headstream', 'streamhead'], + 'headstrong': ['headstrong', 'stronghead'], + 'headward': ['drawhead', 'headward'], + 'headwater': ['headwater', 'waterhead'], + 'heal': ['hale', 'heal', 'leah'], + 'healer': ['healer', 'rehale', 'reheal'], + 'healsome': ['halesome', 'healsome'], + 'heap': ['epha', 'heap'], + 'heaper': ['heaper', 'reheap'], + 'heaps': ['heaps', 'pesah', 'phase', 'shape'], + 'hear': ['hare', 'hear', 'rhea'], + 'hearer': ['hearer', 'rehear'], + 'hearken': ['hearken', 'kenareh'], + 'hearst': ['haster', 'hearst', 'hearts'], + 'heart': ['earth', 'hater', 'heart', 'herat', 'rathe'], + 'heartdeep': ['heartdeep', 'preheated'], + 'hearted': ['earthed', 'hearted'], + 'heartedness': ['heartedness', 'neatherdess'], + 'hearten': ['earthen', 'enheart', 'hearten', 'naether', 'teheran', 'traheen'], + 'heartener': ['heartener', 'rehearten'], + 'heartiness': ['earthiness', 'heartiness'], + 'hearting': ['hearting', 'ingather'], + 'heartless': ['earthless', 'heartless'], + 'heartling': ['earthling', 'heartling'], + 'heartly': ['earthly', 'heartly', 'lathery', 'rathely'], + 'heartnut': ['earthnut', 'heartnut'], + 'heartpea': ['earthpea', 'heartpea'], + 'heartquake': ['earthquake', 'heartquake'], + 'hearts': ['haster', 'hearst', 'hearts'], + 'heartsome': ['heartsome', 'samothere'], + 'heartward': ['earthward', 'heartward'], + 'heartweed': ['heartweed', 'weathered'], + 'hearty': ['earthy', 'hearty', 'yearth'], + 'heat': ['ahet', 'haet', 'hate', 'heat', 'thea'], + 'heatable': ['hateable', 'heatable'], + 'heater': ['heater', 'hereat', 'reheat'], + 'heatful': ['hateful', 'heatful'], + 'heath': ['heath', 'theah'], + 'heating': ['gahnite', 'heating'], + 'heatless': ['hateless', 'heatless'], + 'heatronic': ['anchorite', 'antechoir', 'heatronic', 'hectorian'], + 'heave': ['heave', 'hevea'], + 'hebraizer': ['hebraizer', 'herbarize'], + 'hebridean': ['haberdine', 'hebridean'], + 'hecate': ['achete', 'hecate', 'teache', 'thecae'], + 'hecatine': ['echinate', 'hecatine'], + 'heckle': ['heckle', 'kechel'], + 'hectare': ['cheater', 'hectare', 'recheat', 'reteach', 'teacher'], + 'hecte': ['cheet', 'hecte'], + 'hector': ['hector', 'rochet', 'tocher', 'troche'], + 'hectorian': ['anchorite', 'antechoir', 'heatronic', 'hectorian'], + 'hectorship': ['christophe', 'hectorship'], + 'hedera': ['adhere', 'header', 'hedera', 'rehead'], + 'hedonical': ['chelodina', 'hedonical'], + 'hedonism': ['demonish', 'hedonism'], + 'heehaw': ['heehaw', 'wahehe'], + 'heel': ['heel', 'hele'], + 'heeler': ['heeler', 'reheel'], + 'heelpost': ['heelpost', 'pesthole'], + 'heer': ['heer', 'here'], + 'hegari': ['hegari', 'hegira'], + 'hegemonic': ['hegemonic', 'hemogenic'], + 'hegira': ['hegari', 'hegira'], + 'hei': ['hei', 'hie'], + 'height': ['eighth', 'height'], + 'heightener': ['heightener', 'reheighten'], + 'heintzite': ['heintzite', 'hintzeite'], + 'heinz': ['heinz', 'hienz'], + 'heir': ['heir', 'hire'], + 'heirdom': ['heirdom', 'homerid'], + 'heirless': ['heirless', 'hireless'], + 'hejazi': ['hejazi', 'jeziah'], + 'helcosis': ['helcosis', 'ochlesis'], + 'helcotic': ['helcotic', 'lochetic', 'ochletic'], + 'hele': ['heel', 'hele'], + 'heliacal': ['achillea', 'heliacal'], + 'heliast': ['heliast', 'thesial'], + 'helical': ['alichel', 'challie', 'helical'], + 'heliced': ['chelide', 'heliced'], + 'helicon': ['choline', 'helicon'], + 'heling': ['heling', 'hingle'], + 'heliophotography': ['heliophotography', 'photoheliography'], + 'helios': ['helios', 'isohel'], + 'heliostatic': ['chiastolite', 'heliostatic'], + 'heliotactic': ['heliotactic', 'thiolacetic'], + 'helium': ['helium', 'humlie'], + 'hellcat': ['hellcat', 'tellach'], + 'helleborein': ['helleborein', 'helleborine'], + 'helleborine': ['helleborein', 'helleborine'], + 'hellenic': ['chenille', 'hellenic'], + 'helleri': ['helleri', 'hellier'], + 'hellicat': ['hellicat', 'lecithal'], + 'hellier': ['helleri', 'hellier'], + 'helm': ['helm', 'heml'], + 'heloderma': ['dreamhole', 'heloderma'], + 'helot': ['helot', 'hotel', 'thole'], + 'helotize': ['helotize', 'hotelize'], + 'helpmeet': ['helpmeet', 'meethelp'], + 'hemad': ['ahmed', 'hemad'], + 'hemal': ['hamel', 'hemal'], + 'hemapod': ['hemapod', 'mophead'], + 'hematic': ['chamite', 'hematic'], + 'hematin': ['ethanim', 'hematin'], + 'hematinic': ['hematinic', 'minchiate'], + 'hematolin': ['hematolin', 'maholtine'], + 'hematonic': ['hematonic', 'methanoic'], + 'hematosin': ['hematosin', 'thomasine'], + 'hematoxic': ['hematoxic', 'hexatomic'], + 'hematuric': ['hematuric', 'rheumatic'], + 'hemiasci': ['hemiasci', 'ischemia'], + 'hemiatrophy': ['hemiatrophy', 'hypothermia'], + 'hemic': ['chime', 'hemic', 'miche'], + 'hemicarp': ['camphire', 'hemicarp'], + 'hemicatalepsy': ['hemicatalepsy', 'mesaticephaly'], + 'hemiclastic': ['alchemistic', 'hemiclastic'], + 'hemicrany': ['hemicrany', 'machinery'], + 'hemiholohedral': ['hemiholohedral', 'holohemihedral'], + 'hemiolic': ['elohimic', 'hemiolic'], + 'hemiparesis': ['hemiparesis', 'phariseeism'], + 'hemistater': ['amherstite', 'hemistater'], + 'hemiterata': ['hemiterata', 'metatheria'], + 'hemitype': ['epithyme', 'hemitype'], + 'heml': ['helm', 'heml'], + 'hemogenic': ['hegemonic', 'hemogenic'], + 'hemol': ['hemol', 'mohel'], + 'hemologist': ['hemologist', 'theologism'], + 'hemopneumothorax': ['hemopneumothorax', 'pneumohemothorax'], + 'henbit': ['behint', 'henbit'], + 'hent': ['hent', 'neth', 'then'], + 'henter': ['erthen', 'henter', 'nether', 'threne'], + 'henyard': ['enhydra', 'henyard'], + 'hepar': ['hepar', 'phare', 'raphe'], + 'heparin': ['heparin', 'nephria'], + 'hepatic': ['aphetic', 'caphite', 'hepatic'], + 'hepatica': ['apachite', 'hepatica'], + 'hepatical': ['caliphate', 'hepatical'], + 'hepatize': ['aphetize', 'hepatize'], + 'hepatocolic': ['hepatocolic', 'otocephalic'], + 'hepatogastric': ['gastrohepatic', 'hepatogastric'], + 'hepatoid': ['diaphote', 'hepatoid'], + 'hepatomegalia': ['hepatomegalia', 'megalohepatia'], + 'hepatonephric': ['hepatonephric', 'phrenohepatic'], + 'hepatostomy': ['hepatostomy', 'somatophyte'], + 'hepialid': ['hepialid', 'phialide'], + 'heptace': ['heptace', 'tepache'], + 'heptad': ['heptad', 'pathed'], + 'heptagon': ['heptagon', 'pathogen'], + 'heptameron': ['heptameron', 'promethean'], + 'heptane': ['haptene', 'heptane', 'phenate'], + 'heptaploidy': ['heptaploidy', 'typhlopidae'], + 'hepteris': ['hepteris', 'treeship'], + 'heptine': ['heptine', 'nephite'], + 'heptite': ['epithet', 'heptite'], + 'heptorite': ['heptorite', 'tephroite'], + 'heptylic': ['heptylic', 'phyletic'], + 'her': ['her', 'reh', 'rhe'], + 'heraclid': ['heraclid', 'heraldic'], + 'heraldic': ['heraclid', 'heraldic'], + 'heraldist': ['heraldist', 'tehsildar'], + 'herat': ['earth', 'hater', 'heart', 'herat', 'rathe'], + 'herbage': ['breaghe', 'herbage'], + 'herbarian': ['harebrain', 'herbarian'], + 'herbarism': ['herbarism', 'shambrier'], + 'herbarize': ['hebraizer', 'herbarize'], + 'herbert': ['berther', 'herbert'], + 'herbous': ['herbous', 'subhero'], + 'herdic': ['chider', 'herdic'], + 'here': ['heer', 'here'], + 'hereafter': ['featherer', 'hereafter'], + 'hereat': ['heater', 'hereat', 'reheat'], + 'herein': ['herein', 'inhere'], + 'hereinto': ['etherion', 'hereinto', 'heronite'], + 'herem': ['herem', 'rheme'], + 'heretic': ['erethic', 'etheric', 'heretic', 'heteric', 'teicher'], + 'heretically': ['heretically', 'heterically'], + 'heretication': ['heretication', 'theoretician'], + 'hereto': ['hereto', 'hetero'], + 'heritance': ['catherine', 'heritance'], + 'herl': ['herl', 'hler', 'lehr'], + 'herma': ['harem', 'herma', 'rhema'], + 'hermaic': ['chimera', 'hermaic'], + 'hermitage': ['geheimrat', 'hermitage'], + 'hermo': ['hermo', 'homer', 'horme'], + 'herne': ['herne', 'rheen'], + 'hernia': ['hairen', 'hernia'], + 'hernial': ['hernial', 'inhaler'], + 'herniate': ['atherine', 'herniate'], + 'herniated': ['hardenite', 'herniated'], + 'hernioid': ['dinheiro', 'hernioid'], + 'hero': ['hero', 'hoer'], + 'herodian': ['herodian', 'ironhead'], + 'heroic': ['coheir', 'heroic'], + 'heroical': ['halicore', 'heroical'], + 'heroin': ['heroin', 'hieron', 'hornie'], + 'heroism': ['heroism', 'moreish'], + 'heronite': ['etherion', 'hereinto', 'heronite'], + 'herophile': ['herophile', 'rheophile'], + 'herpes': ['herpes', 'hesper', 'sphere'], + 'herpetism': ['herpetism', 'metership', 'metreship', 'temperish'], + 'herpetological': ['herpetological', 'pretheological'], + 'herpetomonad': ['dermatophone', 'herpetomonad'], + 'hers': ['hers', 'resh', 'sher'], + 'herse': ['herse', 'sereh', 'sheer', 'shree'], + 'hersed': ['hersed', 'sheder'], + 'herself': ['flesher', 'herself'], + 'hersir': ['hersir', 'sherri'], + 'herulian': ['herulian', 'inhauler'], + 'hervati': ['athrive', 'hervati'], + 'hesitater': ['hesitater', 'hetaerist'], + 'hesper': ['herpes', 'hesper', 'sphere'], + 'hespera': ['hespera', 'rephase', 'reshape'], + 'hesperia': ['hesperia', 'pharisee'], + 'hesperian': ['hesperian', 'phrenesia', 'seraphine'], + 'hesperid': ['hesperid', 'perished'], + 'hesperinon': ['hesperinon', 'prehension'], + 'hesperis': ['hesperis', 'seership'], + 'hest': ['esth', 'hest', 'seth'], + 'hester': ['esther', 'hester', 'theres'], + 'het': ['het', 'the'], + 'hetaeric': ['cheatrie', 'hetaeric'], + 'hetaerist': ['hesitater', 'hetaerist'], + 'hetaery': ['erythea', 'hetaery', 'yeather'], + 'heteratomic': ['heteratomic', 'theorematic'], + 'heteraxial': ['exhilarate', 'heteraxial'], + 'heteric': ['erethic', 'etheric', 'heretic', 'heteric', 'teicher'], + 'heterically': ['heretically', 'heterically'], + 'hetericism': ['erethismic', 'hetericism'], + 'hetericist': ['erethistic', 'hetericist'], + 'heterism': ['erethism', 'etherism', 'heterism'], + 'heterization': ['etherization', 'heterization'], + 'heterize': ['etherize', 'heterize'], + 'hetero': ['hereto', 'hetero'], + 'heterocarpus': ['heterocarpus', 'urethrascope'], + 'heteroclite': ['heteroclite', 'heterotelic'], + 'heterodromy': ['heterodromy', 'hydrometeor'], + 'heteroecismal': ['cholesteremia', 'heteroecismal'], + 'heterography': ['erythrophage', 'heterography'], + 'heterogynous': ['heterogynous', 'thyreogenous'], + 'heterology': ['heterology', 'thereology'], + 'heteromeri': ['heteromeri', 'moerithere'], + 'heteroousiast': ['autoheterosis', 'heteroousiast'], + 'heteropathy': ['heteropathy', 'theotherapy'], + 'heteropodal': ['heteropodal', 'prelatehood'], + 'heterotelic': ['heteroclite', 'heterotelic'], + 'heterotic': ['heterotic', 'theoretic'], + 'hetman': ['anthem', 'hetman', 'mentha'], + 'hetmanate': ['hetmanate', 'methanate'], + 'hetter': ['hetter', 'tether'], + 'hevea': ['heave', 'hevea'], + 'hevi': ['hevi', 'hive'], + 'hewel': ['hewel', 'wheel'], + 'hewer': ['hewer', 'wheer', 'where'], + 'hewn': ['hewn', 'when'], + 'hewt': ['hewt', 'thew', 'whet'], + 'hexacid': ['hexacid', 'hexadic'], + 'hexadic': ['hexacid', 'hexadic'], + 'hexakisoctahedron': ['hexakisoctahedron', 'octakishexahedron'], + 'hexakistetrahedron': ['hexakistetrahedron', 'tetrakishexahedron'], + 'hexatetrahedron': ['hexatetrahedron', 'tetrahexahedron'], + 'hexatomic': ['hematoxic', 'hexatomic'], + 'hexonic': ['choenix', 'hexonic'], + 'hiant': ['ahint', 'hiant', 'tahin'], + 'hiatal': ['hiatal', 'thalia'], + 'hibernate': ['hibernate', 'inbreathe'], + 'hic': ['chi', 'hic', 'ich'], + 'hickwall': ['hickwall', 'wallhick'], + 'hidage': ['adighe', 'hidage'], + 'hider': ['dheri', 'hider', 'hired'], + 'hidling': ['hidling', 'hilding'], + 'hidlings': ['dishling', 'hidlings'], + 'hidrotic': ['hidrotic', 'trichoid'], + 'hie': ['hei', 'hie'], + 'hield': ['delhi', 'hield'], + 'hiemal': ['hameil', 'hiemal'], + 'hienz': ['heinz', 'hienz'], + 'hieron': ['heroin', 'hieron', 'hornie'], + 'hieros': ['hieros', 'hosier'], + 'hight': ['hight', 'thigh'], + 'higuero': ['higuero', 'roughie'], + 'hilasmic': ['chiliasm', 'hilasmic', 'machilis'], + 'hilding': ['hidling', 'hilding'], + 'hillside': ['hillside', 'sidehill'], + 'hilsa': ['alish', 'hilsa'], + 'hilt': ['hilt', 'lith'], + 'hima': ['hami', 'hima', 'mahi'], + 'himself': ['flemish', 'himself'], + 'hinderest': ['disherent', 'hinderest', 'tenderish'], + 'hindu': ['hindu', 'hundi', 'unhid'], + 'hing': ['hing', 'nigh'], + 'hinge': ['hinge', 'neigh'], + 'hingle': ['heling', 'hingle'], + 'hint': ['hint', 'thin'], + 'hinter': ['hinter', 'nither', 'theirn'], + 'hintproof': ['hintproof', 'hoofprint'], + 'hintzeite': ['heintzite', 'hintzeite'], + 'hip': ['hip', 'phi'], + 'hipbone': ['hipbone', 'hopbine'], + 'hippodamous': ['amphipodous', 'hippodamous'], + 'hippolyte': ['hippolyte', 'typophile'], + 'hippus': ['hippus', 'uppish'], + 'hiram': ['hiram', 'ihram', 'mahri'], + 'hircine': ['hircine', 'rheinic'], + 'hire': ['heir', 'hire'], + 'hired': ['dheri', 'hider', 'hired'], + 'hireless': ['heirless', 'hireless'], + 'hireman': ['harmine', 'hireman'], + 'hiren': ['hiren', 'rhein', 'rhine'], + 'hirmos': ['hirmos', 'romish'], + 'hirse': ['hirse', 'shier', 'shire'], + 'hirsel': ['hirsel', 'hirsle', 'relish'], + 'hirsle': ['hirsel', 'hirsle', 'relish'], + 'his': ['his', 'hsi', 'shi'], + 'hish': ['hish', 'shih'], + 'hisn': ['hisn', 'shin', 'sinh'], + 'hispa': ['aphis', 'apish', 'hispa', 'saiph', 'spahi'], + 'hispanist': ['hispanist', 'saintship'], + 'hiss': ['hiss', 'sish'], + 'hist': ['hist', 'sith', 'this', 'tshi'], + 'histamine': ['histamine', 'semihiant'], + 'histie': ['histie', 'shiite'], + 'histioid': ['histioid', 'idiotish'], + 'histon': ['histon', 'shinto', 'tonish'], + 'histonal': ['histonal', 'toshnail'], + 'historic': ['historic', 'orchitis'], + 'historics': ['historics', 'trichosis'], + 'history': ['history', 'toryish'], + 'hittable': ['hittable', 'tithable'], + 'hitter': ['hitter', 'tither'], + 'hive': ['hevi', 'hive'], + 'hives': ['hives', 'shive'], + 'hler': ['herl', 'hler', 'lehr'], + 'ho': ['ho', 'oh'], + 'hoar': ['hoar', 'hora'], + 'hoard': ['hoard', 'rhoda'], + 'hoarse': ['ahorse', 'ashore', 'hoarse', 'shorea'], + 'hoarstone': ['anorthose', 'hoarstone'], + 'hoast': ['hoast', 'hosta', 'shoat'], + 'hobbism': ['hobbism', 'mobbish'], + 'hobo': ['boho', 'hobo'], + 'hocco': ['choco', 'hocco'], + 'hock': ['hock', 'koch'], + 'hocker': ['choker', 'hocker'], + 'hocky': ['choky', 'hocky'], + 'hocus': ['chous', 'hocus'], + 'hodiernal': ['hodiernal', 'rhodaline'], + 'hoer': ['hero', 'hoer'], + 'hogan': ['ahong', 'hogan'], + 'hogget': ['egghot', 'hogget'], + 'hogmanay': ['hogmanay', 'mahogany'], + 'hognut': ['hognut', 'nought'], + 'hogsty': ['ghosty', 'hogsty'], + 'hoister': ['hoister', 'rehoist'], + 'hoit': ['hoit', 'hoti', 'thio'], + 'holard': ['harold', 'holard'], + 'holconoti': ['holconoti', 'holotonic'], + 'holcus': ['holcus', 'lochus', 'slouch'], + 'holdfast': ['fasthold', 'holdfast'], + 'holdout': ['holdout', 'outhold'], + 'holdup': ['holdup', 'uphold'], + 'holeman': ['holeman', 'manhole'], + 'holey': ['holey', 'hoyle'], + 'holiday': ['holiday', 'hyaloid', 'hyoidal'], + 'hollandite': ['hollandite', 'hollantide'], + 'hollantide': ['hollandite', 'hollantide'], + 'hollower': ['hollower', 'rehollow'], + 'holmia': ['holmia', 'maholi'], + 'holocentrid': ['holocentrid', 'lechriodont'], + 'holohemihedral': ['hemiholohedral', 'holohemihedral'], + 'holosteric': ['holosteric', 'thiocresol'], + 'holotonic': ['holconoti', 'holotonic'], + 'holster': ['holster', 'hostler'], + 'homage': ['homage', 'ohmage'], + 'homarine': ['homarine', 'homerian'], + 'homecroft': ['forthcome', 'homecroft'], + 'homeogenous': ['homeogenous', 'homogeneous'], + 'homeotypic': ['homeotypic', 'mythopoeic'], + 'homeotypical': ['homeotypical', 'polymetochia'], + 'homer': ['hermo', 'homer', 'horme'], + 'homerian': ['homarine', 'homerian'], + 'homeric': ['homeric', 'moriche'], + 'homerical': ['chloremia', 'homerical'], + 'homerid': ['heirdom', 'homerid'], + 'homerist': ['homerist', 'isotherm', 'otherism', 'theorism'], + 'homiletics': ['homiletics', 'mesolithic'], + 'homo': ['homo', 'moho'], + 'homocline': ['chemiloon', 'homocline'], + 'homogeneous': ['homeogenous', 'homogeneous'], + 'homopolic': ['homopolic', 'lophocomi'], + 'homopteran': ['homopteran', 'trophonema'], + 'homrai': ['homrai', 'mahori', 'mohair'], + 'hondo': ['dhoon', 'hondo'], + 'honest': ['ethnos', 'honest'], + 'honeypod': ['dyophone', 'honeypod'], + 'honeypot': ['eophyton', 'honeypot'], + 'honorer': ['honorer', 'rehonor'], + 'hontous': ['hontous', 'nothous'], + 'hoodman': ['dhamnoo', 'hoodman', 'manhood'], + 'hoofprint': ['hintproof', 'hoofprint'], + 'hooker': ['hooker', 'rehook'], + 'hookweed': ['hookweed', 'weedhook'], + 'hoop': ['hoop', 'phoo', 'pooh'], + 'hooper': ['hooper', 'rehoop'], + 'hoot': ['hoot', 'thoo', 'toho'], + 'hop': ['hop', 'pho', 'poh'], + 'hopbine': ['hipbone', 'hopbine'], + 'hopcalite': ['hopcalite', 'phacolite'], + 'hope': ['hope', 'peho'], + 'hoped': ['depoh', 'ephod', 'hoped'], + 'hoper': ['ephor', 'hoper'], + 'hoplite': ['hoplite', 'pithole'], + 'hoppergrass': ['grasshopper', 'hoppergrass'], + 'hoppers': ['hoppers', 'shopper'], + 'hora': ['hoar', 'hora'], + 'horal': ['horal', 'lohar'], + 'hordarian': ['arianrhod', 'hordarian'], + 'horizontal': ['horizontal', 'notorhizal'], + 'horme': ['hermo', 'homer', 'horme'], + 'horned': ['dehorn', 'horned'], + 'hornet': ['hornet', 'nother', 'theron', 'throne'], + 'hornie': ['heroin', 'hieron', 'hornie'], + 'hornpipe': ['hornpipe', 'porphine'], + 'horopteric': ['horopteric', 'rheotropic', 'trichopore'], + 'horrent': ['horrent', 'norther'], + 'horse': ['horse', 'shoer', 'shore'], + 'horsecar': ['cosharer', 'horsecar'], + 'horseless': ['horseless', 'shoreless'], + 'horseman': ['horseman', 'rhamnose', 'shoreman'], + 'horser': ['horser', 'shorer'], + 'horsetail': ['horsetail', 'isotheral'], + 'horseweed': ['horseweed', 'shoreweed'], + 'horsewhip': ['horsewhip', 'whoreship'], + 'horsewood': ['horsewood', 'woodhorse'], + 'horsing': ['horsing', 'shoring'], + 'horst': ['horst', 'short'], + 'hortensia': ['hairstone', 'hortensia'], + 'hortite': ['hortite', 'orthite', 'thorite'], + 'hose': ['hose', 'shoe'], + 'hosed': ['hosed', 'shode'], + 'hosel': ['hosel', 'sheol', 'shole'], + 'hoseless': ['hoseless', 'shoeless'], + 'hoseman': ['hoseman', 'shoeman'], + 'hosier': ['hieros', 'hosier'], + 'hospitaler': ['hospitaler', 'trophesial'], + 'host': ['host', 'shot', 'thos', 'tosh'], + 'hosta': ['hoast', 'hosta', 'shoat'], + 'hostager': ['hostager', 'shortage'], + 'hoster': ['hoster', 'tosher'], + 'hostile': ['elohist', 'hostile'], + 'hosting': ['hosting', 'onsight'], + 'hostler': ['holster', 'hostler'], + 'hostless': ['hostless', 'shotless'], + 'hostly': ['hostly', 'toshly'], + 'hot': ['hot', 'tho'], + 'hotel': ['helot', 'hotel', 'thole'], + 'hotelize': ['helotize', 'hotelize'], + 'hotfoot': ['foothot', 'hotfoot'], + 'hoti': ['hoit', 'hoti', 'thio'], + 'hotter': ['hotter', 'tother'], + 'hounce': ['cohune', 'hounce'], + 'houseboat': ['boathouse', 'houseboat'], + 'housebug': ['bughouse', 'housebug'], + 'housecraft': ['fratcheous', 'housecraft'], + 'housetop': ['housetop', 'pothouse'], + 'housewarm': ['housewarm', 'warmhouse'], + 'housewear': ['housewear', 'warehouse'], + 'housework': ['housework', 'workhouse'], + 'hovering': ['hovering', 'overnigh'], + 'how': ['how', 'who'], + 'howel': ['howel', 'whole'], + 'however': ['everwho', 'however', 'whoever'], + 'howlet': ['howlet', 'thowel'], + 'howso': ['howso', 'woosh'], + 'howsomever': ['howsomever', 'whomsoever', 'whosomever'], + 'hoya': ['ahoy', 'hoya'], + 'hoyle': ['holey', 'hoyle'], + 'hsi': ['his', 'hsi', 'shi'], + 'huari': ['huari', 'uriah'], + 'hubert': ['hubert', 'turbeh'], + 'hud': ['dhu', 'hud'], + 'hudsonite': ['hudsonite', 'unhoisted'], + 'huer': ['huer', 'hure'], + 'hug': ['hug', 'ugh'], + 'hughes': ['hughes', 'sheugh'], + 'hughoc': ['chough', 'hughoc'], + 'hugo': ['hugo', 'ough'], + 'hugsome': ['gumshoe', 'hugsome'], + 'huk': ['huk', 'khu'], + 'hula': ['haul', 'hula'], + 'hulsean': ['hulsean', 'unleash'], + 'hulster': ['hulster', 'hustler', 'sluther'], + 'huma': ['ahum', 'huma'], + 'human': ['human', 'nahum'], + 'humane': ['humane', 'humean'], + 'humanics': ['humanics', 'inasmuch'], + 'humean': ['humane', 'humean'], + 'humeroradial': ['humeroradial', 'radiohumeral'], + 'humic': ['chimu', 'humic'], + 'humidor': ['humidor', 'rhodium'], + 'humlie': ['helium', 'humlie'], + 'humor': ['humor', 'mohur'], + 'humoralistic': ['humoralistic', 'humoristical'], + 'humoristical': ['humoralistic', 'humoristical'], + 'hump': ['hump', 'umph'], + 'hundi': ['hindu', 'hundi', 'unhid'], + 'hunger': ['hunger', 'rehung'], + 'hunterian': ['hunterian', 'ruthenian'], + 'hup': ['hup', 'phu'], + 'hupa': ['hapu', 'hupa'], + 'hurdis': ['hurdis', 'rudish'], + 'hurdle': ['hurdle', 'hurled'], + 'hure': ['huer', 'hure'], + 'hurled': ['hurdle', 'hurled'], + 'huron': ['huron', 'rohun'], + 'hurst': ['hurst', 'trush'], + 'hurt': ['hurt', 'ruth'], + 'hurter': ['hurter', 'ruther'], + 'hurtful': ['hurtful', 'ruthful'], + 'hurtfully': ['hurtfully', 'ruthfully'], + 'hurtfulness': ['hurtfulness', 'ruthfulness'], + 'hurting': ['hurting', 'ungirth', 'unright'], + 'hurtingest': ['hurtingest', 'shuttering'], + 'hurtle': ['hurtle', 'luther'], + 'hurtless': ['hurtless', 'ruthless'], + 'hurtlessly': ['hurtlessly', 'ruthlessly'], + 'hurtlessness': ['hurtlessness', 'ruthlessness'], + 'husbander': ['husbander', 'shabunder'], + 'husked': ['dehusk', 'husked'], + 'huso': ['huso', 'shou'], + 'huspil': ['huspil', 'pulish'], + 'husting': ['gutnish', 'husting', 'unsight'], + 'hustle': ['hustle', 'sleuth'], + 'hustler': ['hulster', 'hustler', 'sluther'], + 'huterian': ['haurient', 'huterian'], + 'hwa': ['haw', 'hwa', 'wah', 'wha'], + 'hyaloid': ['holiday', 'hyaloid', 'hyoidal'], + 'hydra': ['hardy', 'hydra'], + 'hydramnios': ['disharmony', 'hydramnios'], + 'hydrate': ['hydrate', 'thready'], + 'hydrazidine': ['anhydridize', 'hydrazidine'], + 'hydrazine': ['anhydrize', 'hydrazine'], + 'hydriodate': ['hydriodate', 'iodhydrate'], + 'hydriodic': ['hydriodic', 'iodhydric'], + 'hydriote': ['hydriote', 'thyreoid'], + 'hydrobromate': ['bromohydrate', 'hydrobromate'], + 'hydrocarbide': ['carbohydride', 'hydrocarbide'], + 'hydrocharis': ['hydrocharis', 'hydrorachis'], + 'hydroferricyanic': ['ferrihydrocyanic', 'hydroferricyanic'], + 'hydroferrocyanic': ['ferrohydrocyanic', 'hydroferrocyanic'], + 'hydrofluoboric': ['borofluohydric', 'hydrofluoboric'], + 'hydrogeology': ['geohydrology', 'hydrogeology'], + 'hydroiodic': ['hydroiodic', 'iodohydric'], + 'hydrometeor': ['heterodromy', 'hydrometeor'], + 'hydromotor': ['hydromotor', 'orthodromy'], + 'hydronephrosis': ['hydronephrosis', 'nephrohydrosis'], + 'hydropneumopericardium': ['hydropneumopericardium', 'pneumohydropericardium'], + 'hydropneumothorax': ['hydropneumothorax', 'pneumohydrothorax'], + 'hydrorachis': ['hydrocharis', 'hydrorachis'], + 'hydrosulphate': ['hydrosulphate', 'sulphohydrate'], + 'hydrotical': ['dacryolith', 'hydrotical'], + 'hydrous': ['hydrous', 'shroudy'], + 'hyetograph': ['ethography', 'hyetograph'], + 'hylidae': ['headily', 'hylidae'], + 'hylist': ['hylist', 'slithy'], + 'hyllus': ['hyllus', 'lushly'], + 'hylopathism': ['halophytism', 'hylopathism'], + 'hymenic': ['chimney', 'hymenic'], + 'hymettic': ['hymettic', 'thymetic'], + 'hymnologist': ['hymnologist', 'smoothingly'], + 'hyoglossal': ['glossohyal', 'hyoglossal'], + 'hyoidal': ['holiday', 'hyaloid', 'hyoidal'], + 'hyothyreoid': ['hyothyreoid', 'thyreohyoid'], + 'hyothyroid': ['hyothyroid', 'thyrohyoid'], + 'hypaethron': ['hypaethron', 'hypothenar'], + 'hypercone': ['coryphene', 'hypercone'], + 'hypergamous': ['hypergamous', 'museography'], + 'hypertoxic': ['hypertoxic', 'xerophytic'], + 'hypnobate': ['batyphone', 'hypnobate'], + 'hypnoetic': ['hypnoetic', 'neophytic'], + 'hypnotic': ['hypnotic', 'phytonic', 'pythonic', 'typhonic'], + 'hypnotism': ['hypnotism', 'pythonism'], + 'hypnotist': ['hypnotist', 'pythonist'], + 'hypnotize': ['hypnotize', 'pythonize'], + 'hypnotoid': ['hypnotoid', 'pythonoid'], + 'hypobole': ['hypobole', 'lyophobe'], + 'hypocarp': ['apocryph', 'hypocarp'], + 'hypocrite': ['chirotype', 'hypocrite'], + 'hypodorian': ['hypodorian', 'radiophony'], + 'hypoglottis': ['hypoglottis', 'phytologist'], + 'hypomanic': ['amphicyon', 'hypomanic'], + 'hypopteron': ['hypopteron', 'phonotyper'], + 'hyporadius': ['hyporadius', 'suprahyoid'], + 'hyposcleral': ['hyposcleral', 'phylloceras'], + 'hyposmia': ['hyposmia', 'phymosia'], + 'hypostomatic': ['hypostomatic', 'somatophytic'], + 'hypothec': ['hypothec', 'photechy'], + 'hypothenar': ['hypaethron', 'hypothenar'], + 'hypothermia': ['hemiatrophy', 'hypothermia'], + 'hypsiloid': ['hypsiloid', 'syphiloid'], + 'hyracid': ['diarchy', 'hyracid'], + 'hyssop': ['hyssop', 'phossy', 'sposhy'], + 'hysteresial': ['hysteresial', 'hysteriales'], + 'hysteria': ['hysteria', 'sheriyat'], + 'hysteriales': ['hysteresial', 'hysteriales'], + 'hysterolaparotomy': ['hysterolaparotomy', 'laparohysterotomy'], + 'hysteromyomectomy': ['hysteromyomectomy', 'myomohysterectomy'], + 'hysteropathy': ['hysteropathy', 'hysterophyta'], + 'hysterophyta': ['hysteropathy', 'hysterophyta'], + 'iamb': ['iamb', 'mabi'], + 'iambelegus': ['elegiambus', 'iambelegus'], + 'iambic': ['cimbia', 'iambic'], + 'ian': ['ani', 'ian'], + 'ianus': ['ianus', 'suina'], + 'iatraliptics': ['iatraliptics', 'partialistic'], + 'iatric': ['iatric', 'tricia'], + 'ibad': ['adib', 'ibad'], + 'iban': ['bain', 'bani', 'iban'], + 'ibanag': ['bagani', 'bangia', 'ibanag'], + 'iberian': ['aribine', 'bairnie', 'iberian'], + 'ibo': ['ibo', 'obi'], + 'ibota': ['biota', 'ibota'], + 'icacorea': ['coraciae', 'icacorea'], + 'icarian': ['arician', 'icarian'], + 'icecap': ['icecap', 'ipecac'], + 'iced': ['dice', 'iced'], + 'iceland': ['cladine', 'decalin', 'iceland'], + 'icelandic': ['cicindela', 'cinclidae', 'icelandic'], + 'iceman': ['anemic', 'cinema', 'iceman'], + 'ich': ['chi', 'hic', 'ich'], + 'ichnolite': ['ichnolite', 'neolithic'], + 'ichor': ['chiro', 'choir', 'ichor'], + 'icicle': ['cilice', 'icicle'], + 'icon': ['cion', 'coin', 'icon'], + 'iconian': ['anionic', 'iconian'], + 'iconism': ['iconism', 'imsonic', 'miscoin'], + 'iconolater': ['iconolater', 'relocation'], + 'iconomania': ['iconomania', 'oniomaniac'], + 'iconometrical': ['iconometrical', 'intracoelomic'], + 'icteridae': ['diaeretic', 'icteridae'], + 'icterine': ['icterine', 'reincite'], + 'icterus': ['curtise', 'icterus'], + 'ictonyx': ['ictonyx', 'oxyntic'], + 'ictus': ['cutis', 'ictus'], + 'id': ['di', 'id'], + 'ida': ['aid', 'ida'], + 'idaean': ['adenia', 'idaean'], + 'ide': ['die', 'ide'], + 'idea': ['aide', 'idea'], + 'ideal': ['adiel', 'delia', 'ideal'], + 'idealism': ['idealism', 'lamiides'], + 'idealistic': ['disilicate', 'idealistic'], + 'ideality': ['aedility', 'ideality'], + 'idealness': ['idealness', 'leadiness'], + 'idean': ['diane', 'idean'], + 'ideation': ['ideation', 'iodinate', 'taenioid'], + 'identical': ['ctenidial', 'identical'], + 'ideograph': ['eidograph', 'ideograph'], + 'ideology': ['eidology', 'ideology'], + 'ideoplasty': ['ideoplasty', 'stylopidae'], + 'ides': ['desi', 'ides', 'seid', 'side'], + 'idiasm': ['idiasm', 'simiad'], + 'idioblast': ['diabolist', 'idioblast'], + 'idiomology': ['idiomology', 'oligomyoid'], + 'idioretinal': ['idioretinal', 'litorinidae'], + 'idiotish': ['histioid', 'idiotish'], + 'idle': ['idle', 'lide', 'lied'], + 'idleman': ['idleman', 'melinda'], + 'idleset': ['idleset', 'isleted'], + 'idlety': ['idlety', 'lydite', 'tidely', 'tidley'], + 'idly': ['idly', 'idyl'], + 'idocrase': ['idocrase', 'radicose'], + 'idoism': ['idoism', 'iodism'], + 'idol': ['dilo', 'diol', 'doli', 'idol', 'olid'], + 'idola': ['aloid', 'dolia', 'idola'], + 'idolaster': ['estradiol', 'idolaster'], + 'idolatry': ['adroitly', 'dilatory', 'idolatry'], + 'idolum': ['dolium', 'idolum'], + 'idoneal': ['adinole', 'idoneal'], + 'idorgan': ['gordian', 'idorgan', 'roading'], + 'idose': ['diose', 'idose', 'oside'], + 'idotea': ['idotea', 'iodate', 'otidae'], + 'idryl': ['idryl', 'lyrid'], + 'idyl': ['idly', 'idyl'], + 'idyler': ['direly', 'idyler'], + 'ierne': ['ernie', 'ierne', 'irene'], + 'if': ['fi', 'if'], + 'ife': ['fei', 'fie', 'ife'], + 'igara': ['agria', 'igara'], + 'igdyr': ['igdyr', 'ridgy'], + 'igloo': ['igloo', 'logoi'], + 'ignatius': ['giustina', 'ignatius'], + 'igneoaqueous': ['aqueoigneous', 'igneoaqueous'], + 'ignicolist': ['ignicolist', 'soliciting'], + 'igniter': ['igniter', 'ringite', 'tigrine'], + 'ignitor': ['ignitor', 'rioting'], + 'ignoble': ['gobelin', 'gobline', 'ignoble', 'inglobe'], + 'ignoramus': ['graminous', 'ignoramus'], + 'ignorance': ['enorganic', 'ignorance'], + 'ignorant': ['ignorant', 'tongrian'], + 'ignore': ['ignore', 'region'], + 'ignorement': ['ignorement', 'omnigerent'], + 'iguana': ['guiana', 'iguana'], + 'ihlat': ['ihlat', 'tahil'], + 'ihram': ['hiram', 'ihram', 'mahri'], + 'ijma': ['ijma', 'jami'], + 'ikat': ['atik', 'ikat'], + 'ikona': ['ikona', 'konia'], + 'ikra': ['ikra', 'kari', 'raki'], + 'ila': ['ail', 'ila', 'lai'], + 'ileac': ['alice', 'celia', 'ileac'], + 'ileon': ['enoil', 'ileon', 'olein'], + 'iliac': ['cilia', 'iliac'], + 'iliacus': ['acilius', 'iliacus'], + 'ilian': ['ilian', 'inial'], + 'ilicaceae': ['caeciliae', 'ilicaceae'], + 'ilioischiac': ['ilioischiac', 'ischioiliac'], + 'iliosacral': ['iliosacral', 'oscillaria'], + 'ilk': ['ilk', 'kil'], + 'ilka': ['ilka', 'kail', 'kali'], + 'ilkane': ['alkine', 'ilkane', 'inlake', 'inleak'], + 'illative': ['illative', 'veiltail'], + 'illaudatory': ['illaudatory', 'laudatorily'], + 'illeck': ['ellick', 'illeck'], + 'illinois': ['illinois', 'illision'], + 'illision': ['illinois', 'illision'], + 'illium': ['illium', 'lilium'], + 'illoricated': ['illoricated', 'lacertiloid'], + 'illth': ['illth', 'thill'], + 'illude': ['dillue', 'illude'], + 'illuder': ['dilluer', 'illuder'], + 'illy': ['illy', 'lily', 'yill'], + 'ilmenite': ['ilmenite', 'melinite', 'menilite'], + 'ilongot': ['ilongot', 'tooling'], + 'ilot': ['ilot', 'toil'], + 'ilya': ['ilya', 'yali'], + 'ima': ['aim', 'ami', 'ima'], + 'imager': ['imager', 'maigre', 'margie', 'mirage'], + 'imaginant': ['animating', 'imaginant'], + 'imaginer': ['imaginer', 'migraine'], + 'imagist': ['imagist', 'stigmai'], + 'imago': ['amigo', 'imago'], + 'imam': ['ammi', 'imam', 'maim', 'mima'], + 'imaret': ['imaret', 'metria', 'mirate', 'rimate'], + 'imbarge': ['gambier', 'imbarge'], + 'imbark': ['bikram', 'imbark'], + 'imbat': ['ambit', 'imbat'], + 'imbed': ['bedim', 'imbed'], + 'imbrue': ['erbium', 'imbrue'], + 'imbrute': ['burmite', 'imbrute', 'terbium'], + 'imer': ['emir', 'imer', 'mire', 'reim', 'remi', 'riem', 'rime'], + 'imerina': ['imerina', 'inermia'], + 'imitancy': ['imitancy', 'intimacy', 'minacity'], + 'immane': ['ammine', 'immane'], + 'immanes': ['amenism', 'immanes', 'misname'], + 'immaterials': ['immaterials', 'materialism'], + 'immerd': ['dimmer', 'immerd', 'rimmed'], + 'immersible': ['immersible', 'semilimber'], + 'immersion': ['immersion', 'semiminor'], + 'immi': ['immi', 'mimi'], + 'imogen': ['geonim', 'imogen'], + 'imolinda': ['dominial', 'imolinda', 'limoniad'], + 'imp': ['imp', 'pim'], + 'impaction': ['impaction', 'ptomainic'], + 'impages': ['impages', 'mispage'], + 'impaint': ['impaint', 'timpani'], + 'impair': ['impair', 'pamiri'], + 'impala': ['impala', 'malapi'], + 'impaler': ['impaler', 'impearl', 'lempira', 'premial'], + 'impalsy': ['impalsy', 'misplay'], + 'impane': ['impane', 'pieman'], + 'impanel': ['impanel', 'maniple'], + 'impar': ['impar', 'pamir', 'prima'], + 'imparalleled': ['demiparallel', 'imparalleled'], + 'imparl': ['imparl', 'primal'], + 'impart': ['armpit', 'impart'], + 'imparter': ['imparter', 'reimpart'], + 'impartial': ['impartial', 'primatial'], + 'impaste': ['impaste', 'pastime'], + 'impasture': ['impasture', 'septarium'], + 'impeach': ['aphemic', 'impeach'], + 'impearl': ['impaler', 'impearl', 'lempira', 'premial'], + 'impeder': ['demirep', 'epiderm', 'impeder', 'remiped'], + 'impedient': ['impedient', 'mendipite'], + 'impenetrable': ['impenetrable', 'intemperable'], + 'impenetrably': ['impenetrably', 'intemperably'], + 'impenetrate': ['impenetrate', 'intemperate'], + 'imperant': ['imperant', 'pairment', 'partimen', 'premiant', 'tripeman'], + 'imperate': ['imperate', 'premiate'], + 'imperish': ['emirship', 'imperish'], + 'imperscriptible': ['imperscriptible', 'imprescriptible'], + 'impersonate': ['impersonate', 'proseminate'], + 'impersonation': ['impersonation', 'prosemination', 'semipronation'], + 'impeticos': ['impeticos', 'poeticism'], + 'impetre': ['emptier', 'impetre'], + 'impetus': ['impetus', 'upsmite'], + 'imphee': ['imphee', 'phemie'], + 'implacental': ['capillament', 'implacental'], + 'implanter': ['implanter', 'reimplant'], + 'implate': ['implate', 'palmite'], + 'impleader': ['epidermal', 'impleader', 'premedial'], + 'implicate': ['ampelitic', 'implicate'], + 'impling': ['impling', 'limping'], + 'imply': ['imply', 'limpy', 'pilmy'], + 'impollute': ['impollute', 'multipole'], + 'imponderous': ['endosporium', 'imponderous'], + 'imponent': ['imponent', 'pimenton'], + 'importable': ['bitemporal', 'importable'], + 'importancy': ['importancy', 'patronymic', 'pyromantic'], + 'importer': ['importer', 'promerit', 'reimport'], + 'importunance': ['importunance', 'unimportance'], + 'importunate': ['importunate', 'permutation'], + 'importune': ['entropium', 'importune'], + 'imposal': ['imposal', 'spiloma'], + 'imposer': ['imposer', 'promise', 'semipro'], + 'imposter': ['imposter', 'tripsome'], + 'imposure': ['imposure', 'premious'], + 'imprecatory': ['cryptomeria', 'imprecatory'], + 'impreg': ['gimper', 'impreg'], + 'imprescriptible': ['imperscriptible', 'imprescriptible'], + 'imprese': ['emprise', 'imprese', 'premise', 'spireme'], + 'impress': ['impress', 'persism', 'premiss'], + 'impresser': ['impresser', 'reimpress'], + 'impressibility': ['impressibility', 'permissibility'], + 'impressible': ['impressible', 'permissible'], + 'impressibleness': ['impressibleness', 'permissibleness'], + 'impressibly': ['impressibly', 'permissibly'], + 'impression': ['impression', 'permission'], + 'impressionism': ['impressionism', 'misimpression'], + 'impressive': ['impressive', 'permissive'], + 'impressively': ['impressively', 'permissively'], + 'impressiveness': ['impressiveness', 'permissiveness'], + 'impressure': ['impressure', 'presurmise'], + 'imprinter': ['imprinter', 'reimprint'], + 'imprisoner': ['imprisoner', 'reimprison'], + 'improcreant': ['improcreant', 'preromantic'], + 'impship': ['impship', 'pimpish'], + 'impuberal': ['epilabrum', 'impuberal'], + 'impugnable': ['impugnable', 'plumbagine'], + 'impure': ['impure', 'umpire'], + 'impuritan': ['impuritan', 'partinium'], + 'imputer': ['imputer', 'trumpie'], + 'imsonic': ['iconism', 'imsonic', 'miscoin'], + 'in': ['in', 'ni'], + 'inaction': ['aconitin', 'inaction', 'nicotian'], + 'inactivate': ['inactivate', 'vaticinate'], + 'inactivation': ['inactivation', 'vaticination'], + 'inactive': ['antivice', 'inactive', 'vineatic'], + 'inadept': ['depaint', 'inadept', 'painted', 'patined'], + 'inaja': ['inaja', 'jaina'], + 'inalimental': ['antimallein', 'inalimental'], + 'inamorata': ['amatorian', 'inamorata'], + 'inane': ['annie', 'inane'], + 'inanga': ['angina', 'inanga'], + 'inanimate': ['amanitine', 'inanimate'], + 'inanimated': ['diamantine', 'inanimated'], + 'inapt': ['inapt', 'paint', 'pinta'], + 'inaptly': ['inaptly', 'planity', 'ptyalin'], + 'inarch': ['chinar', 'inarch'], + 'inarm': ['inarm', 'minar'], + 'inasmuch': ['humanics', 'inasmuch'], + 'inaurate': ['inaurate', 'ituraean'], + 'inbe': ['beni', 'bien', 'bine', 'inbe'], + 'inbreak': ['brankie', 'inbreak'], + 'inbreathe': ['hibernate', 'inbreathe'], + 'inbred': ['binder', 'inbred', 'rebind'], + 'inbreed': ['birdeen', 'inbreed'], + 'inca': ['cain', 'inca'], + 'incaic': ['acinic', 'incaic'], + 'incarnate': ['cratinean', 'incarnate', 'nectarian'], + 'incase': ['casein', 'incase'], + 'incast': ['incast', 'nastic'], + 'incensation': ['incensation', 'inscenation'], + 'incept': ['incept', 'pectin'], + 'inceptor': ['inceptor', 'pretonic'], + 'inceration': ['cineration', 'inceration'], + 'incessant': ['anticness', 'cantiness', 'incessant'], + 'incest': ['encist', 'incest', 'insect', 'scient'], + 'inch': ['chin', 'inch'], + 'inched': ['chined', 'inched'], + 'inchoate': ['inchoate', 'noachite'], + 'incide': ['cindie', 'incide'], + 'incinerate': ['creatinine', 'incinerate'], + 'incisal': ['incisal', 'salicin'], + 'incision': ['incision', 'inosinic'], + 'incisure': ['incisure', 'sciurine'], + 'inciter': ['citrine', 'crinite', 'inciter', 'neritic'], + 'inclinatorium': ['anticlinorium', 'inclinatorium'], + 'inclosure': ['cornelius', 'inclosure', 'reclusion'], + 'include': ['include', 'nuclide'], + 'incluse': ['esculin', 'incluse'], + 'incog': ['coign', 'incog'], + 'incognito': ['cognition', 'incognito'], + 'incoherence': ['coinherence', 'incoherence'], + 'incoherent': ['coinherent', 'incoherent'], + 'incomeless': ['comeliness', 'incomeless'], + 'incomer': ['incomer', 'moneric'], + 'incomputable': ['incomputable', 'uncompatible'], + 'incondite': ['incondite', 'nicotined'], + 'inconglomerate': ['inconglomerate', 'nongeometrical'], + 'inconsistent': ['inconsistent', 'nonscientist'], + 'inconsonant': ['inconsonant', 'nonsanction'], + 'incontrovertibility': ['incontrovertibility', 'introconvertibility'], + 'incontrovertible': ['incontrovertible', 'introconvertible'], + 'incorporate': ['incorporate', 'procreation'], + 'incorporated': ['adrenotropic', 'incorporated'], + 'incorpse': ['conspire', 'incorpse'], + 'incrash': ['archsin', 'incrash'], + 'increase': ['cerasein', 'increase'], + 'increate': ['aneretic', 'centiare', 'creatine', 'increate', 'iterance'], + 'incredited': ['incredited', 'indirected'], + 'increep': ['crepine', 'increep'], + 'increpate': ['anticreep', 'apenteric', 'increpate'], + 'increst': ['cistern', 'increst'], + 'incruental': ['incruental', 'unicentral'], + 'incrustant': ['incrustant', 'scrutinant'], + 'incrustate': ['incrustate', 'scaturient', 'scrutinate'], + 'incubate': ['cubanite', 'incubate'], + 'incudal': ['dulcian', 'incudal', 'lucanid', 'lucinda'], + 'incudomalleal': ['incudomalleal', 'malleoincudal'], + 'inculcation': ['anticouncil', 'inculcation'], + 'inculture': ['culturine', 'inculture'], + 'incuneation': ['enunciation', 'incuneation'], + 'incur': ['curin', 'incur', 'runic'], + 'incurable': ['binuclear', 'incurable'], + 'incus': ['incus', 'usnic'], + 'incut': ['cutin', 'incut', 'tunic'], + 'ind': ['din', 'ind', 'nid'], + 'indaba': ['badian', 'indaba'], + 'indagator': ['gradation', 'indagator', 'tanagroid'], + 'indan': ['indan', 'nandi'], + 'indane': ['aidenn', 'andine', 'dannie', 'indane'], + 'inde': ['dine', 'enid', 'inde', 'nide'], + 'indebt': ['bident', 'indebt'], + 'indebted': ['bidented', 'indebted'], + 'indefinitude': ['indefinitude', 'unidentified'], + 'indent': ['dentin', 'indent', 'intend', 'tinned'], + 'indented': ['indented', 'intended'], + 'indentedly': ['indentedly', 'intendedly'], + 'indenter': ['indenter', 'intender', 'reintend'], + 'indentment': ['indentment', 'intendment'], + 'indentured': ['indentured', 'underntide'], + 'indentwise': ['disentwine', 'indentwise'], + 'indeprivable': ['indeprivable', 'predivinable'], + 'indesert': ['indesert', 'inserted', 'resident'], + 'indiana': ['anidian', 'indiana'], + 'indic': ['dinic', 'indic'], + 'indican': ['cnidian', 'indican'], + 'indicate': ['diacetin', 'indicate'], + 'indicatory': ['dictionary', 'indicatory'], + 'indicial': ['anilidic', 'indicial'], + 'indicter': ['indicter', 'indirect', 'reindict'], + 'indies': ['indies', 'inside'], + 'indigena': ['gadinine', 'indigena'], + 'indigitate': ['indigitate', 'tingitidae'], + 'indign': ['dining', 'indign', 'niding'], + 'indigoferous': ['gonidiferous', 'indigoferous'], + 'indigotin': ['digitonin', 'indigotin'], + 'indirect': ['indicter', 'indirect', 'reindict'], + 'indirected': ['incredited', 'indirected'], + 'indirectly': ['cylindrite', 'indirectly'], + 'indiscreet': ['indiscreet', 'indiscrete', 'iridescent'], + 'indiscreetly': ['indiscreetly', 'indiscretely', 'iridescently'], + 'indiscrete': ['indiscreet', 'indiscrete', 'iridescent'], + 'indiscretely': ['indiscreetly', 'indiscretely', 'iridescently'], + 'indissolute': ['delusionist', 'indissolute'], + 'indite': ['indite', 'tineid'], + 'inditer': ['inditer', 'nitride'], + 'indogaean': ['ganoidean', 'indogaean'], + 'indole': ['doline', 'indole', 'leonid', 'loined', 'olenid'], + 'indolence': ['endocline', 'indolence'], + 'indoles': ['indoles', 'sondeli'], + 'indologist': ['indologist', 'nidologist'], + 'indology': ['indology', 'nidology'], + 'indone': ['donnie', 'indone', 'ondine'], + 'indoors': ['indoors', 'sordino'], + 'indorse': ['indorse', 'ordines', 'siredon', 'sordine'], + 'indra': ['darin', 'dinar', 'drain', 'indra', 'nadir', 'ranid'], + 'indrawn': ['indrawn', 'winnard'], + 'induce': ['induce', 'uniced'], + 'inducer': ['inducer', 'uncried'], + 'indulge': ['dueling', 'indulge'], + 'indulgential': ['dentilingual', 'indulgential', 'linguidental'], + 'indulger': ['indulger', 'ungirdle'], + 'indument': ['indument', 'unminted'], + 'indurable': ['indurable', 'unbrailed', 'unridable'], + 'indurate': ['indurate', 'turdinae'], + 'induration': ['diurnation', 'induration'], + 'indus': ['dinus', 'indus', 'nidus'], + 'indusiform': ['disuniform', 'indusiform'], + 'induviae': ['induviae', 'viduinae'], + 'induvial': ['diluvian', 'induvial'], + 'inearth': ['anither', 'inearth', 'naither'], + 'inelastic': ['elasticin', 'inelastic', 'sciential'], + 'inelegant': ['eglantine', 'inelegant', 'legantine'], + 'ineludible': ['ineludible', 'unelidible'], + 'inept': ['inept', 'pinte'], + 'inequity': ['equinity', 'inequity'], + 'inerm': ['inerm', 'miner'], + 'inermes': ['ermines', 'inermes'], + 'inermia': ['imerina', 'inermia'], + 'inermous': ['inermous', 'monsieur'], + 'inert': ['inert', 'inter', 'niter', 'retin', 'trine'], + 'inertance': ['inertance', 'nectarine'], + 'inertial': ['inertial', 'linarite'], + 'inertly': ['elytrin', 'inertly', 'trinely'], + 'inethical': ['echinital', 'inethical'], + 'ineunt': ['ineunt', 'untine'], + 'inez': ['inez', 'zein'], + 'inface': ['fiance', 'inface'], + 'infame': ['famine', 'infame'], + 'infamy': ['infamy', 'manify'], + 'infarct': ['frantic', 'infarct', 'infract'], + 'infarction': ['infarction', 'infraction'], + 'infaust': ['faunist', 'fustian', 'infaust'], + 'infecter': ['frenetic', 'infecter', 'reinfect'], + 'infeed': ['define', 'infeed'], + 'infelt': ['finlet', 'infelt'], + 'infer': ['finer', 'infer'], + 'inferable': ['inferable', 'refinable'], + 'infern': ['finner', 'infern'], + 'inferoanterior': ['anteroinferior', 'inferoanterior'], + 'inferoposterior': ['inferoposterior', 'posteroinferior'], + 'infestation': ['festination', 'infestation', 'sinfonietta'], + 'infester': ['infester', 'reinfest'], + 'infidel': ['infidel', 'infield'], + 'infield': ['infidel', 'infield'], + 'inflame': ['feminal', 'inflame'], + 'inflamed': ['fieldman', 'inflamed'], + 'inflamer': ['inflamer', 'rifleman'], + 'inflatus': ['inflatus', 'stainful'], + 'inflicter': ['inflicter', 'reinflict'], + 'inform': ['formin', 'inform'], + 'informal': ['formalin', 'informal', 'laniform'], + 'informer': ['informer', 'reinform', 'reniform'], + 'infra': ['infra', 'irfan'], + 'infract': ['frantic', 'infarct', 'infract'], + 'infraction': ['infarction', 'infraction'], + 'infringe': ['infringe', 'refining'], + 'ing': ['gin', 'ing', 'nig'], + 'inga': ['gain', 'inga', 'naig', 'ngai'], + 'ingaevones': ['avignonese', 'ingaevones'], + 'ingate': ['eating', 'ingate', 'tangie'], + 'ingather': ['hearting', 'ingather'], + 'ingenue': ['genuine', 'ingenue'], + 'ingenuous': ['ingenuous', 'unigenous'], + 'inger': ['grein', 'inger', 'nigre', 'regin', 'reign', 'ringe'], + 'ingest': ['ingest', 'signet', 'stinge'], + 'ingesta': ['easting', + 'gainset', + 'genista', + 'ingesta', + 'seating', + 'signate', + 'teasing'], + 'ingle': ['ingle', 'ligne', 'linge', 'nigel'], + 'inglobe': ['gobelin', 'gobline', 'ignoble', 'inglobe'], + 'ingomar': ['ingomar', 'moringa', 'roaming'], + 'ingram': ['arming', 'ingram', 'margin'], + 'ingrate': ['angrite', 'granite', 'ingrate', 'tangier', 'tearing', 'tigrean'], + 'ingrow': ['ingrow', 'rowing'], + 'ingrowth': ['ingrowth', 'throwing'], + 'inguinal': ['inguinal', 'unailing'], + 'inguinocrural': ['cruroinguinal', 'inguinocrural'], + 'inhabiter': ['inhabiter', 'reinhabit'], + 'inhaler': ['hernial', 'inhaler'], + 'inhauler': ['herulian', 'inhauler'], + 'inhaust': ['auntish', 'inhaust'], + 'inhere': ['herein', 'inhere'], + 'inhumer': ['inhumer', 'rhenium'], + 'inial': ['ilian', 'inial'], + 'ink': ['ink', 'kin'], + 'inkle': ['inkle', 'liken'], + 'inkless': ['inkless', 'kinless'], + 'inkling': ['inkling', 'linking'], + 'inknot': ['inknot', 'tonkin'], + 'inkra': ['inkra', 'krina', 'nakir', 'rinka'], + 'inks': ['inks', 'sink', 'skin'], + 'inlaid': ['anilid', 'dialin', 'dianil', 'inlaid'], + 'inlake': ['alkine', 'ilkane', 'inlake', 'inleak'], + 'inlaut': ['inlaut', 'unital'], + 'inlaw': ['inlaw', 'liwan'], + 'inlay': ['inlay', 'naily'], + 'inlayer': ['inlayer', 'nailery'], + 'inleak': ['alkine', 'ilkane', 'inlake', 'inleak'], + 'inlet': ['inlet', 'linet'], + 'inlook': ['inlook', 'koilon'], + 'inly': ['inly', 'liny'], + 'inmate': ['etamin', 'inmate', 'taimen', 'tamein'], + 'inmeats': ['atenism', 'inmeats', 'insteam', 'samnite'], + 'inmost': ['inmost', 'monist', 'omnist'], + 'innate': ['annite', 'innate', 'tinean'], + 'innative': ['innative', 'invinate'], + 'innatural': ['innatural', 'triannual'], + 'inner': ['inner', 'renin'], + 'innerve': ['innerve', 'nervine', 'vernine'], + 'innest': ['innest', 'sennit', 'sinnet', 'tennis'], + 'innet': ['innet', 'tinne'], + 'innominata': ['antinomian', 'innominata'], + 'innovate': ['innovate', 'venation'], + 'innovationist': ['innovationist', 'nonvisitation'], + 'ino': ['ino', 'ion'], + 'inobtainable': ['inobtainable', 'nonbilabiate'], + 'inocarpus': ['inocarpus', 'unprosaic'], + 'inoculant': ['continual', 'inoculant', 'unctional'], + 'inocystoma': ['actomyosin', 'inocystoma'], + 'inodes': ['deinos', 'donsie', 'inodes', 'onside'], + 'inogen': ['genion', 'inogen'], + 'inoma': ['amino', 'inoma', 'naomi', 'omani', 'omina'], + 'inomyxoma': ['inomyxoma', 'myxoinoma'], + 'inone': ['inone', 'oenin'], + 'inoperculata': ['inoperculata', 'precautional'], + 'inorb': ['biron', 'inorb', 'robin'], + 'inorganic': ['conringia', 'inorganic'], + 'inorganical': ['carolingian', 'inorganical'], + 'inornate': ['anointer', 'inornate', 'nonirate', 'reanoint'], + 'inosic': ['inosic', 'sinico'], + 'inosinic': ['incision', 'inosinic'], + 'inosite': ['inosite', 'sionite'], + 'inphase': ['inphase', 'phineas'], + 'inpush': ['inpush', 'punish', 'unship'], + 'input': ['input', 'punti'], + 'inquiet': ['inquiet', 'quinite'], + 'inreality': ['inreality', 'linearity'], + 'inro': ['inro', 'iron', 'noir', 'nori'], + 'inroad': ['dorian', 'inroad', 'ordain'], + 'inroader': ['inroader', 'ordainer', 'reordain'], + 'inrub': ['bruin', 'burin', 'inrub'], + 'inrun': ['inrun', 'inurn'], + 'insane': ['insane', 'sienna'], + 'insatiably': ['insatiably', 'sanability'], + 'inscenation': ['incensation', 'inscenation'], + 'inscient': ['inscient', 'nicenist'], + 'insculp': ['insculp', 'sculpin'], + 'insea': ['anise', 'insea', 'siena', 'sinae'], + 'inseam': ['asimen', 'inseam', 'mesian'], + 'insect': ['encist', 'incest', 'insect', 'scient'], + 'insectan': ['insectan', 'instance'], + 'insectile': ['insectile', 'selenitic'], + 'insectivora': ['insectivora', 'visceration'], + 'insecure': ['insecure', 'sinecure'], + 'insee': ['insee', 'seine'], + 'inseer': ['inseer', 'nereis', 'seiner', 'serine', 'sirene'], + 'insert': ['estrin', 'insert', 'sinter', 'sterin', 'triens'], + 'inserted': ['indesert', 'inserted', 'resident'], + 'inserter': ['inserter', 'reinsert'], + 'insessor': ['insessor', 'rosiness'], + 'inset': ['inset', 'neist', 'snite', 'stein', 'stine', 'tsine'], + 'insetter': ['insetter', 'interest', 'interset', 'sternite'], + 'inshave': ['evanish', 'inshave'], + 'inshoot': ['inshoot', 'insooth'], + 'inside': ['indies', 'inside'], + 'insider': ['insider', 'siderin'], + 'insistent': ['insistent', 'tintiness'], + 'insister': ['insister', 'reinsist', 'sinister', 'sisterin'], + 'insole': ['insole', 'leonis', 'lesion', 'selion'], + 'insomnia': ['insomnia', 'simonian'], + 'insomniac': ['aniconism', 'insomniac'], + 'insooth': ['inshoot', 'insooth'], + 'insorb': ['insorb', 'sorbin'], + 'insoul': ['insoul', 'linous', 'nilous', 'unsoil'], + 'inspection': ['cispontine', 'inspection'], + 'inspiriter': ['inspiriter', 'reinspirit'], + 'inspissate': ['antisepsis', 'inspissate'], + 'inspreith': ['inspreith', 'nephritis', 'phrenitis'], + 'installer': ['installer', 'reinstall'], + 'instance': ['insectan', 'instance'], + 'instanter': ['instanter', 'transient'], + 'instar': ['instar', 'santir', 'strain'], + 'instate': ['atenist', 'instate', 'satient', 'steatin'], + 'instead': ['destain', 'instead', 'sainted', 'satined'], + 'insteam': ['atenism', 'inmeats', 'insteam', 'samnite'], + 'instep': ['instep', 'spinet'], + 'instiller': ['instiller', 'reinstill'], + 'instructer': ['instructer', 'intercrust', 'reinstruct'], + 'instructional': ['instructional', 'nonaltruistic'], + 'insula': ['insula', 'lanius', 'lusian'], + 'insulant': ['insulant', 'sultanin'], + 'insulse': ['insulse', 'silenus'], + 'insult': ['insult', 'sunlit', 'unlist', 'unslit'], + 'insulter': ['insulter', 'lustrine', 'reinsult'], + 'insunk': ['insunk', 'unskin'], + 'insurable': ['insurable', 'sublinear'], + 'insurance': ['insurance', 'nuisancer'], + 'insurant': ['insurant', 'unstrain'], + 'insure': ['insure', 'rusine', 'ursine'], + 'insurge': ['insurge', 'resuing'], + 'insurgent': ['insurgent', 'unresting'], + 'intactile': ['catlinite', 'intactile'], + 'intaglio': ['intaglio', 'ligation'], + 'intake': ['intake', 'kentia'], + 'intaker': ['intaker', 'katrine', 'keratin'], + 'intarsia': ['antiaris', 'intarsia'], + 'intarsiate': ['intarsiate', 'nestiatria'], + 'integral': ['integral', 'teraglin', 'triangle'], + 'integralize': ['gelatinizer', 'integralize'], + 'integrate': ['argentite', 'integrate'], + 'integrative': ['integrative', 'vertiginate', 'vinaigrette'], + 'integrious': ['grisounite', 'grisoutine', 'integrious'], + 'intemperable': ['impenetrable', 'intemperable'], + 'intemperably': ['impenetrably', 'intemperably'], + 'intemperate': ['impenetrate', 'intemperate'], + 'intemporal': ['intemporal', 'trampoline'], + 'intend': ['dentin', 'indent', 'intend', 'tinned'], + 'intended': ['indented', 'intended'], + 'intendedly': ['indentedly', 'intendedly'], + 'intender': ['indenter', 'intender', 'reintend'], + 'intendment': ['indentment', 'intendment'], + 'intense': ['intense', 'sennite'], + 'intent': ['intent', 'tinnet'], + 'intently': ['intently', 'nitently'], + 'inter': ['inert', 'inter', 'niter', 'retin', 'trine'], + 'interactional': ['interactional', 'intercalation'], + 'interagent': ['entreating', 'interagent'], + 'interally': ['interally', 'reliantly'], + 'interastral': ['interastral', 'intertarsal'], + 'intercalation': ['interactional', 'intercalation'], + 'intercale': ['intercale', 'interlace', 'lacertine', 'reclinate'], + 'intercede': ['intercede', 'tridecene'], + 'interceder': ['crednerite', 'interceder'], + 'intercession': ['intercession', 'recensionist'], + 'intercome': ['entomeric', 'intercome', 'morencite'], + 'interconal': ['interconal', 'nonrecital'], + 'intercrust': ['instructer', 'intercrust', 'reinstruct'], + 'interdome': ['interdome', 'mordenite', 'nemertoid'], + 'intereat': ['intereat', 'tinetare'], + 'interest': ['insetter', 'interest', 'interset', 'sternite'], + 'interester': ['interester', 'reinterest'], + 'interfering': ['interfering', 'interfinger'], + 'interfinger': ['interfering', 'interfinger'], + 'intergrade': ['gradienter', 'intergrade'], + 'interim': ['interim', 'termini'], + 'interimistic': ['interimistic', 'trimesitinic'], + 'interlace': ['intercale', 'interlace', 'lacertine', 'reclinate'], + 'interlaced': ['credential', 'interlaced', 'reclinated'], + 'interlaid': ['deliriant', 'draintile', 'interlaid'], + 'interlap': ['interlap', 'repliant', 'triplane'], + 'interlapse': ['alpestrine', 'episternal', 'interlapse', 'presential'], + 'interlay': ['interlay', 'lyterian'], + 'interleaf': ['interleaf', 'reinflate'], + 'interleaver': ['interleaver', 'reverential'], + 'interlocal': ['citronella', 'interlocal'], + 'interlope': ['interlope', 'interpole', 'repletion', 'terpineol'], + 'interlot': ['interlot', 'trotline'], + 'intermat': ['intermat', 'martinet', 'tetramin'], + 'intermatch': ['intermatch', 'thermantic'], + 'intermine': ['intermine', 'nemertini', 'terminine'], + 'intermorainic': ['intermorainic', 'recrimination'], + 'intermutual': ['intermutual', 'ultraminute'], + 'intern': ['intern', 'tinner'], + 'internality': ['internality', 'itinerantly'], + 'internecive': ['internecive', 'reincentive'], + 'internee': ['internee', 'retinene'], + 'interoceptor': ['interoceptor', 'reprotection'], + 'interpause': ['interpause', 'resupinate'], + 'interpave': ['interpave', 'prenative'], + 'interpeal': ['interpeal', 'interplea'], + 'interpellate': ['interpellate', 'pantellerite'], + 'interpellation': ['interpellation', 'interpollinate'], + 'interphone': ['interphone', 'pinnothere'], + 'interplay': ['interplay', 'painterly'], + 'interplea': ['interpeal', 'interplea'], + 'interplead': ['interplead', 'peridental'], + 'interpolar': ['interpolar', 'reniportal'], + 'interpolate': ['interpolate', 'triantelope'], + 'interpole': ['interlope', 'interpole', 'repletion', 'terpineol'], + 'interpollinate': ['interpellation', 'interpollinate'], + 'interpone': ['interpone', 'peritenon', 'pinnotere', 'preintone'], + 'interposal': ['interposal', 'psalterion'], + 'interposure': ['interposure', 'neuropteris'], + 'interpreter': ['interpreter', 'reinterpret'], + 'interproduce': ['interproduce', 'prereduction'], + 'interroom': ['interroom', 'remontoir'], + 'interrupter': ['interrupter', 'reinterrupt'], + 'intersale': ['intersale', 'larsenite'], + 'intersectional': ['intersectional', 'intraselection'], + 'interset': ['insetter', 'interest', 'interset', 'sternite'], + 'intershade': ['dishearten', 'intershade'], + 'intersituate': ['intersituate', 'tenuistriate'], + 'intersocial': ['intersocial', 'orleanistic', 'sclerotinia'], + 'interspace': ['esperantic', 'interspace'], + 'interspecific': ['interspecific', 'prescientific'], + 'interspiration': ['interspiration', 'repristination'], + 'intersporal': ['intersporal', 'tripersonal'], + 'interstation': ['interstation', 'strontianite'], + 'intertalk': ['intertalk', 'latterkin'], + 'intertarsal': ['interastral', 'intertarsal'], + 'interteam': ['antimeter', 'attermine', 'interteam', 'terminate', 'tetramine'], + 'intertie': ['intertie', 'retinite'], + 'intertone': ['intertone', 'retention'], + 'intervascular': ['intervascular', 'vernacularist'], + 'intervention': ['intervention', 'introvenient'], + 'interverbal': ['interverbal', 'invertebral'], + 'interviewer': ['interviewer', 'reinterview'], + 'interwed': ['interwed', 'wintered'], + 'interwish': ['interwish', 'winterish'], + 'interwork': ['interwork', 'tinworker'], + 'interwove': ['interwove', 'overtwine'], + 'intestate': ['enstatite', 'intestate', 'satinette'], + 'intestinovesical': ['intestinovesical', 'vesicointestinal'], + 'inthrong': ['inthrong', 'northing'], + 'intima': ['intima', 'timani'], + 'intimacy': ['imitancy', 'intimacy', 'minacity'], + 'intimater': ['intimater', 'traintime'], + 'into': ['into', 'nito', 'oint', 'tino'], + 'intoed': ['ditone', 'intoed'], + 'intolerance': ['crenelation', 'intolerance'], + 'intolerating': ['intolerating', 'nitrogelatin'], + 'intonate': ['intonate', 'totanine'], + 'intonator': ['intonator', 'tortonian'], + 'intone': ['intone', 'tenino'], + 'intonement': ['intonement', 'omnitenent'], + 'intoner': ['intoner', 'ternion'], + 'intort': ['intort', 'tornit', 'triton'], + 'intoxicate': ['excitation', 'intoxicate'], + 'intracoelomic': ['iconometrical', 'intracoelomic'], + 'intracosmic': ['intracosmic', 'narcoticism'], + 'intracostal': ['intracostal', 'stratonical'], + 'intractile': ['intractile', 'triclinate'], + 'intrada': ['intrada', 'radiant'], + 'intraselection': ['intersectional', 'intraselection'], + 'intraseptal': ['intraseptal', 'paternalist', 'prenatalist'], + 'intraspinal': ['intraspinal', 'pinnitarsal'], + 'intreat': ['intreat', 'iterant', 'nitrate', 'tertian'], + 'intrencher': ['intrencher', 'reintrench'], + 'intricate': ['intricate', 'triactine'], + 'intrication': ['citrination', 'intrication'], + 'intrigue': ['intrigue', 'tigurine'], + 'introconvertibility': ['incontrovertibility', 'introconvertibility'], + 'introconvertible': ['incontrovertible', 'introconvertible'], + 'introduce': ['introduce', 'reduction'], + 'introit': ['introit', 'nitriot'], + 'introitus': ['introitus', 'routinist'], + 'introvenient': ['intervention', 'introvenient'], + 'intrude': ['intrude', 'turdine', 'untired', 'untried'], + 'intruse': ['intruse', 'sturine'], + 'intrust': ['intrust', 'sturtin'], + 'intube': ['butein', 'butine', 'intube'], + 'intue': ['intue', 'unite', 'untie'], + 'inula': ['inula', 'luian', 'uinal'], + 'inurbane': ['eburnian', 'inurbane'], + 'inure': ['inure', 'urine'], + 'inured': ['diurne', 'inured', 'ruined', 'unride'], + 'inurn': ['inrun', 'inurn'], + 'inustion': ['inustion', 'unionist'], + 'invader': ['invader', 'ravined', 'viander'], + 'invaluable': ['invaluable', 'unvailable'], + 'invar': ['invar', 'ravin', 'vanir'], + 'invector': ['contrive', 'invector'], + 'inveigler': ['inveigler', 'relieving'], + 'inventer': ['inventer', 'reinvent', 'ventrine', 'vintener'], + 'inventress': ['inventress', 'vintneress'], + 'inverness': ['inverness', 'nerviness'], + 'inversatile': ['inversatile', 'serviential'], + 'inverse': ['inverse', 'versine'], + 'invert': ['invert', 'virent'], + 'invertase': ['invertase', 'servetian'], + 'invertebral': ['interverbal', 'invertebral'], + 'inverter': ['inverter', 'reinvert', 'trinerve'], + 'investigation': ['investigation', 'tenovaginitis'], + 'invinate': ['innative', 'invinate'], + 'inviter': ['inviter', 'vitrine'], + 'invocate': ['conative', 'invocate'], + 'invoker': ['invoker', 'overink'], + 'involucrate': ['countervail', 'involucrate'], + 'involucre': ['involucre', 'volucrine'], + 'inwards': ['inwards', 'sinward'], + 'inwith': ['inwith', 'within'], + 'iodate': ['idotea', 'iodate', 'otidae'], + 'iodhydrate': ['hydriodate', 'iodhydrate'], + 'iodhydric': ['hydriodic', 'iodhydric'], + 'iodinate': ['ideation', 'iodinate', 'taenioid'], + 'iodinium': ['iodinium', 'ionidium'], + 'iodism': ['idoism', 'iodism'], + 'iodite': ['iodite', 'teioid'], + 'iodo': ['iodo', 'ooid'], + 'iodocasein': ['iodocasein', 'oniscoidea'], + 'iodochloride': ['chloroiodide', 'iodochloride'], + 'iodohydric': ['hydroiodic', 'iodohydric'], + 'iodol': ['dooli', 'iodol'], + 'iodothyrin': ['iodothyrin', 'thyroiodin'], + 'iodous': ['iodous', 'odious'], + 'ion': ['ino', 'ion'], + 'ionidium': ['iodinium', 'ionidium'], + 'ionizer': ['ionizer', 'ironize'], + 'iota': ['iota', 'tiao'], + 'iotacist': ['iotacist', 'taoistic'], + 'ipecac': ['icecap', 'ipecac'], + 'ipil': ['ipil', 'pili'], + 'ipseand': ['ipseand', 'panside', 'pansied'], + 'ira': ['air', 'ira', 'ria'], + 'iracund': ['candiru', 'iracund'], + 'irade': ['aider', 'deair', 'irade', 'redia'], + 'iran': ['arni', 'iran', 'nair', 'rain', 'rani'], + 'irani': ['irani', 'irian'], + 'iranism': ['iranism', 'sirmian'], + 'iranist': ['iranist', 'istrian'], + 'irascent': ['canister', 'cestrian', 'cisterna', 'irascent'], + 'irate': ['arite', 'artie', 'irate', 'retia', 'tarie'], + 'irately': ['irately', 'reality'], + 'ire': ['ire', 'rie'], + 'irena': ['erian', 'irena', 'reina'], + 'irene': ['ernie', 'ierne', 'irene'], + 'irenic': ['irenic', 'ricine'], + 'irenics': ['irenics', 'resinic', 'sericin', 'sirenic'], + 'irenicum': ['irenicum', 'muricine'], + 'iresine': ['iresine', 'iserine'], + 'irfan': ['infra', 'irfan'], + 'irgun': ['irgun', 'ruing', 'unrig'], + 'irian': ['irani', 'irian'], + 'iridal': ['iridal', 'lariid'], + 'iridate': ['arietid', 'iridate'], + 'iridectomy': ['iridectomy', 'mediocrity'], + 'irides': ['irides', 'irised'], + 'iridescent': ['indiscreet', 'indiscrete', 'iridescent'], + 'iridescently': ['indiscreetly', 'indiscretely', 'iridescently'], + 'iridosmium': ['iridosmium', 'osmiridium'], + 'irised': ['irides', 'irised'], + 'irish': ['irish', 'rishi', 'sirih'], + 'irk': ['irk', 'rik'], + 'irma': ['amir', 'irma', 'mari', 'mira', 'rami', 'rima'], + 'iroha': ['haori', 'iroha'], + 'irok': ['irok', 'kori'], + 'iron': ['inro', 'iron', 'noir', 'nori'], + 'ironclad': ['ironclad', 'rolandic'], + 'irone': ['irone', 'norie'], + 'ironhead': ['herodian', 'ironhead'], + 'ironice': ['ironice', 'oneiric'], + 'ironize': ['ionizer', 'ironize'], + 'ironshod': ['dishonor', 'ironshod'], + 'ironside': ['derision', 'ironside', 'resinoid', 'sirenoid'], + 'irradiant': ['irradiant', 'triandria'], + 'irrationable': ['irrationable', 'orbitelarian'], + 'irredenta': ['irredenta', 'retainder'], + 'irrelate': ['irrelate', 'retailer'], + 'irrepentance': ['irrepentance', 'pretercanine'], + 'irving': ['irving', 'riving', 'virgin'], + 'irvingiana': ['irvingiana', 'viraginian'], + 'is': ['is', 'si'], + 'isabel': ['isabel', 'lesbia'], + 'isabella': ['isabella', 'sailable'], + 'isagogical': ['isagogical', 'sialagogic'], + 'isagon': ['gosain', 'isagon', 'sagoin'], + 'isander': ['andries', 'isander', 'sardine'], + 'isanthous': ['anhistous', 'isanthous'], + 'isatate': ['isatate', 'satiate', 'taetsia'], + 'isatic': ['isatic', 'saitic'], + 'isatin': ['antisi', 'isatin'], + 'isatinic': ['isatinic', 'sinaitic'], + 'isaurian': ['anisuria', 'isaurian'], + 'isawa': ['isawa', 'waasi'], + 'isba': ['absi', 'bais', 'bias', 'isba'], + 'iscariot': ['aoristic', 'iscariot'], + 'ischemia': ['hemiasci', 'ischemia'], + 'ischioiliac': ['ilioischiac', 'ischioiliac'], + 'ischiorectal': ['ischiorectal', 'sciotherical'], + 'iserine': ['iresine', 'iserine'], + 'iseum': ['iseum', 'musie'], + 'isiac': ['ascii', 'isiac'], + 'isidore': ['isidore', 'osiride'], + 'isis': ['isis', 'sisi'], + 'islam': ['islam', 'ismal', 'simal'], + 'islamic': ['islamic', 'laicism', 'silicam'], + 'islamitic': ['islamitic', 'italicism'], + 'islandy': ['islandy', 'lindsay'], + 'islay': ['islay', 'saily'], + 'isle': ['isle', 'lise', 'sile'], + 'islet': ['islet', 'istle', 'slite', 'stile'], + 'isleta': ['isleta', 'litsea', 'salite', 'stelai'], + 'isleted': ['idleset', 'isleted'], + 'ism': ['ism', 'sim'], + 'ismal': ['islam', 'ismal', 'simal'], + 'ismatic': ['ismatic', 'itacism'], + 'ismatical': ['ismatical', 'lamaistic'], + 'isocamphor': ['chromopsia', 'isocamphor'], + 'isoclinal': ['collinsia', 'isoclinal'], + 'isocline': ['isocline', 'silicone'], + 'isocoumarin': ['acrimonious', 'isocoumarin'], + 'isodulcite': ['isodulcite', 'solicitude'], + 'isogen': ['geison', 'isogen'], + 'isogeotherm': ['geoisotherm', 'isogeotherm'], + 'isogon': ['isogon', 'songoi'], + 'isogram': ['isogram', 'orgiasm'], + 'isohel': ['helios', 'isohel'], + 'isoheptane': ['apothesine', 'isoheptane'], + 'isolate': ['aeolist', 'isolate'], + 'isolated': ['diastole', 'isolated', 'sodalite', 'solidate'], + 'isolative': ['isolative', 'soliative'], + 'isolde': ['isolde', 'soiled'], + 'isomer': ['isomer', 'rimose'], + 'isometric': ['eroticism', 'isometric', 'meroistic', 'trioecism'], + 'isomorph': ['isomorph', 'moorship'], + 'isonitrile': ['isonitrile', 'resilition'], + 'isonym': ['isonym', 'myosin', 'simony'], + 'isophthalyl': ['isophthalyl', 'lithophysal'], + 'isopodan': ['anisopod', 'isopodan'], + 'isoptera': ['isoptera', 'septoria'], + 'isosaccharic': ['isosaccharic', 'sacroischiac'], + 'isostere': ['erotesis', 'isostere'], + 'isotac': ['isotac', 'scotia'], + 'isotheral': ['horsetail', 'isotheral'], + 'isotherm': ['homerist', 'isotherm', 'otherism', 'theorism'], + 'isotria': ['isotria', 'oaritis'], + 'isotron': ['isotron', 'torsion'], + 'isotrope': ['isotrope', 'portoise'], + 'isotropism': ['isotropism', 'promitosis'], + 'isotropy': ['isotropy', 'porosity'], + 'israel': ['israel', 'relais', 'resail', 'sailer', 'serail', 'serial'], + 'israeli': ['alisier', 'israeli'], + 'israelite': ['israelite', 'resiliate'], + 'issuable': ['basileus', 'issuable', 'suasible'], + 'issuant': ['issuant', 'sustain'], + 'issue': ['issue', 'susie'], + 'issuer': ['issuer', 'uresis'], + 'ist': ['ist', 'its', 'sit'], + 'isthmi': ['isthmi', 'timish'], + 'isthmian': ['isthmian', 'smithian'], + 'isthmoid': ['isthmoid', 'thomisid'], + 'istle': ['islet', 'istle', 'slite', 'stile'], + 'istrian': ['iranist', 'istrian'], + 'isuret': ['isuret', 'resuit'], + 'it': ['it', 'ti'], + 'ita': ['ait', 'ati', 'ita', 'tai'], + 'itacism': ['ismatic', 'itacism'], + 'itaconate': ['acetation', 'itaconate'], + 'itaconic': ['aconitic', 'cationic', 'itaconic'], + 'itali': ['itali', 'tilia'], + 'italian': ['antilia', 'italian'], + 'italic': ['clitia', 'italic'], + 'italicism': ['islamitic', 'italicism'], + 'italite': ['italite', 'letitia', 'tilaite'], + 'italon': ['italon', 'lation', 'talion'], + 'itaves': ['itaves', 'stevia'], + 'itch': ['chit', 'itch', 'tchi'], + 'item': ['emit', 'item', 'mite', 'time'], + 'iten': ['iten', 'neti', 'tien', 'tine'], + 'itenean': ['aniente', 'itenean'], + 'iter': ['iter', 'reit', 'rite', 'teri', 'tier', 'tire'], + 'iterable': ['iterable', 'liberate'], + 'iterance': ['aneretic', 'centiare', 'creatine', 'increate', 'iterance'], + 'iterant': ['intreat', 'iterant', 'nitrate', 'tertian'], + 'ithaca': ['cahita', 'ithaca'], + 'ithacan': ['ithacan', 'tachina'], + 'ither': ['ither', 'their'], + 'itinerant': ['itinerant', 'nitratine'], + 'itinerantly': ['internality', 'itinerantly'], + 'itmo': ['itmo', 'moit', 'omit', 'timo'], + 'ito': ['ito', 'toi'], + 'itoism': ['itoism', 'omitis'], + 'itoist': ['itoist', 'otitis'], + 'itoland': ['itoland', 'talonid', 'tindalo'], + 'itonama': ['amniota', 'itonama'], + 'itonia': ['aition', 'itonia'], + 'its': ['ist', 'its', 'sit'], + 'itself': ['itself', 'stifle'], + 'ituraean': ['inaurate', 'ituraean'], + 'itza': ['itza', 'tiza', 'zati'], + 'iva': ['iva', 'vai', 'via'], + 'ivan': ['ivan', 'vain', 'vina'], + 'ivorist': ['ivorist', 'visitor'], + 'iwaiwa': ['iwaiwa', 'waiwai'], + 'ixiama': ['amixia', 'ixiama'], + 'ixodic': ['ixodic', 'oxidic'], + 'iyo': ['iyo', 'yoi'], + 'izar': ['izar', 'zira'], + 'jacami': ['jacami', 'jicama'], + 'jacobian': ['bajocian', 'jacobian'], + 'jag': ['gaj', 'jag'], + 'jagir': ['jagir', 'jirga'], + 'jagua': ['ajuga', 'jagua'], + 'jail': ['jail', 'lija'], + 'jailer': ['jailer', 'rejail'], + 'jaime': ['jaime', 'jamie'], + 'jain': ['jain', 'jina'], + 'jaina': ['inaja', 'jaina'], + 'jalouse': ['jalouse', 'jealous'], + 'jama': ['jama', 'maja'], + 'jamesian': ['jamesian', 'jamesina'], + 'jamesina': ['jamesian', 'jamesina'], + 'jami': ['ijma', 'jami'], + 'jamie': ['jaime', 'jamie'], + 'jane': ['jane', 'jean'], + 'janos': ['janos', 'jason', 'jonas', 'sonja'], + 'jantu': ['jantu', 'jaunt', 'junta'], + 'januslike': ['januslike', 'seljukian'], + 'japonism': ['japonism', 'pajonism'], + 'jar': ['jar', 'raj'], + 'jara': ['ajar', 'jara', 'raja'], + 'jarmo': ['jarmo', 'major'], + 'jarnut': ['jarnut', 'jurant'], + 'jason': ['janos', 'jason', 'jonas', 'sonja'], + 'jat': ['jat', 'taj'], + 'jatki': ['jatki', 'tajik'], + 'jato': ['jato', 'jota'], + 'jaun': ['jaun', 'juan'], + 'jaunt': ['jantu', 'jaunt', 'junta'], + 'jaup': ['jaup', 'puja'], + 'jealous': ['jalouse', 'jealous'], + 'jean': ['jane', 'jean'], + 'jebusitical': ['jebusitical', 'justiciable'], + 'jecoral': ['cajoler', 'jecoral'], + 'jeffery': ['jeffery', 'jeffrey'], + 'jeffrey': ['jeffery', 'jeffrey'], + 'jejunoduodenal': ['duodenojejunal', 'jejunoduodenal'], + 'jenine': ['jenine', 'jennie'], + 'jennie': ['jenine', 'jennie'], + 'jerker': ['jerker', 'rejerk'], + 'jerkin': ['jerkin', 'jinker'], + 'jeziah': ['hejazi', 'jeziah'], + 'jicama': ['jacami', 'jicama'], + 'jihad': ['hadji', 'jihad'], + 'jina': ['jain', 'jina'], + 'jingoist': ['jingoist', 'joisting'], + 'jinker': ['jerkin', 'jinker'], + 'jirga': ['jagir', 'jirga'], + 'jobo': ['bojo', 'jobo'], + 'johan': ['johan', 'jonah'], + 'join': ['join', 'joni'], + 'joinant': ['joinant', 'jotnian'], + 'joiner': ['joiner', 'rejoin'], + 'jointless': ['jointless', 'joltiness'], + 'joisting': ['jingoist', 'joisting'], + 'jolter': ['jolter', 'rejolt'], + 'joltiness': ['jointless', 'joltiness'], + 'jonah': ['johan', 'jonah'], + 'jonas': ['janos', 'jason', 'jonas', 'sonja'], + 'joni': ['join', 'joni'], + 'joom': ['joom', 'mojo'], + 'joshi': ['joshi', 'shoji'], + 'jota': ['jato', 'jota'], + 'jotnian': ['joinant', 'jotnian'], + 'journeyer': ['journeyer', 'rejourney'], + 'joust': ['joust', 'justo'], + 'juan': ['jaun', 'juan'], + 'judaic': ['judaic', 'judica'], + 'judica': ['judaic', 'judica'], + 'jujitsu': ['jujitsu', 'jujuist'], + 'jujuist': ['jujitsu', 'jujuist'], + 'junta': ['jantu', 'jaunt', 'junta'], + 'jurant': ['jarnut', 'jurant'], + 'justiciable': ['jebusitical', 'justiciable'], + 'justo': ['joust', 'justo'], + 'jute': ['jute', 'teju'], + 'ka': ['ak', 'ka'], + 'kabel': ['blake', 'bleak', 'kabel'], + 'kaberu': ['kaberu', 'kubera'], + 'kabuli': ['kabuli', 'kiluba'], + 'kabyle': ['bleaky', 'kabyle'], + 'kachari': ['chakari', 'chikara', 'kachari'], + 'kachin': ['hackin', 'kachin'], + 'kafir': ['fakir', 'fraik', 'kafir', 'rafik'], + 'kaha': ['akha', 'kaha'], + 'kahar': ['harka', 'kahar'], + 'kahu': ['haku', 'kahu'], + 'kaid': ['dika', 'kaid'], + 'kaik': ['kaik', 'kaki'], + 'kail': ['ilka', 'kail', 'kali'], + 'kainga': ['kainga', 'kanagi'], + 'kaiwi': ['kaiwi', 'kiwai'], + 'kaka': ['akka', 'kaka'], + 'kaki': ['kaik', 'kaki'], + 'kala': ['akal', 'kala'], + 'kalamian': ['kalamian', 'malikana'], + 'kaldani': ['danakil', 'dankali', 'kaldani', 'ladakin'], + 'kale': ['kale', 'lake', 'leak'], + 'kali': ['ilka', 'kail', 'kali'], + 'kalo': ['kalo', 'kola', 'loka'], + 'kamansi': ['kamansi', 'kamasin'], + 'kamares': ['kamares', 'seamark'], + 'kamasin': ['kamansi', 'kamasin'], + 'kame': ['kame', 'make', 'meak'], + 'kamel': ['kamel', 'kemal'], + 'kamiya': ['kamiya', 'yakima'], + 'kan': ['kan', 'nak'], + 'kana': ['akan', 'kana'], + 'kanagi': ['kainga', 'kanagi'], + 'kanap': ['kanap', 'panak'], + 'kanat': ['kanat', 'tanak', 'tanka'], + 'kande': ['kande', 'knead', 'naked'], + 'kang': ['kang', 'knag'], + 'kanga': ['angka', 'kanga'], + 'kangani': ['kangani', 'kiangan'], + 'kangli': ['kangli', 'laking'], + 'kanred': ['darken', 'kanred', 'ranked'], + 'kans': ['kans', 'sank'], + 'kaolin': ['ankoli', 'kaolin'], + 'karch': ['chark', 'karch'], + 'karel': ['karel', 'laker'], + 'karen': ['anker', 'karen', 'naker'], + 'kari': ['ikra', 'kari', 'raki'], + 'karite': ['arkite', 'karite'], + 'karl': ['karl', 'kral', 'lark'], + 'karling': ['karling', 'larking'], + 'karma': ['karma', 'krama', 'marka'], + 'karo': ['karo', 'kora', 'okra', 'roka'], + 'karree': ['karree', 'rerake'], + 'karst': ['karst', 'skart', 'stark'], + 'karstenite': ['karstenite', 'kersantite'], + 'kartel': ['kartel', 'retalk', 'talker'], + 'kasa': ['asak', 'kasa', 'saka'], + 'kasbah': ['abkhas', 'kasbah'], + 'kasha': ['kasha', 'khasa', 'sakha', 'shaka'], + 'kashan': ['kashan', 'sankha'], + 'kasher': ['kasher', 'shaker'], + 'kashi': ['kashi', 'khasi'], + 'kasm': ['kasm', 'mask'], + 'katar': ['katar', 'takar'], + 'kate': ['kate', 'keta', 'take', 'teak'], + 'kath': ['kath', 'khat'], + 'katharsis': ['katharsis', 'shastraik'], + 'katie': ['katie', 'keita'], + 'katik': ['katik', 'tikka'], + 'katrine': ['intaker', 'katrine', 'keratin'], + 'katy': ['katy', 'kyat', 'taky'], + 'kavass': ['kavass', 'vakass'], + 'kavi': ['kavi', 'kiva'], + 'kay': ['kay', 'yak'], + 'kayak': ['kayak', 'yakka'], + 'kayan': ['kayan', 'yakan'], + 'kayo': ['kayo', 'oaky'], + 'kea': ['ake', 'kea'], + 'keach': ['cheka', 'keach'], + 'keawe': ['aweek', 'keawe'], + 'kechel': ['heckle', 'kechel'], + 'kedar': ['daker', 'drake', 'kedar', 'radek'], + 'kee': ['eke', 'kee'], + 'keech': ['cheek', 'cheke', 'keech'], + 'keel': ['keel', 'kele', 'leek'], + 'keen': ['keen', 'knee'], + 'keena': ['aknee', 'ankee', 'keena'], + 'keep': ['keep', 'peek'], + 'keepership': ['keepership', 'shipkeeper'], + 'kees': ['kees', 'seek', 'skee'], + 'keest': ['keest', 'skeet', 'skete', 'steek'], + 'kefir': ['frike', 'kefir'], + 'keid': ['dike', 'keid'], + 'keita': ['katie', 'keita'], + 'keith': ['keith', 'kithe'], + 'keitloa': ['keitloa', 'oatlike'], + 'kelchin': ['chinkle', 'kelchin'], + 'kele': ['keel', 'kele', 'leek'], + 'kelima': ['kelima', 'mikael'], + 'kelpie': ['kelpie', 'pelike'], + 'kelty': ['kelty', 'ketyl'], + 'kemal': ['kamel', 'kemal'], + 'kemalist': ['kemalist', 'mastlike'], + 'kenareh': ['hearken', 'kenareh'], + 'kennel': ['kennel', 'nelken'], + 'kenotic': ['kenotic', 'ketonic'], + 'kent': ['kent', 'knet'], + 'kentia': ['intake', 'kentia'], + 'kenton': ['kenton', 'nekton'], + 'kepi': ['kepi', 'kipe', 'pike'], + 'keralite': ['keralite', 'tearlike'], + 'kerasin': ['kerasin', 'sarkine'], + 'kerat': ['kerat', 'taker'], + 'keratin': ['intaker', 'katrine', 'keratin'], + 'keratoangioma': ['angiokeratoma', 'keratoangioma'], + 'keratosis': ['asterikos', 'keratosis'], + 'keres': ['esker', 'keres', 'reesk', 'seker', 'skeer', 'skere'], + 'keresan': ['keresan', 'sneaker'], + 'kerewa': ['kerewa', 'rewake'], + 'kerf': ['ferk', 'kerf'], + 'kern': ['kern', 'renk'], + 'kersantite': ['karstenite', 'kersantite'], + 'kersey': ['kersey', 'skeery'], + 'kestrel': ['kestrel', 'skelter'], + 'keta': ['kate', 'keta', 'take', 'teak'], + 'ketene': ['ektene', 'ketene'], + 'keto': ['keto', 'oket', 'toke'], + 'ketol': ['ketol', 'loket'], + 'ketonic': ['kenotic', 'ketonic'], + 'ketu': ['ketu', 'teuk', 'tuke'], + 'ketupa': ['ketupa', 'uptake'], + 'ketyl': ['kelty', 'ketyl'], + 'keup': ['keup', 'puke'], + 'keuper': ['keuper', 'peruke'], + 'kevan': ['kevan', 'knave'], + 'kha': ['hak', 'kha'], + 'khami': ['hakim', 'khami'], + 'khan': ['ankh', 'hank', 'khan'], + 'khar': ['hark', 'khar', 'rakh'], + 'khasa': ['kasha', 'khasa', 'sakha', 'shaka'], + 'khasi': ['kashi', 'khasi'], + 'khat': ['kath', 'khat'], + 'khatib': ['bhakti', 'khatib'], + 'khila': ['khila', 'kilah'], + 'khu': ['huk', 'khu'], + 'khula': ['khula', 'kulah'], + 'kiangan': ['kangani', 'kiangan'], + 'kibe': ['bike', 'kibe'], + 'kicker': ['kicker', 'rekick'], + 'kickout': ['kickout', 'outkick'], + 'kidney': ['dinkey', 'kidney'], + 'kids': ['disk', 'kids', 'skid'], + 'kiel': ['kiel', 'like'], + 'kier': ['erik', 'kier', 'reki'], + 'kiku': ['kiku', 'kuki'], + 'kikumon': ['kikumon', 'kokumin'], + 'kil': ['ilk', 'kil'], + 'kilah': ['khila', 'kilah'], + 'kiliare': ['airlike', 'kiliare'], + 'killcalf': ['calfkill', 'killcalf'], + 'killer': ['killer', 'rekill'], + 'kiln': ['kiln', 'link'], + 'kilnman': ['kilnman', 'linkman'], + 'kilo': ['kilo', 'koil', 'koli'], + 'kilp': ['kilp', 'klip'], + 'kilter': ['kilter', 'kirtle'], + 'kilting': ['kilting', 'kitling'], + 'kiluba': ['kabuli', 'kiluba'], + 'kimberlite': ['kimberlite', 'timberlike'], + 'kimnel': ['kimnel', 'milken'], + 'kin': ['ink', 'kin'], + 'kina': ['akin', 'kina', 'naik'], + 'kinase': ['kinase', 'sekani'], + 'kinch': ['chink', 'kinch'], + 'kind': ['dink', 'kind'], + 'kindle': ['kindle', 'linked'], + 'kinetomer': ['kinetomer', 'konimeter'], + 'king': ['gink', 'king'], + 'kingcob': ['bocking', 'kingcob'], + 'kingpin': ['kingpin', 'pinking'], + 'kingrow': ['kingrow', 'working'], + 'kinless': ['inkless', 'kinless'], + 'kinship': ['kinship', 'pinkish'], + 'kioko': ['kioko', 'kokio'], + 'kip': ['kip', 'pik'], + 'kipe': ['kepi', 'kipe', 'pike'], + 'kirk': ['kirk', 'rikk'], + 'kirktown': ['kirktown', 'knitwork'], + 'kirn': ['kirn', 'rink'], + 'kirsten': ['kirsten', 'kristen', 'stinker'], + 'kirsty': ['kirsty', 'skirty'], + 'kirtle': ['kilter', 'kirtle'], + 'kirve': ['kirve', 'kiver'], + 'kish': ['kish', 'shik', 'sikh'], + 'kishen': ['kishen', 'neskhi'], + 'kisra': ['kisra', 'sikar', 'skair'], + 'kissar': ['kissar', 'krasis'], + 'kisser': ['kisser', 'rekiss'], + 'kist': ['kist', 'skit'], + 'kistful': ['kistful', 'lutfisk'], + 'kitab': ['batik', 'kitab'], + 'kitan': ['kitan', 'takin'], + 'kitar': ['kitar', 'krait', 'rakit', 'traik'], + 'kitchen': ['kitchen', 'thicken'], + 'kitchener': ['kitchener', 'rethicken', 'thickener'], + 'kithe': ['keith', 'kithe'], + 'kitling': ['kilting', 'kitling'], + 'kitlope': ['kitlope', 'potlike', 'toplike'], + 'kittel': ['kittel', 'kittle'], + 'kittle': ['kittel', 'kittle'], + 'kittles': ['kittles', 'skittle'], + 'kiva': ['kavi', 'kiva'], + 'kiver': ['kirve', 'kiver'], + 'kiwai': ['kaiwi', 'kiwai'], + 'klan': ['klan', 'lank'], + 'klanism': ['klanism', 'silkman'], + 'klaus': ['klaus', 'lukas', 'sulka'], + 'kleistian': ['kleistian', 'saintlike', 'satinlike'], + 'klendusic': ['klendusic', 'unsickled'], + 'kling': ['glink', 'kling'], + 'klip': ['kilp', 'klip'], + 'klop': ['klop', 'polk'], + 'knab': ['bank', 'knab', 'nabk'], + 'knag': ['kang', 'knag'], + 'knap': ['knap', 'pank'], + 'knape': ['knape', 'pekan'], + 'knar': ['knar', 'kran', 'nark', 'rank'], + 'knave': ['kevan', 'knave'], + 'knawel': ['knawel', 'wankle'], + 'knead': ['kande', 'knead', 'naked'], + 'knee': ['keen', 'knee'], + 'knet': ['kent', 'knet'], + 'knit': ['knit', 'tink'], + 'knitter': ['knitter', 'trinket'], + 'knitwork': ['kirktown', 'knitwork'], + 'knob': ['bonk', 'knob'], + 'knot': ['knot', 'tonk'], + 'knottiness': ['knottiness', 'stinkstone'], + 'knower': ['knower', 'reknow', 'wroken'], + 'knub': ['bunk', 'knub'], + 'knurly': ['knurly', 'runkly'], + 'knut': ['knut', 'tunk'], + 'knute': ['knute', 'unket'], + 'ko': ['ko', 'ok'], + 'koa': ['ako', 'koa', 'oak', 'oka'], + 'koali': ['koali', 'koila'], + 'kobu': ['bouk', 'kobu'], + 'koch': ['hock', 'koch'], + 'kochia': ['choiak', 'kochia'], + 'koel': ['koel', 'loke'], + 'koi': ['koi', 'oki'], + 'koil': ['kilo', 'koil', 'koli'], + 'koila': ['koali', 'koila'], + 'koilon': ['inlook', 'koilon'], + 'kokan': ['kokan', 'konak'], + 'kokio': ['kioko', 'kokio'], + 'kokumin': ['kikumon', 'kokumin'], + 'kola': ['kalo', 'kola', 'loka'], + 'koli': ['kilo', 'koil', 'koli'], + 'kolo': ['kolo', 'look'], + 'kome': ['kome', 'moke'], + 'komi': ['komi', 'moki'], + 'kona': ['kona', 'nako'], + 'konak': ['kokan', 'konak'], + 'kongo': ['kongo', 'ngoko'], + 'kongoni': ['kongoni', 'nooking'], + 'konia': ['ikona', 'konia'], + 'konimeter': ['kinetomer', 'konimeter'], + 'kor': ['kor', 'rok'], + 'kora': ['karo', 'kora', 'okra', 'roka'], + 'korait': ['korait', 'troika'], + 'koran': ['koran', 'krona'], + 'korana': ['anorak', 'korana'], + 'kore': ['kore', 'roke'], + 'korec': ['coker', 'corke', 'korec'], + 'korero': ['korero', 'rooker'], + 'kori': ['irok', 'kori'], + 'korimako': ['korimako', 'koromika'], + 'koromika': ['korimako', 'koromika'], + 'korwa': ['awork', 'korwa'], + 'kory': ['kory', 'roky', 'york'], + 'kos': ['kos', 'sok'], + 'koso': ['koso', 'skoo', 'sook'], + 'kotar': ['kotar', 'tarok'], + 'koto': ['koto', 'toko', 'took'], + 'kra': ['ark', 'kra'], + 'krait': ['kitar', 'krait', 'rakit', 'traik'], + 'kraken': ['kraken', 'nekkar'], + 'kral': ['karl', 'kral', 'lark'], + 'krama': ['karma', 'krama', 'marka'], + 'kran': ['knar', 'kran', 'nark', 'rank'], + 'kras': ['askr', 'kras', 'sark'], + 'krasis': ['kissar', 'krasis'], + 'kraut': ['kraut', 'tukra'], + 'kreis': ['kreis', 'skier'], + 'kreistle': ['kreistle', 'triskele'], + 'krepi': ['krepi', 'piker'], + 'krina': ['inkra', 'krina', 'nakir', 'rinka'], + 'kris': ['kris', 'risk'], + 'krishna': ['krishna', 'rankish'], + 'kristen': ['kirsten', 'kristen', 'stinker'], + 'krona': ['koran', 'krona'], + 'krone': ['ekron', 'krone'], + 'kroo': ['kroo', 'rook'], + 'krosa': ['krosa', 'oskar'], + 'kua': ['aku', 'auk', 'kua'], + 'kuar': ['kuar', 'raku', 'rauk'], + 'kuba': ['baku', 'kuba'], + 'kubera': ['kaberu', 'kubera'], + 'kuki': ['kiku', 'kuki'], + 'kulah': ['khula', 'kulah'], + 'kulimit': ['kulimit', 'tilikum'], + 'kulm': ['kulm', 'mulk'], + 'kuman': ['kuman', 'naumk'], + 'kumhar': ['kumhar', 'kumrah'], + 'kumrah': ['kumhar', 'kumrah'], + 'kunai': ['kunai', 'nikau'], + 'kuneste': ['kuneste', 'netsuke'], + 'kung': ['gunk', 'kung'], + 'kurmi': ['kurmi', 'mukri'], + 'kurt': ['kurt', 'turk'], + 'kurus': ['kurus', 'ursuk'], + 'kusa': ['kusa', 'skua'], + 'kusam': ['kusam', 'sumak'], + 'kusan': ['ankus', 'kusan'], + 'kusha': ['kusha', 'shaku', 'ushak'], + 'kutchin': ['kutchin', 'unthick'], + 'kutenai': ['kutenai', 'unakite'], + 'kyar': ['kyar', 'yark'], + 'kyat': ['katy', 'kyat', 'taky'], + 'kyle': ['kyle', 'yelk'], + 'kylo': ['kylo', 'yolk'], + 'kyte': ['kyte', 'tyke'], + 'la': ['al', 'la'], + 'laager': ['aglare', 'alegar', 'galera', 'laager'], + 'laang': ['laang', 'lagan', 'lagna'], + 'lab': ['alb', 'bal', 'lab'], + 'laban': ['alban', 'balan', 'banal', 'laban', 'nabal', 'nabla'], + 'labber': ['barbel', 'labber', 'rabble'], + 'labefact': ['factable', 'labefact'], + 'label': ['bella', 'label'], + 'labeler': ['labeler', 'relabel'], + 'labia': ['balai', 'labia'], + 'labial': ['abilla', 'labial'], + 'labially': ['alliably', 'labially'], + 'labiate': ['baalite', 'bialate', 'labiate'], + 'labiella': ['alliable', 'labiella'], + 'labile': ['alible', 'belial', 'labile', 'liable'], + 'labiocervical': ['cervicolabial', 'labiocervical'], + 'labiodental': ['dentolabial', 'labiodental'], + 'labioglossal': ['glossolabial', 'labioglossal'], + 'labioglossolaryngeal': ['glossolabiolaryngeal', 'labioglossolaryngeal'], + 'labioglossopharyngeal': ['glossolabiopharyngeal', 'labioglossopharyngeal'], + 'labiomental': ['labiomental', 'mentolabial'], + 'labionasal': ['labionasal', 'nasolabial'], + 'labiovelar': ['bialveolar', 'labiovelar'], + 'labis': ['basil', 'labis'], + 'labor': ['balor', 'bolar', 'boral', 'labor', 'lobar'], + 'laborant': ['balatron', 'laborant'], + 'laborism': ['laborism', 'mislabor'], + 'laborist': ['laborist', 'strobila'], + 'laborite': ['betailor', 'laborite', 'orbitale'], + 'labrador': ['labrador', 'larboard'], + 'labret': ['albert', 'balter', 'labret', 'tabler'], + 'labridae': ['labridae', 'radiable'], + 'labrose': ['borlase', 'labrose', 'rosabel'], + 'labrum': ['brumal', 'labrum', 'lumbar', 'umbral'], + 'labrus': ['bursal', 'labrus'], + 'laburnum': ['alburnum', 'laburnum'], + 'lac': ['cal', 'lac'], + 'lace': ['acle', 'alec', 'lace'], + 'laced': ['clead', 'decal', 'laced'], + 'laceman': ['laceman', 'manacle'], + 'lacepod': ['lacepod', 'pedocal', 'placode'], + 'lacer': ['ceral', 'clare', 'clear', 'lacer'], + 'lacerable': ['clearable', 'lacerable'], + 'lacerate': ['lacerate', 'lacertae'], + 'laceration': ['creational', 'crotalinae', 'laceration', 'reactional'], + 'lacerative': ['calaverite', 'lacerative'], + 'lacertae': ['lacerate', 'lacertae'], + 'lacertian': ['carnalite', 'claretian', 'lacertian', 'nectarial'], + 'lacertid': ['articled', 'lacertid'], + 'lacertidae': ['dilacerate', 'lacertidae'], + 'lacertiloid': ['illoricated', 'lacertiloid'], + 'lacertine': ['intercale', 'interlace', 'lacertine', 'reclinate'], + 'lacertoid': ['dialector', 'lacertoid'], + 'lacery': ['clayer', 'lacery'], + 'lacet': ['cleat', 'eclat', 'ectal', 'lacet', 'tecla'], + 'lache': ['chela', 'lache', 'leach'], + 'laches': ['cashel', 'laches', 'sealch'], + 'lachrymonasal': ['lachrymonasal', 'nasolachrymal'], + 'lachsa': ['calash', 'lachsa'], + 'laciness': ['laciness', 'sensical'], + 'lacing': ['anglic', 'lacing'], + 'lacinia': ['lacinia', 'licania'], + 'laciniated': ['acetanilid', 'laciniated', 'teniacidal'], + 'lacis': ['lacis', 'salic'], + 'lack': ['calk', 'lack'], + 'lacker': ['calker', 'lacker', 'rackle', 'recalk', 'reckla'], + 'lacmoid': ['domical', 'lacmoid'], + 'laconic': ['conical', 'laconic'], + 'laconica': ['canicola', 'laconica'], + 'laconizer': ['laconizer', 'locarnize'], + 'lacquer': ['claquer', 'lacquer'], + 'lacquerer': ['lacquerer', 'relacquer'], + 'lactarene': ['lactarene', 'nectareal'], + 'lactarious': ['alacritous', 'lactarious', 'lactosuria'], + 'lactarium': ['lactarium', 'matricula'], + 'lactarius': ['australic', 'lactarius'], + 'lacteal': ['catella', 'lacteal'], + 'lacteous': ['lacteous', 'osculate'], + 'lactide': ['citadel', 'deltaic', 'dialect', 'edictal', 'lactide'], + 'lactinate': ['cantalite', 'lactinate', 'tetanical'], + 'lacto': ['lacto', 'tlaco'], + 'lactoid': ['cotidal', 'lactoid', 'talcoid'], + 'lactoprotein': ['lactoprotein', 'protectional'], + 'lactose': ['alecost', 'lactose', 'scotale', 'talcose'], + 'lactoside': ['dislocate', 'lactoside'], + 'lactosuria': ['alacritous', 'lactarious', 'lactosuria'], + 'lacunal': ['calluna', 'lacunal'], + 'lacune': ['auncel', 'cuneal', 'lacune', 'launce', 'unlace'], + 'lacustral': ['claustral', 'lacustral'], + 'lacwork': ['lacwork', 'warlock'], + 'lacy': ['acyl', 'clay', 'lacy'], + 'lad': ['dal', 'lad'], + 'ladakin': ['danakil', 'dankali', 'kaldani', 'ladakin'], + 'ladanum': ['ladanum', 'udalman'], + 'ladder': ['ladder', 'raddle'], + 'laddery': ['dreadly', 'laddery'], + 'laddie': ['daidle', 'laddie'], + 'lade': ['dale', 'deal', 'lade', 'lead', 'leda'], + 'lademan': ['daleman', 'lademan', 'leadman'], + 'laden': ['eland', 'laden', 'lenad'], + 'lader': ['alder', 'daler', 'lader'], + 'ladies': ['aisled', 'deasil', 'ladies', 'sailed'], + 'ladin': ['danli', 'ladin', 'linda', 'nidal'], + 'lading': ['angild', 'lading'], + 'ladino': ['dolina', 'ladino'], + 'ladle': ['dalle', 'della', 'ladle'], + 'ladrone': ['endoral', 'ladrone', 'leonard'], + 'ladyfy': ['dayfly', 'ladyfy'], + 'ladyish': ['ladyish', 'shadily'], + 'ladyling': ['dallying', 'ladyling'], + 'laet': ['atle', 'laet', 'late', 'leat', 'tael', 'tale', 'teal'], + 'laeti': ['alite', 'laeti'], + 'laetic': ['calite', 'laetic', 'tecali'], + 'lafite': ['fetial', 'filate', 'lafite', 'leafit'], + 'lag': ['gal', 'lag'], + 'lagan': ['laang', 'lagan', 'lagna'], + 'lagen': ['agnel', 'angel', 'angle', 'galen', 'genal', 'glean', 'lagen'], + 'lagena': ['alnage', 'angela', 'galena', 'lagena'], + 'lagend': ['angled', 'dangle', 'englad', 'lagend'], + 'lager': ['argel', 'ergal', 'garle', 'glare', 'lager', 'large', 'regal'], + 'lagetto': ['lagetto', 'tagetol'], + 'lagged': ['daggle', 'lagged'], + 'laggen': ['laggen', 'naggle'], + 'lagger': ['gargle', 'gregal', 'lagger', 'raggle'], + 'lagna': ['laang', 'lagan', 'lagna'], + 'lagniappe': ['appealing', 'lagniappe', 'panplegia'], + 'lagonite': ['gelation', 'lagonite', 'legation'], + 'lagunero': ['lagunero', 'organule', 'uroglena'], + 'lagurus': ['argulus', 'lagurus'], + 'lai': ['ail', 'ila', 'lai'], + 'laicism': ['islamic', 'laicism', 'silicam'], + 'laid': ['dail', 'dali', 'dial', 'laid', 'lida'], + 'lain': ['alin', 'anil', 'lain', 'lina', 'nail'], + 'laine': ['alien', 'aline', 'anile', 'elain', 'elian', 'laine', 'linea'], + 'laiose': ['aeolis', 'laiose'], + 'lair': ['aril', 'lair', 'lari', 'liar', 'lira', 'rail', 'rial'], + 'lairage': ['lairage', 'railage', 'regalia'], + 'laird': ['drail', 'laird', 'larid', 'liard'], + 'lairless': ['lairless', 'railless'], + 'lairman': ['lairman', 'laminar', 'malarin', 'railman'], + 'lairstone': ['lairstone', 'orleanist', 'serotinal'], + 'lairy': ['lairy', 'riyal'], + 'laitance': ['analcite', 'anticlea', 'laitance'], + 'laity': ['laity', 'taily'], + 'lak': ['alk', 'lak'], + 'lake': ['kale', 'lake', 'leak'], + 'lakeless': ['lakeless', 'leakless'], + 'laker': ['karel', 'laker'], + 'lakie': ['alike', 'lakie'], + 'laking': ['kangli', 'laking'], + 'lakish': ['lakish', 'shakil'], + 'lakota': ['atokal', 'lakota'], + 'laky': ['alky', 'laky'], + 'lalo': ['lalo', 'lola', 'olla'], + 'lalopathy': ['allopathy', 'lalopathy'], + 'lam': ['lam', 'mal'], + 'lama': ['alma', 'amla', 'lama', 'mala'], + 'lamaic': ['amical', 'camail', 'lamaic'], + 'lamaism': ['lamaism', 'miasmal'], + 'lamaist': ['lamaist', 'lamista'], + 'lamaistic': ['ismatical', 'lamaistic'], + 'lamanite': ['lamanite', 'laminate'], + 'lamany': ['amylan', 'lamany', 'layman'], + 'lamb': ['balm', 'lamb'], + 'lambaste': ['blastema', 'lambaste'], + 'lambent': ['beltman', 'lambent'], + 'lamber': ['ambler', 'blamer', 'lamber', 'marble', 'ramble'], + 'lambie': ['bemail', 'lambie'], + 'lambiness': ['balminess', 'lambiness'], + 'lamblike': ['balmlike', 'lamblike'], + 'lamby': ['balmy', 'lamby'], + 'lame': ['alem', 'alme', 'lame', 'leam', 'male', 'meal', 'mela'], + 'lamella': ['lamella', 'malella', 'malleal'], + 'lamellose': ['lamellose', 'semolella'], + 'lamely': ['lamely', 'mellay'], + 'lameness': ['lameness', 'maleness', 'maneless', 'nameless'], + 'lament': ['lament', 'manlet', 'mantel', 'mantle', 'mental'], + 'lamenter': ['lamenter', 'relament', 'remantle'], + 'lamenting': ['alignment', 'lamenting'], + 'lameter': ['lameter', 'metaler', 'remetal'], + 'lamia': ['alima', 'lamia'], + 'lamiger': ['gremial', 'lamiger'], + 'lamiides': ['idealism', 'lamiides'], + 'lamin': ['lamin', 'liman', 'milan'], + 'lamina': ['almain', 'animal', 'lamina', 'manila'], + 'laminae': ['laminae', 'melania'], + 'laminar': ['lairman', 'laminar', 'malarin', 'railman'], + 'laminarin': ['laminarin', 'linamarin'], + 'laminarite': ['laminarite', 'terminalia'], + 'laminate': ['lamanite', 'laminate'], + 'laminated': ['almandite', 'laminated'], + 'lamination': ['antimonial', 'lamination'], + 'laminboard': ['laminboard', 'lombardian'], + 'laminectomy': ['laminectomy', 'metonymical'], + 'laminose': ['laminose', 'lemonias', 'semolina'], + 'lamish': ['lamish', 'shimal'], + 'lamista': ['lamaist', 'lamista'], + 'lamiter': ['lamiter', 'marlite'], + 'lammer': ['lammer', 'rammel'], + 'lammy': ['lammy', 'malmy'], + 'lamna': ['alman', 'lamna', 'manal'], + 'lamnid': ['lamnid', 'mandil'], + 'lamnidae': ['aldamine', 'lamnidae'], + 'lamp': ['lamp', 'palm'], + 'lampad': ['lampad', 'palmad'], + 'lampas': ['lampas', 'plasma'], + 'lamper': ['lamper', 'palmer', 'relamp'], + 'lampers': ['lampers', 'sampler'], + 'lampful': ['lampful', 'palmful'], + 'lampist': ['lampist', 'palmist'], + 'lampistry': ['lampistry', 'palmistry'], + 'lampoon': ['lampoon', 'pomonal'], + 'lamprey': ['lamprey', 'palmery'], + 'lampyridae': ['lampyridae', 'pyramidale'], + 'lamus': ['lamus', 'malus', 'musal', 'slaum'], + 'lamut': ['lamut', 'tamul'], + 'lan': ['aln', 'lan'], + 'lana': ['alan', 'anal', 'lana'], + 'lanas': ['alans', 'lanas', 'nasal'], + 'lanate': ['anteal', 'lanate', 'teanal'], + 'lancaster': ['ancestral', 'lancaster'], + 'lancasterian': ['alcantarines', 'lancasterian'], + 'lance': ['canel', 'clean', 'lance', 'lenca'], + 'lanced': ['calden', 'candle', 'lanced'], + 'lancely': ['cleanly', 'lancely'], + 'lanceolar': ['lanceolar', 'olecranal'], + 'lancer': ['lancer', 'rancel'], + 'lances': ['lances', 'senlac'], + 'lancet': ['cantle', 'cental', 'lancet', 'tancel'], + 'lanceteer': ['crenelate', 'lanceteer'], + 'lancinate': ['cantilena', 'lancinate'], + 'landbook': ['bookland', 'landbook'], + 'landed': ['dandle', 'landed'], + 'lander': ['aldern', + 'darnel', + 'enlard', + 'lander', + 'lenard', + 'randle', + 'reland'], + 'landfast': ['fastland', 'landfast'], + 'landgrave': ['grandeval', 'landgrave'], + 'landimere': ['landimere', 'madrilene'], + 'landing': ['danglin', 'landing'], + 'landlubber': ['landlubber', 'lubberland'], + 'landreeve': ['landreeve', 'reeveland'], + 'landstorm': ['landstorm', 'transmold'], + 'landwash': ['landwash', 'washland'], + 'lane': ['alen', 'lane', 'lean', 'lena', 'nael', 'neal'], + 'lanete': ['elanet', 'lanete', 'lateen'], + 'laney': ['laney', 'layne'], + 'langhian': ['hangnail', 'langhian'], + 'langi': ['algin', 'align', 'langi', 'liang', 'linga'], + 'langite': ['atingle', 'gelatin', 'genital', 'langite', 'telinga'], + 'lango': ['along', 'gonal', 'lango', 'longa', 'nogal'], + 'langobard': ['bandarlog', 'langobard'], + 'language': ['ganguela', 'language'], + 'laniate': ['laniate', 'natalie', 'taenial'], + 'lanific': ['finical', 'lanific'], + 'laniform': ['formalin', 'informal', 'laniform'], + 'laniidae': ['aedilian', 'laniidae'], + 'lanista': ['lanista', 'santali'], + 'lanius': ['insula', 'lanius', 'lusian'], + 'lank': ['klan', 'lank'], + 'lanket': ['anklet', 'lanket', 'tankle'], + 'lanner': ['lanner', 'rannel'], + 'lansat': ['aslant', 'lansat', 'natals', 'santal'], + 'lanseh': ['halsen', 'hansel', 'lanseh'], + 'lantaca': ['cantala', 'catalan', 'lantaca'], + 'lanum': ['lanum', 'manul'], + 'lao': ['alo', 'lao', 'loa'], + 'laodicean': ['caledonia', 'laodicean'], + 'laotian': ['ailanto', 'alation', 'laotian', 'notalia'], + 'lap': ['alp', 'lap', 'pal'], + 'laparohysterotomy': ['hysterolaparotomy', 'laparohysterotomy'], + 'laparosplenotomy': ['laparosplenotomy', 'splenolaparotomy'], + 'lapidarist': ['lapidarist', 'triapsidal'], + 'lapidate': ['lapidate', 'talpidae'], + 'lapideon': ['lapideon', 'palinode', 'pedalion'], + 'lapidose': ['episodal', 'lapidose', 'sepaloid'], + 'lapith': ['lapith', 'tilpah'], + 'lapon': ['lapon', 'nopal'], + 'lapp': ['lapp', 'palp', 'plap'], + 'lappa': ['lappa', 'papal'], + 'lapped': ['dapple', 'lapped', 'palped'], + 'lapper': ['lapper', 'rappel'], + 'lappish': ['lappish', 'shiplap'], + 'lapsation': ['apolistan', 'lapsation'], + 'lapse': ['elaps', + 'lapse', + 'lepas', + 'pales', + 'salep', + 'saple', + 'sepal', + 'slape', + 'spale', + 'speal'], + 'lapsi': ['alisp', 'lapsi'], + 'lapsing': ['lapsing', 'sapling'], + 'lapstone': ['lapstone', 'pleonast'], + 'larboard': ['labrador', 'larboard'], + 'larcenic': ['calciner', 'larcenic'], + 'larcenist': ['cisternal', 'larcenist'], + 'larcenous': ['larcenous', 'senocular'], + 'larchen': ['charnel', 'larchen'], + 'lardacein': ['ecardinal', 'lardacein'], + 'lardite': ['dilater', 'lardite', 'redtail'], + 'lardon': ['androl', 'arnold', 'lardon', 'roland', 'ronald'], + 'lardy': ['daryl', 'lardy', 'lyard'], + 'large': ['argel', 'ergal', 'garle', 'glare', 'lager', 'large', 'regal'], + 'largely': ['allergy', 'gallery', 'largely', 'regally'], + 'largen': ['angler', 'arleng', 'garnel', 'largen', 'rangle', 'regnal'], + 'largeness': ['largeness', 'rangeless', 'regalness'], + 'largess': ['glasser', 'largess'], + 'largition': ['gratiolin', 'largition', 'tailoring'], + 'largo': ['algor', 'argol', 'goral', 'largo'], + 'lari': ['aril', 'lair', 'lari', 'liar', 'lira', 'rail', 'rial'], + 'lariat': ['altair', 'atrail', 'atrial', 'lariat', 'latria', 'talari'], + 'larid': ['drail', 'laird', 'larid', 'liard'], + 'laridae': ['ardelia', 'laridae', 'radiale'], + 'larigo': ['gloria', 'larigo', 'logria'], + 'larigot': ['goitral', 'larigot', 'ligator'], + 'lariid': ['iridal', 'lariid'], + 'larine': ['arline', 'larine', 'linear', 'nailer', 'renail'], + 'lark': ['karl', 'kral', 'lark'], + 'larking': ['karling', 'larking'], + 'larsenite': ['intersale', 'larsenite'], + 'larus': ['larus', 'sural', 'ursal'], + 'larva': ['alvar', 'arval', 'larva'], + 'larval': ['larval', 'vallar'], + 'larvate': ['larvate', 'lavaret', 'travale'], + 'larve': ['arvel', 'larve', 'laver', 'ravel', 'velar'], + 'larvicide': ['larvicide', 'veridical'], + 'laryngopharyngeal': ['laryngopharyngeal', 'pharyngolaryngeal'], + 'laryngopharyngitis': ['laryngopharyngitis', 'pharyngolaryngitis'], + 'laryngotome': ['laryngotome', 'maternology'], + 'laryngotracheotomy': ['laryngotracheotomy', 'tracheolaryngotomy'], + 'las': ['las', 'sal', 'sla'], + 'lasa': ['alas', 'lasa'], + 'lascar': ['lascar', 'rascal', 'sacral', 'scalar'], + 'laser': ['arles', 'arsle', 'laser', 'seral', 'slare'], + 'lash': ['hals', 'lash'], + 'lasi': ['lasi', 'lias', 'lisa', 'sail', 'sial'], + 'lasius': ['asilus', 'lasius'], + 'lask': ['lask', 'skal'], + 'lasket': ['lasket', 'sklate'], + 'laspring': ['laspring', 'sparling', 'springal'], + 'lasque': ['lasque', 'squeal'], + 'lasset': ['lasset', 'tassel'], + 'lassie': ['elissa', 'lassie'], + 'lasso': ['lasso', 'ossal'], + 'lassoer': ['lassoer', 'oarless', 'rosales'], + 'last': ['last', 'salt', 'slat'], + 'laster': ['laster', + 'lastre', + 'rastle', + 'relast', + 'resalt', + 'salter', + 'slater', + 'stelar'], + 'lasting': ['anglist', 'lasting', 'salting', 'slating', 'staling'], + 'lastly': ['lastly', 'saltly'], + 'lastness': ['lastness', 'saltness'], + 'lastre': ['laster', + 'lastre', + 'rastle', + 'relast', + 'resalt', + 'salter', + 'slater', + 'stelar'], + 'lasty': ['lasty', 'salty', 'slaty'], + 'lat': ['alt', 'lat', 'tal'], + 'lata': ['lata', 'taal', 'tala'], + 'latania': ['altaian', 'latania', 'natalia'], + 'latcher': ['clethra', 'latcher', 'ratchel', 'relatch', 'talcher', 'trachle'], + 'latchet': ['chattel', 'latchet'], + 'late': ['atle', 'laet', 'late', 'leat', 'tael', 'tale', 'teal'], + 'latebra': ['alberta', 'latebra', 'ratable'], + 'lated': ['adlet', 'dealt', 'delta', 'lated', 'taled'], + 'lateen': ['elanet', 'lanete', 'lateen'], + 'lately': ['lately', 'lealty'], + 'laten': ['ental', 'laten', 'leant'], + 'latent': ['latent', 'latten', 'nattle', 'talent', 'tantle'], + 'latentness': ['latentness', 'tenantless'], + 'later': ['alert', 'alter', 'artel', 'later', 'ratel', 'taler', 'telar'], + 'latera': ['latera', 'relata'], + 'laterad': ['altared', 'laterad'], + 'lateralis': ['lateralis', 'stellaria'], + 'lateran': ['alatern', 'lateran'], + 'laterite': ['laterite', 'literate', 'teretial'], + 'laterocaudal': ['caudolateral', 'laterocaudal'], + 'laterodorsal': ['dorsolateral', 'laterodorsal'], + 'lateroventral': ['lateroventral', 'ventrolateral'], + 'latest': ['latest', 'sattle', 'taslet'], + 'latex': ['exalt', 'latex'], + 'lath': ['halt', 'lath'], + 'lathe': ['ethal', 'lathe', 'leath'], + 'latheman': ['latheman', 'methanal'], + 'lathen': ['ethnal', 'hantle', 'lathen', 'thenal'], + 'lather': ['arthel', 'halter', 'lather', 'thaler'], + 'lathery': ['earthly', 'heartly', 'lathery', 'rathely'], + 'lathing': ['halting', 'lathing', 'thingal'], + 'latian': ['antlia', 'latian', 'nalita'], + 'latibulize': ['latibulize', 'utilizable'], + 'latices': ['astelic', 'elastic', 'latices'], + 'laticlave': ['laticlave', 'vacillate'], + 'latigo': ['galiot', 'latigo'], + 'latimeria': ['latimeria', 'marialite'], + 'latin': ['altin', 'latin'], + 'latinate': ['antliate', 'latinate'], + 'latiner': ['entrail', + 'latiner', + 'latrine', + 'ratline', + 'reliant', + 'retinal', + 'trenail'], + 'latinesque': ['latinesque', 'sequential'], + 'latinian': ['antinial', 'latinian'], + 'latinizer': ['latinizer', 'trinalize'], + 'latinus': ['latinus', 'tulisan', 'unalist'], + 'lation': ['italon', 'lation', 'talion'], + 'latirostres': ['latirostres', 'setirostral'], + 'latirus': ['latirus', 'trisula'], + 'latish': ['latish', 'tahsil'], + 'latite': ['latite', 'tailet', 'tailte', 'talite'], + 'latitude': ['altitude', 'latitude'], + 'latitudinal': ['altitudinal', 'latitudinal'], + 'latitudinarian': ['altitudinarian', 'latitudinarian'], + 'latomy': ['latomy', 'tyloma'], + 'latona': ['atonal', 'latona'], + 'latonian': ['latonian', 'nataloin', 'national'], + 'latria': ['altair', 'atrail', 'atrial', 'lariat', 'latria', 'talari'], + 'latrine': ['entrail', + 'latiner', + 'latrine', + 'ratline', + 'reliant', + 'retinal', + 'trenail'], + 'latris': ['latris', 'strial'], + 'latro': ['latro', 'rotal', 'toral'], + 'latrobe': ['alberto', 'bloater', 'latrobe'], + 'latrobite': ['latrobite', 'trilobate'], + 'latrocinium': ['latrocinium', 'tourmalinic'], + 'latron': ['latron', 'lontar', 'tornal'], + 'latten': ['latent', 'latten', 'nattle', 'talent', 'tantle'], + 'latter': ['artlet', 'latter', 'rattle', 'tartle', 'tatler'], + 'latterkin': ['intertalk', 'latterkin'], + 'lattice': ['lattice', 'tactile'], + 'latticinio': ['latticinio', 'licitation'], + 'latuka': ['latuka', 'taluka'], + 'latus': ['latus', 'sault', 'talus'], + 'latvian': ['latvian', 'valiant'], + 'laubanite': ['laubanite', 'unlabiate'], + 'laud': ['auld', 'dual', 'laud', 'udal'], + 'laudation': ['adulation', 'laudation'], + 'laudator': ['adulator', 'laudator'], + 'laudatorily': ['illaudatory', 'laudatorily'], + 'laudatory': ['adulatory', 'laudatory'], + 'lauder': ['lauder', 'udaler'], + 'laudism': ['dualism', 'laudism'], + 'laudist': ['dualist', 'laudist'], + 'laumonite': ['emulation', 'laumonite'], + 'laun': ['laun', 'luna', 'ulna', 'unal'], + 'launce': ['auncel', 'cuneal', 'lacune', 'launce', 'unlace'], + 'launch': ['chulan', 'launch', 'nuchal'], + 'launcher': ['launcher', 'relaunch'], + 'laund': ['dunal', 'laund', 'lunda', 'ulnad'], + 'launder': ['launder', 'rundale'], + 'laur': ['alur', 'laur', 'lura', 'raul', 'ural'], + 'laura': ['aural', 'laura'], + 'laurel': ['allure', 'laurel'], + 'laureled': ['laureled', 'reallude'], + 'laurence': ['cerulean', 'laurence'], + 'laurent': ['laurent', 'neutral', 'unalert'], + 'laurentide': ['adulterine', 'laurentide'], + 'lauric': ['curial', 'lauric', 'uracil', 'uralic'], + 'laurin': ['laurin', 'urinal'], + 'laurite': ['laurite', 'uralite'], + 'laurus': ['laurus', 'ursula'], + 'lava': ['aval', 'lava'], + 'lavacre': ['caravel', 'lavacre'], + 'lavaret': ['larvate', 'lavaret', 'travale'], + 'lave': ['lave', 'vale', 'veal', 'vela'], + 'laveer': ['laveer', 'leaver', 'reveal', 'vealer'], + 'lavehr': ['halver', 'lavehr'], + 'lavenite': ['elvanite', 'lavenite'], + 'laver': ['arvel', 'larve', 'laver', 'ravel', 'velar'], + 'laverania': ['laverania', 'valeriana'], + 'lavic': ['cavil', 'lavic'], + 'lavinia': ['lavinia', 'vinalia'], + 'lavish': ['lavish', 'vishal'], + 'lavisher': ['lavisher', 'shrieval'], + 'lavolta': ['lavolta', 'vallota'], + 'law': ['awl', 'law'], + 'lawing': ['lawing', 'waling'], + 'lawk': ['lawk', 'walk'], + 'lawmonger': ['angleworm', 'lawmonger'], + 'lawned': ['delawn', 'lawned', 'wandle'], + 'lawner': ['lawner', 'warnel'], + 'lawny': ['lawny', 'wanly'], + 'lawrie': ['lawrie', 'wailer'], + 'lawter': ['lawter', 'walter'], + 'lawyer': ['lawyer', 'yawler'], + 'laxism': ['laxism', 'smilax'], + 'lay': ['aly', 'lay'], + 'layer': ['early', 'layer', 'relay'], + 'layered': ['delayer', 'layered', 'redelay'], + 'layery': ['layery', 'yearly'], + 'laying': ['gainly', 'laying'], + 'layman': ['amylan', 'lamany', 'layman'], + 'layne': ['laney', 'layne'], + 'layout': ['layout', 'lutayo', 'outlay'], + 'layover': ['layover', 'overlay'], + 'layship': ['apishly', 'layship'], + 'lazarlike': ['alkalizer', 'lazarlike'], + 'laze': ['laze', 'zeal'], + 'lea': ['ale', 'lea'], + 'leach': ['chela', 'lache', 'leach'], + 'leachman': ['leachman', 'mechanal'], + 'lead': ['dale', 'deal', 'lade', 'lead', 'leda'], + 'leadable': ['dealable', 'leadable'], + 'leaded': ['delead', 'leaded'], + 'leader': ['dealer', 'leader', 'redeal', 'relade', 'relead'], + 'leadership': ['dealership', 'leadership'], + 'leadin': ['aldine', 'daniel', 'delian', 'denial', 'enalid', 'leadin'], + 'leadiness': ['idealness', 'leadiness'], + 'leading': ['adeling', 'dealing', 'leading'], + 'leadman': ['daleman', 'lademan', 'leadman'], + 'leads': ['leads', 'slade'], + 'leadsman': ['dalesman', 'leadsman'], + 'leadstone': ['endosteal', 'leadstone'], + 'leady': ['delay', 'leady'], + 'leaf': ['alef', 'feal', 'flea', 'leaf'], + 'leafen': ['enleaf', 'leafen'], + 'leafit': ['fetial', 'filate', 'lafite', 'leafit'], + 'leafy': ['fleay', 'leafy'], + 'leah': ['hale', 'heal', 'leah'], + 'leak': ['kale', 'lake', 'leak'], + 'leakiness': ['alikeness', 'leakiness'], + 'leakless': ['lakeless', 'leakless'], + 'leal': ['alle', 'ella', 'leal'], + 'lealty': ['lately', 'lealty'], + 'leam': ['alem', 'alme', 'lame', 'leam', 'male', 'meal', 'mela'], + 'leamer': ['leamer', 'mealer'], + 'lean': ['alen', 'lane', 'lean', 'lena', 'nael', 'neal'], + 'leander': ['leander', 'learned', 'reladen'], + 'leaner': ['arlene', 'leaner'], + 'leaning': ['angelin', 'leaning'], + 'leant': ['ental', 'laten', 'leant'], + 'leap': ['leap', 'lepa', 'pale', 'peal', 'plea'], + 'leaper': ['leaper', 'releap', 'repale', 'repeal'], + 'leaping': ['apeling', 'leaping'], + 'leapt': ['leapt', + 'palet', + 'patel', + 'pelta', + 'petal', + 'plate', + 'pleat', + 'tepal'], + 'lear': ['earl', 'eral', 'lear', 'real'], + 'learn': ['learn', 'renal'], + 'learned': ['leander', 'learned', 'reladen'], + 'learnedly': ['ellenyard', 'learnedly'], + 'learner': ['learner', 'relearn'], + 'learnt': ['altern', 'antler', 'learnt', 'rental', 'ternal'], + 'leasable': ['leasable', 'sealable'], + 'lease': ['easel', 'lease'], + 'leaser': ['alerse', 'leaser', 'reales', 'resale', 'reseal', 'sealer'], + 'leash': ['halse', 'leash', 'selah', 'shale', 'sheal', 'shela'], + 'leasing': ['leasing', 'sealing'], + 'least': ['least', 'setal', 'slate', 'stale', 'steal', 'stela', 'tales'], + 'leat': ['atle', 'laet', 'late', 'leat', 'tael', 'tale', 'teal'], + 'leath': ['ethal', 'lathe', 'leath'], + 'leather': ['leather', 'tarheel'], + 'leatherbark': ['halterbreak', 'leatherbark'], + 'leatherer': ['leatherer', 'releather', 'tarheeler'], + 'leatman': ['amental', 'leatman'], + 'leaver': ['laveer', 'leaver', 'reveal', 'vealer'], + 'leaves': ['leaves', 'sleave'], + 'leaving': ['leaving', 'vangeli'], + 'leavy': ['leavy', 'vealy'], + 'leban': ['leban', 'nable'], + 'lebanese': ['ebenales', 'lebanese'], + 'lebensraum': ['lebensraum', 'mensurable'], + 'lecaniid': ['alcidine', 'danielic', 'lecaniid'], + 'lecanora': ['carolean', 'lecanora'], + 'lecanoroid': ['lecanoroid', 'olecranoid'], + 'lechery': ['cheerly', 'lechery'], + 'lechriodont': ['holocentrid', 'lechriodont'], + 'lecithal': ['hellicat', 'lecithal'], + 'lecontite': ['lecontite', 'nicolette'], + 'lector': ['colter', 'lector', 'torcel'], + 'lectorial': ['corallite', 'lectorial'], + 'lectorship': ['lectorship', 'leptorchis'], + 'lectrice': ['electric', 'lectrice'], + 'lecturess': ['cutleress', 'lecturess', 'truceless'], + 'lecyth': ['lecyth', 'letchy'], + 'lecythis': ['chestily', 'lecythis'], + 'led': ['del', 'eld', 'led'], + 'leda': ['dale', 'deal', 'lade', 'lead', 'leda'], + 'lede': ['dele', 'lede', 'leed'], + 'leden': ['leden', 'neeld'], + 'ledge': ['glede', 'gleed', 'ledge'], + 'ledger': ['gelder', 'ledger', 'redleg'], + 'ledging': ['gelding', 'ledging'], + 'ledgy': ['gledy', 'ledgy'], + 'lee': ['eel', 'lee'], + 'leed': ['dele', 'lede', 'leed'], + 'leek': ['keel', 'kele', 'leek'], + 'leep': ['leep', 'peel', 'pele'], + 'leepit': ['leepit', 'pelite', 'pielet'], + 'leer': ['leer', 'reel'], + 'leeringly': ['leeringly', 'reelingly'], + 'leerness': ['leerness', 'lessener'], + 'lees': ['else', 'lees', 'seel', 'sele', 'slee'], + 'leet': ['leet', 'lete', 'teel', 'tele'], + 'leetman': ['entelam', 'leetman'], + 'leewan': ['leewan', 'weanel'], + 'left': ['felt', 'flet', 'left'], + 'leftish': ['fishlet', 'leftish'], + 'leftness': ['feltness', 'leftness'], + 'leg': ['gel', 'leg'], + 'legalist': ['legalist', 'stillage'], + 'legantine': ['eglantine', 'inelegant', 'legantine'], + 'legate': ['eaglet', 'legate', 'teagle', 'telega'], + 'legatine': ['galenite', 'legatine'], + 'legation': ['gelation', 'lagonite', 'legation'], + 'legative': ['legative', 'levigate'], + 'legator': ['argolet', 'gloater', 'legator'], + 'legendary': ['enragedly', 'legendary'], + 'leger': ['leger', 'regle'], + 'legger': ['eggler', 'legger'], + 'legion': ['eloign', 'gileno', 'legion'], + 'legioner': ['eloigner', 'legioner'], + 'legionry': ['legionry', 'yeorling'], + 'legislator': ['allegorist', 'legislator'], + 'legman': ['legman', 'mangel', 'mangle'], + 'legoa': ['gloea', 'legoa'], + 'legua': ['gulae', 'legua'], + 'leguan': ['genual', 'leguan'], + 'lehr': ['herl', 'hler', 'lehr'], + 'lei': ['eli', 'lei', 'lie'], + 'leif': ['feil', 'file', 'leif', 'lief', 'life'], + 'leila': ['allie', 'leila', 'lelia'], + 'leipoa': ['apiole', 'leipoa'], + 'leisten': ['leisten', 'setline', 'tensile'], + 'leister': ['leister', 'sterile'], + 'leith': ['leith', 'lithe'], + 'leitneria': ['leitneria', 'lienteria'], + 'lek': ['elk', 'lek'], + 'lekach': ['hackle', 'lekach'], + 'lekane': ['alkene', 'lekane'], + 'lelia': ['allie', 'leila', 'lelia'], + 'leman': ['leman', 'lemna'], + 'lemma': ['lemma', 'melam'], + 'lemna': ['leman', 'lemna'], + 'lemnad': ['lemnad', 'menald'], + 'lemnian': ['lemnian', 'lineman', 'melanin'], + 'lemniscate': ['centesimal', 'lemniscate'], + 'lemon': ['lemon', 'melon', 'monel'], + 'lemonias': ['laminose', 'lemonias', 'semolina'], + 'lemonlike': ['lemonlike', 'melonlike'], + 'lemony': ['lemony', 'myelon'], + 'lemosi': ['lemosi', 'limose', 'moiles'], + 'lempira': ['impaler', 'impearl', 'lempira', 'premial'], + 'lemuria': ['lemuria', 'miauler'], + 'lemurian': ['lemurian', 'malurine', 'rumelian'], + 'lemurinae': ['lemurinae', 'neurilema'], + 'lemurine': ['lemurine', 'meruline', 'relumine'], + 'lena': ['alen', 'lane', 'lean', 'lena', 'nael', 'neal'], + 'lenad': ['eland', 'laden', 'lenad'], + 'lenape': ['alpeen', 'lenape', 'pelean'], + 'lenard': ['aldern', + 'darnel', + 'enlard', + 'lander', + 'lenard', + 'randle', + 'reland'], + 'lenca': ['canel', 'clean', 'lance', 'lenca'], + 'lencan': ['cannel', 'lencan'], + 'lendee': ['lendee', 'needle'], + 'lender': ['lender', 'relend'], + 'lendu': ['lendu', 'unled'], + 'lengthy': ['lengthy', 'thegnly'], + 'lenient': ['lenient', 'tenline'], + 'lenify': ['finely', 'lenify'], + 'lenis': ['elsin', 'lenis', 'niels', 'silen', 'sline'], + 'lenity': ['lenity', 'yetlin'], + 'lenny': ['lenny', 'lynne'], + 'leno': ['elon', 'enol', 'leno', 'leon', 'lone', 'noel'], + 'lenora': ['lenora', 'loaner', 'orlean', 'reloan'], + 'lenticel': ['lenticel', 'lenticle'], + 'lenticle': ['lenticel', 'lenticle'], + 'lentil': ['lentil', 'lintel'], + 'lentisc': ['lentisc', 'scintle', 'stencil'], + 'lentisco': ['lentisco', 'telsonic'], + 'lentiscus': ['lentiscus', 'tunicless'], + 'lento': ['lento', 'olent'], + 'lentous': ['lentous', 'sultone'], + 'lenvoy': ['lenvoy', 'ovenly'], + 'leo': ['leo', 'ole'], + 'leon': ['elon', 'enol', 'leno', 'leon', 'lone', 'noel'], + 'leonard': ['endoral', 'ladrone', 'leonard'], + 'leonhardite': ['leonhardite', 'lionhearted'], + 'leonid': ['doline', 'indole', 'leonid', 'loined', 'olenid'], + 'leonines': ['leonines', 'selenion'], + 'leonis': ['insole', 'leonis', 'lesion', 'selion'], + 'leonist': ['leonist', 'onliest'], + 'leonite': ['elonite', 'leonite'], + 'leonotis': ['leonotis', 'oilstone'], + 'leoparde': ['leoparde', 'reapdole'], + 'leopardite': ['leopardite', 'protelidae'], + 'leotard': ['delator', 'leotard'], + 'lepa': ['leap', 'lepa', 'pale', 'peal', 'plea'], + 'lepanto': ['lepanto', 'nepotal', 'petalon', 'polenta'], + 'lepas': ['elaps', + 'lapse', + 'lepas', + 'pales', + 'salep', + 'saple', + 'sepal', + 'slape', + 'spale', + 'speal'], + 'lepcha': ['chapel', 'lepcha', 'pleach'], + 'leper': ['leper', 'perle', 'repel'], + 'leperdom': ['leperdom', 'premodel'], + 'lepidopter': ['dopplerite', 'lepidopter'], + 'lepidosauria': ['lepidosauria', 'pliosauridae'], + 'lepidote': ['lepidote', 'petioled'], + 'lepidotic': ['diploetic', 'lepidotic'], + 'lepisma': ['ampelis', 'lepisma'], + 'leporid': ['leporid', 'leproid'], + 'leporis': ['leporis', 'spoiler'], + 'lepra': ['lepra', 'paler', 'parel', 'parle', 'pearl', 'perla', 'relap'], + 'leproid': ['leporid', 'leproid'], + 'leproma': ['leproma', 'palermo', 'pleroma', 'polearm'], + 'leprosied': ['despoiler', 'leprosied'], + 'leprosis': ['leprosis', 'plerosis'], + 'leprous': ['leprous', 'pelorus', 'sporule'], + 'leptandra': ['leptandra', 'peltandra'], + 'leptidae': ['depilate', 'leptidae', 'pileated'], + 'leptiform': ['leptiform', 'peltiform'], + 'leptodora': ['doorplate', 'leptodora'], + 'leptome': ['leptome', 'poemlet'], + 'lepton': ['lepton', 'pentol'], + 'leptonema': ['leptonema', 'ptolemean'], + 'leptorchis': ['lectorship', 'leptorchis'], + 'lepus': ['lepus', 'pulse'], + 'ler': ['ler', 'rel'], + 'lernaean': ['annealer', 'lernaean', 'reanneal'], + 'lerot': ['lerot', 'orlet', 'relot'], + 'lerwa': ['lerwa', 'waler'], + 'les': ['els', 'les'], + 'lesath': ['haslet', 'lesath', 'shelta'], + 'lesbia': ['isabel', 'lesbia'], + 'lesche': ['lesche', 'sleech'], + 'lesion': ['insole', 'leonis', 'lesion', 'selion'], + 'lesional': ['lesional', 'solenial'], + 'leslie': ['leslie', 'sellie'], + 'lessener': ['leerness', 'lessener'], + 'lest': ['lest', 'selt'], + 'lester': ['lester', 'selter', 'streel'], + 'let': ['elt', 'let'], + 'letchy': ['lecyth', 'letchy'], + 'lete': ['leet', 'lete', 'teel', 'tele'], + 'lethargus': ['lethargus', 'slaughter'], + 'lethe': ['ethel', 'lethe'], + 'lethean': ['entheal', 'lethean'], + 'lethologica': ['ethological', 'lethologica', 'theological'], + 'letitia': ['italite', 'letitia', 'tilaite'], + 'leto': ['leto', 'lote', 'tole'], + 'letoff': ['letoff', 'offlet'], + 'lett': ['lett', 'telt'], + 'letten': ['letten', 'nettle'], + 'letterer': ['letterer', 'reletter'], + 'lettish': ['lettish', 'thistle'], + 'lettrin': ['lettrin', 'trintle'], + 'leu': ['leu', 'lue', 'ule'], + 'leucadian': ['leucadian', 'lucanidae'], + 'leucocism': ['leucocism', 'muscicole'], + 'leucoma': ['caulome', 'leucoma'], + 'leucosis': ['coulisse', 'leucosis', 'ossicule'], + 'leud': ['deul', 'duel', 'leud'], + 'leuk': ['leuk', 'luke'], + 'leuma': ['amelu', 'leuma', 'ulema'], + 'leung': ['leung', 'lunge'], + 'levance': ['enclave', 'levance', 'valence'], + 'levant': ['levant', 'valent'], + 'levanter': ['levanter', 'relevant', 'revelant'], + 'levantine': ['levantine', 'valentine'], + 'leveler': ['leveler', 'relevel'], + 'lever': ['elver', 'lever', 'revel'], + 'leverer': ['leverer', 'reveler'], + 'levi': ['evil', 'levi', 'live', 'veil', 'vile', 'vlei'], + 'levier': ['levier', 'relive', 'reveil', 'revile', 'veiler'], + 'levigate': ['legative', 'levigate'], + 'levin': ['levin', 'liven'], + 'levining': ['levining', 'nievling'], + 'levir': ['levir', 'liver', 'livre', 'rivel'], + 'levirate': ['levirate', 'relative'], + 'levis': ['elvis', 'levis', 'slive'], + 'levitation': ['levitation', 'tonalitive', 'velitation'], + 'levo': ['levo', 'love', 'velo', 'vole'], + 'levyist': ['levyist', 'sylvite'], + 'lewd': ['lewd', 'weld'], + 'lewis': ['lewis', 'swile'], + 'lexia': ['axile', 'lexia'], + 'ley': ['ley', 'lye'], + 'lhota': ['altho', 'lhota', 'loath'], + 'liability': ['alibility', 'liability'], + 'liable': ['alible', 'belial', 'labile', 'liable'], + 'liana': ['alain', 'alani', 'liana'], + 'liang': ['algin', 'align', 'langi', 'liang', 'linga'], + 'liar': ['aril', 'lair', 'lari', 'liar', 'lira', 'rail', 'rial'], + 'liard': ['drail', 'laird', 'larid', 'liard'], + 'lias': ['lasi', 'lias', 'lisa', 'sail', 'sial'], + 'liatris': ['liatris', 'trilisa'], + 'libament': ['bailment', 'libament'], + 'libate': ['albeit', + 'albite', + 'baltei', + 'belait', + 'betail', + 'bletia', + 'libate'], + 'libationer': ['libationer', 'liberation'], + 'libber': ['libber', 'ribble'], + 'libby': ['bilby', 'libby'], + 'libellary': ['libellary', 'liberally'], + 'liber': ['birle', 'liber'], + 'liberal': ['braille', 'liberal'], + 'liberally': ['libellary', 'liberally'], + 'liberate': ['iterable', 'liberate'], + 'liberation': ['libationer', 'liberation'], + 'liberator': ['liberator', 'orbitelar'], + 'liberian': ['bilinear', 'liberian'], + 'libertas': ['abristle', 'libertas'], + 'libertine': ['berlinite', 'libertine'], + 'libra': ['blair', 'brail', 'libra'], + 'librate': ['betrail', 'librate', 'triable', 'trilabe'], + 'licania': ['lacinia', 'licania'], + 'license': ['license', 'selenic', 'silence'], + 'licensed': ['licensed', 'silenced'], + 'licenser': ['licenser', 'silencer'], + 'licensor': ['cresolin', 'licensor'], + 'lich': ['chil', 'lich'], + 'lichanos': ['lichanos', 'nicholas'], + 'lichenoid': ['cheloniid', 'lichenoid'], + 'lichi': ['chili', 'lichi'], + 'licitation': ['latticinio', 'licitation'], + 'licker': ['licker', 'relick', 'rickle'], + 'lickspit': ['lickspit', 'lipstick'], + 'licorne': ['creolin', 'licorne', 'locrine'], + 'lida': ['dail', 'dali', 'dial', 'laid', 'lida'], + 'lidded': ['diddle', 'lidded'], + 'lidder': ['lidder', 'riddel', 'riddle'], + 'lide': ['idle', 'lide', 'lied'], + 'lie': ['eli', 'lei', 'lie'], + 'lied': ['idle', 'lide', 'lied'], + 'lief': ['feil', 'file', 'leif', 'lief', 'life'], + 'lien': ['lien', 'line', 'neil', 'nile'], + 'lienal': ['lienal', 'lineal'], + 'lienee': ['eileen', 'lienee'], + 'lienor': ['elinor', 'lienor', 'lorien', 'noiler'], + 'lienteria': ['leitneria', 'lienteria'], + 'lientery': ['entirely', 'lientery'], + 'lier': ['lier', 'lire', 'rile'], + 'lierne': ['lierne', 'reline'], + 'lierre': ['lierre', 'relier'], + 'liesh': ['liesh', 'shiel'], + 'lievaart': ['lievaart', 'varietal'], + 'life': ['feil', 'file', 'leif', 'lief', 'life'], + 'lifelike': ['filelike', 'lifelike'], + 'lifer': ['filer', 'flier', 'lifer', 'rifle'], + 'lifeward': ['drawfile', 'lifeward'], + 'lifo': ['filo', 'foil', 'lifo'], + 'lift': ['flit', 'lift'], + 'lifter': ['fertil', 'filter', 'lifter', 'relift', 'trifle'], + 'lifting': ['fliting', 'lifting'], + 'ligament': ['ligament', 'metaling', 'tegminal'], + 'ligas': ['gisla', 'ligas', 'sigla'], + 'ligate': ['aiglet', 'ligate', 'taigle', 'tailge'], + 'ligation': ['intaglio', 'ligation'], + 'ligator': ['goitral', 'larigot', 'ligator'], + 'ligature': ['alurgite', 'ligature'], + 'lighten': ['enlight', 'lighten'], + 'lightener': ['lightener', 'relighten', 'threeling'], + 'lighter': ['lighter', 'relight', 'rightle'], + 'lighthead': ['headlight', 'lighthead'], + 'lightness': ['lightness', 'nightless', 'thingless'], + 'ligne': ['ingle', 'ligne', 'linge', 'nigel'], + 'lignin': ['lignin', 'lining'], + 'lignitic': ['lignitic', 'tiglinic'], + 'lignose': ['gelosin', 'lignose'], + 'ligroine': ['ligroine', 'religion'], + 'ligure': ['ligure', 'reguli'], + 'lija': ['jail', 'lija'], + 'like': ['kiel', 'like'], + 'liken': ['inkle', 'liken'], + 'likewise': ['likewise', 'wiselike'], + 'lilac': ['calli', 'lilac'], + 'lilacky': ['alkylic', 'lilacky'], + 'lilium': ['illium', 'lilium'], + 'lilt': ['lilt', 'till'], + 'lily': ['illy', 'lily', 'yill'], + 'lim': ['lim', 'mil'], + 'lima': ['amil', 'amli', 'lima', 'mail', 'mali', 'mila'], + 'limacina': ['animalic', 'limacina'], + 'limacon': ['limacon', 'malonic'], + 'liman': ['lamin', 'liman', 'milan'], + 'limation': ['limation', 'miltonia'], + 'limbat': ['limbat', 'timbal'], + 'limbate': ['limbate', 'timable', 'timbale'], + 'limbed': ['dimble', 'limbed'], + 'limbus': ['bluism', 'limbus'], + 'limby': ['blimy', 'limby'], + 'lime': ['emil', 'lime', 'mile'], + 'limean': ['limean', 'maline', 'melian', 'menial'], + 'limeman': ['ammelin', 'limeman'], + 'limer': ['limer', 'meril', 'miler'], + 'limes': ['limes', 'miles', 'slime', 'smile'], + 'limestone': ['limestone', 'melonites', 'milestone'], + 'limey': ['elymi', 'emily', 'limey'], + 'liminess': ['liminess', 'senilism'], + 'limitary': ['limitary', 'military'], + 'limitate': ['limitate', 'militate'], + 'limitation': ['limitation', 'militation'], + 'limited': ['delimit', 'limited'], + 'limiter': ['limiter', 'relimit'], + 'limitless': ['limitless', 'semistill'], + 'limner': ['limner', 'merlin', 'milner'], + 'limnetic': ['limnetic', 'milicent'], + 'limoniad': ['dominial', 'imolinda', 'limoniad'], + 'limosa': ['limosa', 'somali'], + 'limose': ['lemosi', 'limose', 'moiles'], + 'limp': ['limp', 'pilm', 'plim'], + 'limper': ['limper', 'prelim', 'rimple'], + 'limping': ['impling', 'limping'], + 'limpsy': ['limpsy', 'simply'], + 'limpy': ['imply', 'limpy', 'pilmy'], + 'limsy': ['limsy', 'slimy', 'smily'], + 'lin': ['lin', 'nil'], + 'lina': ['alin', 'anil', 'lain', 'lina', 'nail'], + 'linaga': ['agnail', 'linaga'], + 'linage': ['algine', 'genial', 'linage'], + 'linamarin': ['laminarin', 'linamarin'], + 'linarite': ['inertial', 'linarite'], + 'linchet': ['linchet', 'tinchel'], + 'linctus': ['clunist', 'linctus'], + 'linda': ['danli', 'ladin', 'linda', 'nidal'], + 'lindane': ['annelid', 'lindane'], + 'linder': ['linder', 'rindle'], + 'lindoite': ['lindoite', 'tolidine'], + 'lindsay': ['islandy', 'lindsay'], + 'line': ['lien', 'line', 'neil', 'nile'], + 'linea': ['alien', 'aline', 'anile', 'elain', 'elian', 'laine', 'linea'], + 'lineal': ['lienal', 'lineal'], + 'lineament': ['lineament', 'manteline'], + 'linear': ['arline', 'larine', 'linear', 'nailer', 'renail'], + 'linearity': ['inreality', 'linearity'], + 'lineate': ['elatine', 'lineate'], + 'lineature': ['lineature', 'rutelinae'], + 'linecut': ['linecut', 'tunicle'], + 'lined': ['eldin', 'lined'], + 'lineman': ['lemnian', 'lineman', 'melanin'], + 'linen': ['linen', 'linne'], + 'linesman': ['annelism', 'linesman'], + 'linet': ['inlet', 'linet'], + 'linga': ['algin', 'align', 'langi', 'liang', 'linga'], + 'lingbird': ['birdling', 'bridling', 'lingbird'], + 'linge': ['ingle', 'ligne', 'linge', 'nigel'], + 'linger': ['linger', 'ringle'], + 'lingo': ['lingo', 'login'], + 'lingtow': ['lingtow', 'twoling'], + 'lingua': ['gaulin', 'lingua'], + 'lingual': ['lingual', 'lingula'], + 'linguidental': ['dentilingual', 'indulgential', 'linguidental'], + 'lingula': ['lingual', 'lingula'], + 'linguodental': ['dentolingual', 'linguodental'], + 'lingy': ['lingy', 'lying'], + 'linha': ['linha', 'nihal'], + 'lining': ['lignin', 'lining'], + 'link': ['kiln', 'link'], + 'linked': ['kindle', 'linked'], + 'linker': ['linker', 'relink'], + 'linking': ['inkling', 'linking'], + 'linkman': ['kilnman', 'linkman'], + 'links': ['links', 'slink'], + 'linnaea': ['alanine', 'linnaea'], + 'linnaean': ['annaline', 'linnaean'], + 'linne': ['linen', 'linne'], + 'linnet': ['linnet', 'linten'], + 'lino': ['lino', 'lion', 'loin', 'noil'], + 'linolenic': ['encinillo', 'linolenic'], + 'linometer': ['linometer', 'nilometer'], + 'linopteris': ['linopteris', 'prosilient'], + 'linous': ['insoul', 'linous', 'nilous', 'unsoil'], + 'linsey': ['linsey', 'lysine'], + 'linstock': ['coltskin', 'linstock'], + 'lintel': ['lentil', 'lintel'], + 'linten': ['linnet', 'linten'], + 'lintseed': ['enlisted', 'lintseed'], + 'linum': ['linum', 'ulmin'], + 'linus': ['linus', 'sunil'], + 'liny': ['inly', 'liny'], + 'lion': ['lino', 'lion', 'loin', 'noil'], + 'lioncel': ['colline', 'lioncel'], + 'lionel': ['lionel', 'niello'], + 'lionet': ['entoil', 'lionet'], + 'lionhearted': ['leonhardite', 'lionhearted'], + 'lipa': ['lipa', 'pail', 'pali', 'pial'], + 'lipan': ['lipan', 'pinal', 'plain'], + 'liparis': ['aprilis', 'liparis'], + 'liparite': ['liparite', 'reptilia'], + 'liparous': ['liparous', 'pliosaur'], + 'lipase': ['espial', 'lipase', 'pelias'], + 'lipin': ['lipin', 'pilin'], + 'liplet': ['liplet', 'pillet'], + 'lipochondroma': ['chondrolipoma', 'lipochondroma'], + 'lipoclasis': ['calliopsis', 'lipoclasis'], + 'lipocyte': ['epicotyl', 'lipocyte'], + 'lipofibroma': ['fibrolipoma', 'lipofibroma'], + 'lipolytic': ['lipolytic', 'politicly'], + 'lipoma': ['lipoma', 'pimola', 'ploima'], + 'lipomyoma': ['lipomyoma', 'myolipoma'], + 'lipomyxoma': ['lipomyxoma', 'myxolipoma'], + 'liposis': ['liposis', 'pilosis'], + 'lipotype': ['lipotype', 'polypite'], + 'lippen': ['lippen', 'nipple'], + 'lipper': ['lipper', 'ripple'], + 'lippia': ['lippia', 'pilpai'], + 'lipsanotheca': ['lipsanotheca', 'sphacelation'], + 'lipstick': ['lickspit', 'lipstick'], + 'liquate': ['liquate', 'tequila'], + 'liquidate': ['liquidate', 'qualitied'], + 'lira': ['aril', 'lair', 'lari', 'liar', 'lira', 'rail', 'rial'], + 'lirate': ['lirate', 'retail', 'retial', 'tailer'], + 'liration': ['liration', 'litorina'], + 'lire': ['lier', 'lire', 'rile'], + 'lis': ['lis', 'sil'], + 'lisa': ['lasi', 'lias', 'lisa', 'sail', 'sial'], + 'lise': ['isle', 'lise', 'sile'], + 'lisere': ['lisere', 'resile'], + 'lisk': ['lisk', 'silk', 'skil'], + 'lisle': ['lisle', 'selli'], + 'lisp': ['lisp', 'slip'], + 'lisper': ['lisper', 'pliers', 'sirple', 'spiler'], + 'list': ['list', 'silt', 'slit'], + 'listable': ['bastille', 'listable'], + 'listen': ['enlist', 'listen', 'silent', 'tinsel'], + 'listener': ['enlister', 'esterlin', 'listener', 'relisten'], + 'lister': ['lister', 'relist'], + 'listera': ['aletris', 'alister', 'listera', 'realist', 'saltier'], + 'listerian': ['listerian', 'trisilane'], + 'listerine': ['listerine', 'resilient'], + 'listerize': ['listerize', 'sterilize'], + 'listing': ['listing', 'silting'], + 'listless': ['listless', 'slitless'], + 'lisuarte': ['auletris', 'lisuarte'], + 'lit': ['lit', 'til'], + 'litas': ['alist', 'litas', 'slait', 'talis'], + 'litchi': ['litchi', 'lithic'], + 'lite': ['lite', 'teil', 'teli', 'tile'], + 'liter': ['liter', 'tiler'], + 'literal': ['literal', 'tallier'], + 'literary': ['literary', 'trailery'], + 'literate': ['laterite', 'literate', 'teretial'], + 'literose': ['literose', 'roselite', 'tirolese'], + 'lith': ['hilt', 'lith'], + 'litharge': ['litharge', 'thirlage'], + 'lithe': ['leith', 'lithe'], + 'lithectomy': ['lithectomy', 'methylotic'], + 'lithic': ['litchi', 'lithic'], + 'litho': ['litho', 'thiol', 'tholi'], + 'lithochromography': ['chromolithography', 'lithochromography'], + 'lithocyst': ['cystolith', 'lithocyst'], + 'lithonephria': ['lithonephria', 'philotherian'], + 'lithonephrotomy': ['lithonephrotomy', 'nephrolithotomy'], + 'lithophane': ['anthophile', 'lithophane'], + 'lithophone': ['lithophone', 'thiophenol'], + 'lithophotography': ['lithophotography', 'photolithography'], + 'lithophysal': ['isophthalyl', 'lithophysal'], + 'lithopone': ['lithopone', 'phonolite'], + 'lithous': ['lithous', 'loutish'], + 'litigate': ['litigate', 'tagilite'], + 'litmus': ['litmus', 'tilmus'], + 'litorina': ['liration', 'litorina'], + 'litorinidae': ['idioretinal', 'litorinidae'], + 'litra': ['litra', 'trail', 'trial'], + 'litsea': ['isleta', 'litsea', 'salite', 'stelai'], + 'litster': ['litster', 'slitter', 'stilter', 'testril'], + 'litten': ['litten', 'tinlet'], + 'litter': ['litter', 'tilter', 'titler'], + 'littery': ['littery', 'tritely'], + 'littoral': ['littoral', 'tortilla'], + 'lituiform': ['lituiform', 'trifolium'], + 'litus': ['litus', 'sluit', 'tulsi'], + 'live': ['evil', 'levi', 'live', 'veil', 'vile', 'vlei'], + 'lived': ['devil', 'divel', 'lived'], + 'livedo': ['livedo', 'olived'], + 'liveliness': ['liveliness', 'villeiness'], + 'livelong': ['livelong', 'loveling'], + 'lively': ['evilly', 'lively', 'vilely'], + 'liven': ['levin', 'liven'], + 'liveness': ['evilness', 'liveness', 'veinless', 'vileness', 'vineless'], + 'liver': ['levir', 'liver', 'livre', 'rivel'], + 'livered': ['deliver', 'deviler', 'livered'], + 'livery': ['livery', 'verily'], + 'livier': ['livier', 'virile'], + 'livonian': ['livonian', 'violanin'], + 'livre': ['levir', 'liver', 'livre', 'rivel'], + 'liwan': ['inlaw', 'liwan'], + 'llandeilo': ['diallelon', 'llandeilo'], + 'llew': ['llew', 'well'], + 'lloyd': ['dolly', 'lloyd'], + 'loa': ['alo', 'lao', 'loa'], + 'loach': ['chola', 'loach', 'olcha'], + 'load': ['alod', 'dola', 'load', 'odal'], + 'loaden': ['enodal', 'loaden'], + 'loader': ['loader', 'ordeal', 'reload'], + 'loading': ['angloid', 'loading'], + 'loaf': ['foal', 'loaf', 'olaf'], + 'loam': ['loam', 'loma', 'malo', 'mola', 'olam'], + 'loaminess': ['loaminess', 'melanosis'], + 'loaming': ['almoign', 'loaming'], + 'loamy': ['amylo', 'loamy'], + 'loaner': ['lenora', 'loaner', 'orlean', 'reloan'], + 'loasa': ['alosa', 'loasa', 'oasal'], + 'loath': ['altho', 'lhota', 'loath'], + 'loather': ['loather', 'rathole'], + 'loathly': ['loathly', 'tallyho'], + 'lob': ['blo', 'lob'], + 'lobar': ['balor', 'bolar', 'boral', 'labor', 'lobar'], + 'lobate': ['lobate', 'oblate'], + 'lobated': ['bloated', 'lobated'], + 'lobately': ['lobately', 'oblately'], + 'lobation': ['boltonia', 'lobation', 'oblation'], + 'lobe': ['bleo', 'bole', 'lobe'], + 'lobed': ['bodle', 'boled', 'lobed'], + 'lobelet': ['bellote', 'lobelet'], + 'lobelia': ['bolelia', 'lobelia', 'obelial'], + 'lobing': ['globin', 'goblin', 'lobing'], + 'lobo': ['bolo', 'bool', 'lobo', 'obol'], + 'lobola': ['balolo', 'lobola'], + 'lobscourse': ['lobscourse', 'lobscouser'], + 'lobscouser': ['lobscourse', 'lobscouser'], + 'lobster': ['bolster', 'lobster'], + 'loca': ['alco', 'coal', 'cola', 'loca'], + 'local': ['callo', 'colla', 'local'], + 'locanda': ['acnodal', 'canadol', 'locanda'], + 'locarnite': ['alectrion', 'clarionet', 'crotaline', 'locarnite'], + 'locarnize': ['laconizer', 'locarnize'], + 'locarno': ['coronal', 'locarno'], + 'locate': ['acetol', 'colate', 'locate'], + 'location': ['colation', 'coontail', 'location'], + 'locational': ['allocation', 'locational'], + 'locator': ['crotalo', 'locator'], + 'loch': ['chol', 'loch'], + 'lochan': ['chalon', 'lochan'], + 'lochetic': ['helcotic', 'lochetic', 'ochletic'], + 'lochus': ['holcus', 'lochus', 'slouch'], + 'loci': ['clio', 'coil', 'coli', 'loci'], + 'lociation': ['coalition', 'lociation'], + 'lock': ['colk', 'lock'], + 'locker': ['locker', 'relock'], + 'lockpin': ['lockpin', 'pinlock'], + 'lockram': ['lockram', 'marlock'], + 'lockspit': ['lockspit', 'lopstick'], + 'lockup': ['lockup', 'uplock'], + 'loco': ['cool', 'loco'], + 'locoweed': ['coolweed', 'locoweed'], + 'locrian': ['carolin', 'clarion', 'colarin', 'locrian'], + 'locrine': ['creolin', 'licorne', 'locrine'], + 'loculate': ['allocute', 'loculate'], + 'loculation': ['allocution', 'loculation'], + 'locum': ['cumol', 'locum'], + 'locusta': ['costula', 'locusta', 'talcous'], + 'lod': ['dol', 'lod', 'old'], + 'lode': ['dole', 'elod', 'lode', 'odel'], + 'lodesman': ['dolesman', 'lodesman'], + 'lodgeman': ['angeldom', 'lodgeman'], + 'lodger': ['golder', 'lodger'], + 'lodging': ['godling', 'lodging'], + 'loess': ['loess', 'soles'], + 'loessic': ['loessic', 'ossicle'], + 'lof': ['flo', 'lof'], + 'loft': ['flot', 'loft'], + 'lofter': ['floret', 'forlet', 'lofter', 'torfel'], + 'lofty': ['lofty', 'oftly'], + 'log': ['gol', 'log'], + 'logania': ['alogian', 'logania'], + 'logarithm': ['algorithm', 'logarithm'], + 'logarithmic': ['algorithmic', 'logarithmic'], + 'loge': ['egol', 'goel', 'loge', 'ogle', 'oleg'], + 'logger': ['logger', 'roggle'], + 'logicalist': ['logicalist', 'logistical'], + 'logicist': ['logicist', 'logistic'], + 'login': ['lingo', 'login'], + 'logistic': ['logicist', 'logistic'], + 'logistical': ['logicalist', 'logistical'], + 'logistics': ['glossitic', 'logistics'], + 'logman': ['amlong', 'logman'], + 'logographic': ['graphologic', 'logographic'], + 'logographical': ['graphological', 'logographical'], + 'logography': ['graphology', 'logography'], + 'logoi': ['igloo', 'logoi'], + 'logometrical': ['logometrical', 'metrological'], + 'logos': ['gools', 'logos'], + 'logotypy': ['logotypy', 'typology'], + 'logria': ['gloria', 'larigo', 'logria'], + 'logy': ['gloy', 'logy'], + 'lohar': ['horal', 'lohar'], + 'loin': ['lino', 'lion', 'loin', 'noil'], + 'loined': ['doline', 'indole', 'leonid', 'loined', 'olenid'], + 'loir': ['loir', 'lori', 'roil'], + 'lois': ['lois', 'silo', 'siol', 'soil', 'soli'], + 'loiter': ['loiter', 'toiler', 'triole'], + 'loka': ['kalo', 'kola', 'loka'], + 'lokao': ['lokao', 'oolak'], + 'loke': ['koel', 'loke'], + 'loket': ['ketol', 'loket'], + 'lola': ['lalo', 'lola', 'olla'], + 'loma': ['loam', 'loma', 'malo', 'mola', 'olam'], + 'lomatine': ['lomatine', 'tolamine'], + 'lombardian': ['laminboard', 'lombardian'], + 'lomboy': ['bloomy', 'lomboy'], + 'loment': ['loment', 'melton', 'molten'], + 'lomentaria': ['ameliorant', 'lomentaria'], + 'lomita': ['lomita', 'tomial'], + 'lone': ['elon', 'enol', 'leno', 'leon', 'lone', 'noel'], + 'longa': ['along', 'gonal', 'lango', 'longa', 'nogal'], + 'longanimous': ['longanimous', 'longimanous'], + 'longbeard': ['boglander', 'longbeard'], + 'longear': ['argenol', 'longear'], + 'longhead': ['headlong', 'longhead'], + 'longimanous': ['longanimous', 'longimanous'], + 'longimetry': ['longimetry', 'mongrelity'], + 'longmouthed': ['goldenmouth', 'longmouthed'], + 'longue': ['longue', 'lounge'], + 'lonicera': ['acrolein', + 'arecolin', + 'caroline', + 'colinear', + 'cornelia', + 'creolian', + 'lonicera'], + 'lontar': ['latron', 'lontar', 'tornal'], + 'looby': ['booly', 'looby'], + 'lood': ['dool', 'lood'], + 'loof': ['fool', 'loof', 'olof'], + 'look': ['kolo', 'look'], + 'looker': ['looker', 'relook'], + 'lookout': ['lookout', 'outlook'], + 'loom': ['loom', 'mool'], + 'loon': ['loon', 'nolo'], + 'loop': ['loop', 'polo', 'pool'], + 'looper': ['looper', 'pooler'], + 'loopist': ['loopist', 'poloist', 'topsoil'], + 'loopy': ['loopy', 'pooly'], + 'loosing': ['loosing', 'sinolog'], + 'loot': ['loot', 'tool'], + 'looter': ['looter', 'retool', 'rootle', 'tooler'], + 'lootie': ['lootie', 'oolite'], + 'lop': ['lop', 'pol'], + 'lope': ['lope', 'olpe', 'pole'], + 'loper': ['loper', 'poler'], + 'lopezia': ['epizoal', 'lopezia', 'opalize'], + 'lophine': ['lophine', 'pinhole'], + 'lophocomi': ['homopolic', 'lophocomi'], + 'loppet': ['loppet', 'topple'], + 'loppy': ['loppy', 'polyp'], + 'lopstick': ['lockspit', 'lopstick'], + 'loquacious': ['aquicolous', 'loquacious'], + 'lora': ['lora', 'oral'], + 'lorandite': ['lorandite', 'rodential'], + 'lorate': ['elator', 'lorate'], + 'lorcha': ['choral', 'lorcha'], + 'lordly': ['drolly', 'lordly'], + 'lore': ['lore', 'orle', 'role'], + 'lored': ['lored', 'older'], + 'loren': ['enrol', 'loren'], + 'lori': ['loir', 'lori', 'roil'], + 'lorica': ['caroli', 'corial', 'lorica'], + 'loricate': ['calorite', 'erotical', 'loricate'], + 'loricati': ['clitoria', 'loricati'], + 'lorien': ['elinor', 'lienor', 'lorien', 'noiler'], + 'loro': ['loro', 'olor', 'orlo', 'rool'], + 'lose': ['lose', 'sloe', 'sole'], + 'loser': ['loser', 'orsel', 'rosel', 'soler'], + 'lost': ['lost', 'lots', 'slot'], + 'lot': ['lot', 'tol'], + 'lota': ['alto', 'lota'], + 'lotase': ['lotase', 'osteal', 'solate', 'stolae', 'talose'], + 'lote': ['leto', 'lote', 'tole'], + 'lotic': ['cloit', 'lotic'], + 'lotrite': ['lotrite', 'tortile', 'triolet'], + 'lots': ['lost', 'lots', 'slot'], + 'lotta': ['lotta', 'total'], + 'lotter': ['lotter', 'rottle', 'tolter'], + 'lottie': ['lottie', 'toilet', 'tolite'], + 'lou': ['lou', 'luo'], + 'loud': ['loud', 'ludo'], + 'louden': ['louden', 'nodule'], + 'lough': ['ghoul', 'lough'], + 'lounder': ['durenol', 'lounder', 'roundel'], + 'lounge': ['longue', 'lounge'], + 'loupe': ['epulo', 'loupe'], + 'lourdy': ['dourly', 'lourdy'], + 'louse': ['eusol', 'louse'], + 'lousy': ['lousy', 'souly'], + 'lout': ['lout', 'tolu'], + 'louter': ['elutor', 'louter', 'outler'], + 'loutish': ['lithous', 'loutish'], + 'louty': ['louty', 'outly'], + 'louvar': ['louvar', 'ovular'], + 'louver': ['louver', 'louvre'], + 'louvre': ['louver', 'louvre'], + 'lovable': ['lovable', 'volable'], + 'lovage': ['lovage', 'volage'], + 'love': ['levo', 'love', 'velo', 'vole'], + 'loveling': ['livelong', 'loveling'], + 'lovely': ['lovely', 'volley'], + 'lovering': ['lovering', 'overling'], + 'low': ['low', 'lwo', 'owl'], + 'lowa': ['alow', 'awol', 'lowa'], + 'lowder': ['lowder', 'weldor', 'wordle'], + 'lower': ['lower', 'owler', 'rowel'], + 'lowerer': ['lowerer', 'relower'], + 'lowery': ['lowery', 'owlery', 'rowley', 'yowler'], + 'lowish': ['lowish', 'owlish'], + 'lowishly': ['lowishly', 'owlishly', 'sillyhow'], + 'lowishness': ['lowishness', 'owlishness'], + 'lowy': ['lowy', 'owly', 'yowl'], + 'loyal': ['alloy', 'loyal'], + 'loyalism': ['loyalism', 'lysiloma'], + 'loyd': ['loyd', 'odyl'], + 'luba': ['balu', 'baul', 'bual', 'luba'], + 'lubber': ['burble', 'lubber', 'rubble'], + 'lubberland': ['landlubber', 'lubberland'], + 'lube': ['blue', 'lube'], + 'lucan': ['lucan', 'nucal'], + 'lucania': ['lucania', 'luciana'], + 'lucanid': ['dulcian', 'incudal', 'lucanid', 'lucinda'], + 'lucanidae': ['leucadian', 'lucanidae'], + 'lucarne': ['crenula', 'lucarne', 'nuclear', 'unclear'], + 'lucban': ['buncal', 'lucban'], + 'luce': ['clue', 'luce'], + 'luceres': ['luceres', 'recluse'], + 'lucern': ['encurl', 'lucern'], + 'lucernal': ['lucernal', 'nucellar', 'uncellar'], + 'lucet': ['culet', 'lucet'], + 'lucia': ['aulic', 'lucia'], + 'lucian': ['cunila', 'lucian', 'lucina', 'uncial'], + 'luciana': ['lucania', 'luciana'], + 'lucifer': ['ferulic', 'lucifer'], + 'lucigen': ['glucine', 'lucigen'], + 'lucina': ['cunila', 'lucian', 'lucina', 'uncial'], + 'lucinda': ['dulcian', 'incudal', 'lucanid', 'lucinda'], + 'lucinoid': ['lucinoid', 'oculinid'], + 'lucite': ['lucite', 'luetic', 'uletic'], + 'lucrative': ['lucrative', 'revictual', 'victualer'], + 'lucre': ['cruel', 'lucre', 'ulcer'], + 'lucretia': ['arculite', 'cutleria', 'lucretia', 'reticula', 'treculia'], + 'lucretian': ['centurial', 'lucretian', 'ultranice'], + 'luctiferous': ['fruticulose', 'luctiferous'], + 'lucubrate': ['lucubrate', 'tubercula'], + 'ludden': ['ludden', 'nuddle'], + 'luddite': ['diluted', 'luddite'], + 'ludian': ['dualin', 'ludian', 'unlaid'], + 'ludibry': ['buirdly', 'ludibry'], + 'ludicroserious': ['ludicroserious', 'serioludicrous'], + 'ludo': ['loud', 'ludo'], + 'lue': ['leu', 'lue', 'ule'], + 'lues': ['lues', 'slue'], + 'luetic': ['lucite', 'luetic', 'uletic'], + 'lug': ['gul', 'lug'], + 'luge': ['glue', 'gule', 'luge'], + 'luger': ['gluer', 'gruel', 'luger'], + 'lugger': ['gurgle', 'lugger', 'ruggle'], + 'lugnas': ['lugnas', 'salung'], + 'lugsome': ['glumose', 'lugsome'], + 'luian': ['inula', 'luian', 'uinal'], + 'luiseno': ['elusion', 'luiseno'], + 'luite': ['luite', 'utile'], + 'lukas': ['klaus', 'lukas', 'sulka'], + 'luke': ['leuk', 'luke'], + 'lula': ['lula', 'ulla'], + 'lulab': ['bulla', 'lulab'], + 'lumbar': ['brumal', 'labrum', 'lumbar', 'umbral'], + 'lumber': ['lumber', 'rumble', 'umbrel'], + 'lumbosacral': ['lumbosacral', 'sacrolumbal'], + 'lumine': ['lumine', 'unlime'], + 'lump': ['lump', 'plum'], + 'lumper': ['lumper', 'plumer', 'replum', 'rumple'], + 'lumpet': ['lumpet', 'plumet'], + 'lumpiness': ['lumpiness', 'pluminess'], + 'lumpy': ['lumpy', 'plumy'], + 'luna': ['laun', 'luna', 'ulna', 'unal'], + 'lunacy': ['lunacy', 'unclay'], + 'lunar': ['lunar', 'ulnar', 'urnal'], + 'lunare': ['lunare', 'neural', 'ulnare', 'unreal'], + 'lunaria': ['lunaria', 'ulnaria', 'uralian'], + 'lunary': ['lunary', 'uranyl'], + 'lunatic': ['calinut', 'lunatic'], + 'lunation': ['lunation', 'ultonian'], + 'lunda': ['dunal', 'laund', 'lunda', 'ulnad'], + 'lung': ['gunl', 'lung'], + 'lunge': ['leung', 'lunge'], + 'lunged': ['gulden', 'lunged'], + 'lungfish': ['flushing', 'lungfish'], + 'lungsick': ['lungsick', 'suckling'], + 'lunisolar': ['lunisolar', 'solilunar'], + 'luo': ['lou', 'luo'], + 'lupe': ['lupe', 'pelu', 'peul', 'pule'], + 'luperci': ['luperci', 'pleuric'], + 'lupicide': ['lupicide', 'pediculi', 'pulicide'], + 'lupinaster': ['lupinaster', 'palustrine'], + 'lupine': ['lupine', 'unpile', 'upline'], + 'lupinus': ['lupinus', 'pinulus'], + 'lupis': ['lupis', 'pilus'], + 'lupous': ['lupous', 'opulus'], + 'lura': ['alur', 'laur', 'lura', 'raul', 'ural'], + 'lurch': ['churl', 'lurch'], + 'lure': ['lure', 'rule'], + 'lurer': ['lurer', 'ruler'], + 'lurg': ['gurl', 'lurg'], + 'luringly': ['luringly', 'rulingly'], + 'luscinia': ['luscinia', 'siculian'], + 'lush': ['lush', 'shlu', 'shul'], + 'lusher': ['lusher', 'shuler'], + 'lushly': ['hyllus', 'lushly'], + 'lushness': ['lushness', 'shunless'], + 'lusian': ['insula', 'lanius', 'lusian'], + 'lusk': ['lusk', 'sulk'], + 'lusky': ['lusky', 'sulky'], + 'lusory': ['lusory', 'sourly'], + 'lust': ['lust', 'slut'], + 'luster': ['luster', 'result', 'rustle', 'sutler', 'ulster'], + 'lusterless': ['lusterless', 'lustreless', 'resultless'], + 'lustihead': ['hastilude', 'lustihead'], + 'lustreless': ['lusterless', 'lustreless', 'resultless'], + 'lustrine': ['insulter', 'lustrine', 'reinsult'], + 'lustring': ['lustring', 'rustling'], + 'lusty': ['lusty', 'tylus'], + 'lutaceous': ['cautelous', 'lutaceous'], + 'lutany': ['auntly', 'lutany'], + 'lutayo': ['layout', 'lutayo', 'outlay'], + 'lute': ['lute', 'tule'], + 'luteal': ['alulet', 'luteal'], + 'lutecia': ['aleutic', 'auletic', 'caulite', 'lutecia'], + 'lutecium': ['cumulite', 'lutecium'], + 'lutein': ['lutein', 'untile'], + 'lutfisk': ['kistful', 'lutfisk'], + 'luther': ['hurtle', 'luther'], + 'lutheran': ['lutheran', 'unhalter'], + 'lutianoid': ['lutianoid', 'nautiloid'], + 'lutianus': ['lutianus', 'nautilus', 'ustulina'], + 'luting': ['glutin', 'luting', 'ungilt'], + 'lutose': ['lutose', 'solute', 'tousle'], + 'lutra': ['lutra', 'ultra'], + 'lutrinae': ['lutrinae', 'retinula', 'rutelian', 'tenurial'], + 'luxe': ['luxe', 'ulex'], + 'lwo': ['low', 'lwo', 'owl'], + 'lyam': ['amyl', 'lyam', 'myal'], + 'lyard': ['daryl', 'lardy', 'lyard'], + 'lyas': ['lyas', 'slay'], + 'lycaenid': ['adenylic', 'lycaenid'], + 'lyceum': ['cymule', 'lyceum'], + 'lycopodium': ['lycopodium', 'polycodium'], + 'lyctidae': ['diacetyl', 'lyctidae'], + 'lyddite': ['lyddite', 'tiddley'], + 'lydia': ['daily', 'lydia'], + 'lydite': ['idlety', 'lydite', 'tidely', 'tidley'], + 'lye': ['ley', 'lye'], + 'lying': ['lingy', 'lying'], + 'lymnaeid': ['lymnaeid', 'maidenly', 'medianly'], + 'lymphadenia': ['lymphadenia', 'nymphalidae'], + 'lymphectasia': ['lymphectasia', 'metaphysical'], + 'lymphopenia': ['lymphopenia', 'polyphemian'], + 'lynne': ['lenny', 'lynne'], + 'lyon': ['lyon', 'only'], + 'lyophobe': ['hypobole', 'lyophobe'], + 'lyra': ['aryl', 'lyra', 'ryal', 'yarl'], + 'lyraid': ['aridly', 'lyraid'], + 'lyrate': ['lyrate', 'raylet', 'realty', 'telary'], + 'lyre': ['lyre', 'rely'], + 'lyric': ['cyril', 'lyric'], + 'lyrical': ['cyrilla', 'lyrical'], + 'lyrid': ['idryl', 'lyrid'], + 'lys': ['lys', 'sly'], + 'lysander': ['lysander', 'synedral'], + 'lysate': ['alytes', 'astely', 'lysate', 'stealy'], + 'lyse': ['lyse', 'sley'], + 'lysiloma': ['loyalism', 'lysiloma'], + 'lysine': ['linsey', 'lysine'], + 'lysogenetic': ['cleistogeny', 'lysogenetic'], + 'lysogenic': ['glycosine', 'lysogenic'], + 'lyssic': ['clysis', 'lyssic'], + 'lyterian': ['interlay', 'lyterian'], + 'lyxose': ['lyxose', 'xylose'], + 'ma': ['am', 'ma'], + 'maam': ['amma', 'maam'], + 'mab': ['bam', 'mab'], + 'maba': ['amba', 'maba'], + 'mabel': ['amble', 'belam', 'blame', 'mabel'], + 'mabi': ['iamb', 'mabi'], + 'mabolo': ['abloom', 'mabolo'], + 'mac': ['cam', 'mac'], + 'macaca': ['camaca', 'macaca'], + 'macaco': ['cocama', 'macaco'], + 'macaglia': ['almaciga', 'macaglia'], + 'macan': ['caman', 'macan'], + 'macanese': ['macanese', 'maecenas'], + 'macao': ['acoma', 'macao'], + 'macarism': ['macarism', 'marasmic'], + 'macaroni': ['armonica', 'macaroni', 'marocain'], + 'macaronic': ['carcinoma', 'macaronic'], + 'mace': ['acme', 'came', 'mace'], + 'macedon': ['conamed', 'macedon'], + 'macedonian': ['caedmonian', 'macedonian'], + 'macedonic': ['caedmonic', 'macedonic'], + 'macer': ['cream', 'macer'], + 'macerate': ['camerate', 'macerate', 'racemate'], + 'maceration': ['aeromantic', 'cameration', 'maceration', 'racemation'], + 'machar': ['chamar', 'machar'], + 'machi': ['chiam', 'machi', 'micah'], + 'machilis': ['chiliasm', 'hilasmic', 'machilis'], + 'machinator': ['achromatin', 'chariotman', 'machinator'], + 'machine': ['chimane', 'machine'], + 'machinery': ['hemicrany', 'machinery'], + 'macies': ['camise', 'macies'], + 'macigno': ['coaming', 'macigno'], + 'macilency': ['cyclamine', 'macilency'], + 'macle': ['camel', 'clame', 'cleam', 'macle'], + 'maclura': ['maclura', 'macular'], + 'maco': ['coma', 'maco'], + 'macon': ['coman', 'macon', 'manoc'], + 'maconite': ['coinmate', 'maconite'], + 'macro': ['carom', 'coram', 'macro', 'marco'], + 'macrobian': ['carbamino', 'macrobian'], + 'macromazia': ['macromazia', 'macrozamia'], + 'macrophage': ['cameograph', 'macrophage'], + 'macrophotograph': ['macrophotograph', 'photomacrograph'], + 'macrotia': ['aromatic', 'macrotia'], + 'macrotin': ['macrotin', 'romantic'], + 'macrourid': ['macrourid', 'macruroid'], + 'macrourus': ['macrourus', 'macrurous'], + 'macrozamia': ['macromazia', 'macrozamia'], + 'macruroid': ['macrourid', 'macruroid'], + 'macrurous': ['macrourus', 'macrurous'], + 'mactra': ['mactra', 'tarmac'], + 'macular': ['maclura', 'macular'], + 'macule': ['almuce', 'caelum', 'macule'], + 'maculose': ['maculose', 'somacule'], + 'mad': ['dam', 'mad'], + 'madden': ['damned', 'demand', 'madden'], + 'maddening': ['demanding', 'maddening'], + 'maddeningly': ['demandingly', 'maddeningly'], + 'madder': ['dermad', 'madder'], + 'made': ['dame', 'made', 'mead'], + 'madeira': ['adermia', 'madeira'], + 'madeiran': ['madeiran', 'marinade'], + 'madeline': ['endemial', 'madeline'], + 'madi': ['admi', 'amid', 'madi', 'maid'], + 'madia': ['amadi', 'damia', 'madia', 'maida'], + 'madiga': ['agamid', 'madiga'], + 'madman': ['madman', 'nammad'], + 'madnep': ['dampen', 'madnep'], + 'madrid': ['madrid', 'riddam'], + 'madrier': ['admirer', 'madrier', 'married'], + 'madrilene': ['landimere', 'madrilene'], + 'madrona': ['anadrom', 'madrona', 'mandora', 'monarda', 'roadman'], + 'madship': ['dampish', 'madship', 'phasmid'], + 'madurese': ['madurese', 'measured'], + 'mae': ['ame', 'mae'], + 'maecenas': ['macanese', 'maecenas'], + 'maenad': ['anadem', 'maenad'], + 'maenadism': ['maenadism', 'mandaeism'], + 'maeonian': ['enomania', 'maeonian'], + 'maestri': ['artemis', 'maestri', 'misrate'], + 'maestro': ['maestro', 'tarsome'], + 'mag': ['gam', 'mag'], + 'magadis': ['gamasid', 'magadis'], + 'magani': ['angami', 'magani', 'magian'], + 'magas': ['agsam', 'magas'], + 'mage': ['egma', 'game', 'mage'], + 'magenta': ['gateman', 'magenta', 'magnate', 'magneta'], + 'magian': ['angami', 'magani', 'magian'], + 'magic': ['gamic', 'magic'], + 'magister': ['gemarist', 'magister', 'sterigma'], + 'magistrate': ['magistrate', 'sterigmata'], + 'magma': ['gamma', 'magma'], + 'magnate': ['gateman', 'magenta', 'magnate', 'magneta'], + 'magnes': ['magnes', 'semang'], + 'magneta': ['gateman', 'magenta', 'magnate', 'magneta'], + 'magnetist': ['agistment', 'magnetist'], + 'magneto': ['geomant', 'magneto', 'megaton', 'montage'], + 'magnetod': ['magnetod', 'megadont'], + 'magnetoelectric': ['electromagnetic', 'magnetoelectric'], + 'magnetoelectrical': ['electromagnetical', 'magnetoelectrical'], + 'magnolia': ['algomian', 'magnolia'], + 'magnus': ['magnus', 'musang'], + 'magpie': ['magpie', 'piemag'], + 'magyar': ['magyar', 'margay'], + 'mah': ['ham', 'mah'], + 'maha': ['amah', 'maha'], + 'mahar': ['amhar', 'mahar', 'mahra'], + 'maharani': ['amiranha', 'maharani'], + 'mahdism': ['dammish', 'mahdism'], + 'mahdist': ['adsmith', 'mahdist'], + 'mahi': ['hami', 'hima', 'mahi'], + 'mahican': ['chamian', 'mahican'], + 'mahogany': ['hogmanay', 'mahogany'], + 'maholi': ['holmia', 'maholi'], + 'maholtine': ['hematolin', 'maholtine'], + 'mahori': ['homrai', 'mahori', 'mohair'], + 'mahra': ['amhar', 'mahar', 'mahra'], + 'mahran': ['amhran', 'harman', 'mahran'], + 'mahri': ['hiram', 'ihram', 'mahri'], + 'maia': ['amia', 'maia'], + 'maid': ['admi', 'amid', 'madi', 'maid'], + 'maida': ['amadi', 'damia', 'madia', 'maida'], + 'maiden': ['daimen', 'damine', 'maiden', 'median', 'medina'], + 'maidenism': ['maidenism', 'medianism'], + 'maidenly': ['lymnaeid', 'maidenly', 'medianly'], + 'maidish': ['hasidim', 'maidish'], + 'maidism': ['amidism', 'maidism'], + 'maigre': ['imager', 'maigre', 'margie', 'mirage'], + 'maiidae': ['amiidae', 'maiidae'], + 'mail': ['amil', 'amli', 'lima', 'mail', 'mali', 'mila'], + 'mailed': ['aldime', 'mailed', 'medial'], + 'mailer': ['mailer', 'remail'], + 'mailie': ['emilia', 'mailie'], + 'maim': ['ammi', 'imam', 'maim', 'mima'], + 'main': ['amin', 'main', 'mani', 'mian', 'mina', 'naim'], + 'maine': ['amine', 'anime', 'maine', 'manei'], + 'mainly': ['amylin', 'mainly'], + 'mainour': ['mainour', 'uramino'], + 'mainpast': ['mainpast', 'mantispa', 'panamist', 'stampian'], + 'mainprise': ['mainprise', 'presimian'], + 'mains': ['mains', 'manis'], + 'maint': ['maint', 'matin'], + 'maintain': ['amanitin', 'maintain'], + 'maintainer': ['antimerina', 'maintainer', 'remaintain'], + 'maintop': ['maintop', 'ptomain', 'tampion', 'timpano'], + 'maioid': ['daimio', 'maioid'], + 'maioidean': ['anomiidae', 'maioidean'], + 'maire': ['aimer', 'maire', 'marie', 'ramie'], + 'maja': ['jama', 'maja'], + 'majoon': ['majoon', 'moonja'], + 'major': ['jarmo', 'major'], + 'makah': ['hakam', 'makah'], + 'makassar': ['makassar', 'samskara'], + 'make': ['kame', 'make', 'meak'], + 'maker': ['maker', 'marek', 'merak'], + 'maki': ['akim', 'maki'], + 'mako': ['amok', 'mako'], + 'mal': ['lam', 'mal'], + 'mala': ['alma', 'amla', 'lama', 'mala'], + 'malacologist': ['malacologist', 'mastological'], + 'malaga': ['agalma', 'malaga'], + 'malagma': ['amalgam', 'malagma'], + 'malakin': ['alkamin', 'malakin'], + 'malanga': ['malanga', 'nagmaal'], + 'malapert': ['armplate', 'malapert'], + 'malapi': ['impala', 'malapi'], + 'malar': ['alarm', 'malar', 'maral', 'marla', 'ramal'], + 'malarin': ['lairman', 'laminar', 'malarin', 'railman'], + 'malate': ['malate', 'meatal', 'tamale'], + 'malcreated': ['cradlemate', 'malcreated'], + 'maldonite': ['antimodel', 'maldonite', 'monilated'], + 'male': ['alem', 'alme', 'lame', 'leam', 'male', 'meal', 'mela'], + 'maleficiation': ['amelification', 'maleficiation'], + 'maleic': ['maleic', 'malice', 'melica'], + 'maleinoid': ['alimonied', 'maleinoid'], + 'malella': ['lamella', 'malella', 'malleal'], + 'maleness': ['lameness', 'maleness', 'maneless', 'nameless'], + 'malengine': ['enameling', 'malengine', 'meningeal'], + 'maleo': ['amole', 'maleo'], + 'malfed': ['flamed', 'malfed'], + 'malhonest': ['malhonest', 'mashelton'], + 'mali': ['amil', 'amli', 'lima', 'mail', 'mali', 'mila'], + 'malic': ['claim', 'clima', 'malic'], + 'malice': ['maleic', 'malice', 'melica'], + 'malicho': ['chiloma', 'malicho'], + 'maligner': ['germinal', 'maligner', 'malinger'], + 'malikana': ['kalamian', 'malikana'], + 'maline': ['limean', 'maline', 'melian', 'menial'], + 'malines': ['malines', 'salmine', 'selamin', 'seminal'], + 'malinger': ['germinal', 'maligner', 'malinger'], + 'malison': ['malison', 'manolis', 'osmanli', 'somnial'], + 'malladrite': ['armillated', 'malladrite', 'mallardite'], + 'mallardite': ['armillated', 'malladrite', 'mallardite'], + 'malleal': ['lamella', 'malella', 'malleal'], + 'mallein': ['mallein', 'manille'], + 'malleoincudal': ['incudomalleal', 'malleoincudal'], + 'malleus': ['amellus', 'malleus'], + 'malmaison': ['anomalism', 'malmaison'], + 'malmy': ['lammy', 'malmy'], + 'malo': ['loam', 'loma', 'malo', 'mola', 'olam'], + 'malonic': ['limacon', 'malonic'], + 'malonyl': ['allonym', 'malonyl'], + 'malope': ['aplome', 'malope'], + 'malpoise': ['malpoise', 'semiopal'], + 'malposed': ['malposed', 'plasmode'], + 'maltase': ['asmalte', 'maltase'], + 'malter': ['armlet', 'malter', 'martel'], + 'maltese': ['maltese', 'seamlet'], + 'malthe': ['hamlet', 'malthe'], + 'malurinae': ['malurinae', 'melanuria'], + 'malurine': ['lemurian', 'malurine', 'rumelian'], + 'malurus': ['malurus', 'ramulus'], + 'malus': ['lamus', 'malus', 'musal', 'slaum'], + 'mamers': ['mamers', 'sammer'], + 'mamo': ['ammo', 'mamo'], + 'man': ['man', 'nam'], + 'mana': ['anam', 'mana', 'naam', 'nama'], + 'manacle': ['laceman', 'manacle'], + 'manacus': ['manacus', 'samucan'], + 'manage': ['agname', 'manage'], + 'manager': ['gearman', 'manager'], + 'manal': ['alman', 'lamna', 'manal'], + 'manas': ['manas', 'saman'], + 'manatee': ['emanate', 'manatee'], + 'manatine': ['annamite', 'manatine'], + 'manbird': ['birdman', 'manbird'], + 'manchester': ['manchester', 'searchment'], + 'mand': ['damn', 'mand'], + 'mandaeism': ['maenadism', 'mandaeism'], + 'mandaite': ['animated', 'mandaite', 'mantidae'], + 'mandarin': ['drainman', 'mandarin'], + 'mandation': ['damnation', 'mandation'], + 'mandatory': ['damnatory', 'mandatory'], + 'mande': ['amend', 'mande', 'maned'], + 'mandelate': ['aldeament', 'mandelate'], + 'mandil': ['lamnid', 'mandil'], + 'mandola': ['mandola', 'odalman'], + 'mandora': ['anadrom', 'madrona', 'mandora', 'monarda', 'roadman'], + 'mandra': ['mandra', 'radman'], + 'mandrill': ['drillman', 'mandrill'], + 'mandyas': ['daysman', 'mandyas'], + 'mane': ['amen', 'enam', 'mane', 'mean', 'name', 'nema'], + 'maned': ['amend', 'mande', 'maned'], + 'manege': ['gamene', 'manege', 'menage'], + 'manei': ['amine', 'anime', 'maine', 'manei'], + 'maneless': ['lameness', 'maleness', 'maneless', 'nameless'], + 'manent': ['manent', 'netman'], + 'manerial': ['almerian', 'manerial'], + 'manes': ['manes', 'manse', 'mensa', 'samen', 'senam'], + 'maness': ['enmass', 'maness', 'messan'], + 'manettia': ['antietam', 'manettia'], + 'maney': ['maney', 'yamen'], + 'manga': ['amang', 'ganam', 'manga'], + 'mangar': ['amgarn', 'mangar', 'marang', 'ragman'], + 'mangel': ['legman', 'mangel', 'mangle'], + 'mangelin': ['mangelin', 'nameling'], + 'manger': ['engram', 'german', 'manger'], + 'mangerite': ['germanite', 'germinate', 'gramenite', 'mangerite'], + 'mangi': ['gamin', 'mangi'], + 'mangle': ['legman', 'mangel', 'mangle'], + 'mango': ['among', 'mango'], + 'mangrass': ['grassman', 'mangrass'], + 'mangrate': ['grateman', 'mangrate', 'mentagra', 'targeman'], + 'mangue': ['mangue', 'maunge'], + 'manhead': ['headman', 'manhead'], + 'manhole': ['holeman', 'manhole'], + 'manhood': ['dhamnoo', 'hoodman', 'manhood'], + 'mani': ['amin', 'main', 'mani', 'mian', 'mina', 'naim'], + 'mania': ['amain', 'amani', 'amnia', 'anima', 'mania'], + 'maniable': ['animable', 'maniable'], + 'maniac': ['amniac', 'caiman', 'maniac'], + 'manic': ['amnic', 'manic'], + 'manid': ['dimna', 'manid'], + 'manidae': ['adamine', 'manidae'], + 'manify': ['infamy', 'manify'], + 'manila': ['almain', 'animal', 'lamina', 'manila'], + 'manilla': ['alnilam', 'manilla'], + 'manille': ['mallein', 'manille'], + 'manioc': ['camion', 'conima', 'manioc', 'monica'], + 'maniple': ['impanel', 'maniple'], + 'manipuri': ['manipuri', 'unimpair'], + 'manis': ['mains', 'manis'], + 'manist': ['manist', 'mantis', 'matins', 'stamin'], + 'manistic': ['actinism', 'manistic'], + 'manito': ['atimon', 'manito', 'montia'], + 'maniu': ['maniu', 'munia', 'unami'], + 'manius': ['animus', 'anisum', 'anusim', 'manius'], + 'maniva': ['maniva', 'vimana'], + 'manlet': ['lament', 'manlet', 'mantel', 'mantle', 'mental'], + 'manna': ['annam', 'manna'], + 'mannite': ['mannite', 'tineman'], + 'mannonic': ['cinnamon', 'mannonic'], + 'mano': ['mano', 'moan', 'mona', 'noam', 'noma', 'oman'], + 'manoc': ['coman', 'macon', 'manoc'], + 'manolis': ['malison', 'manolis', 'osmanli', 'somnial'], + 'manometrical': ['commentarial', 'manometrical'], + 'manometry': ['manometry', 'momentary'], + 'manor': ['manor', 'moran', 'norma', 'ramon', 'roman'], + 'manorial': ['manorial', 'morainal'], + 'manorship': ['manorship', 'orphanism'], + 'manoscope': ['manoscope', 'moonscape'], + 'manred': ['damner', 'manred', 'randem', 'remand'], + 'manrent': ['manrent', 'remnant'], + 'manrope': ['manrope', 'ropeman'], + 'manse': ['manes', 'manse', 'mensa', 'samen', 'senam'], + 'manship': ['manship', 'shipman'], + 'mansion': ['mansion', 'onanism'], + 'mansioneer': ['emersonian', 'mansioneer'], + 'manslaughter': ['manslaughter', 'slaughterman'], + 'manso': ['manso', 'mason', 'monas'], + 'manta': ['atman', 'manta'], + 'mantel': ['lament', 'manlet', 'mantel', 'mantle', 'mental'], + 'manteline': ['lineament', 'manteline'], + 'manter': ['manter', 'marten', 'rament'], + 'mantes': ['mantes', 'stamen'], + 'manticore': ['cremation', 'manticore'], + 'mantidae': ['animated', 'mandaite', 'mantidae'], + 'mantis': ['manist', 'mantis', 'matins', 'stamin'], + 'mantispa': ['mainpast', 'mantispa', 'panamist', 'stampian'], + 'mantissa': ['mantissa', 'satanism'], + 'mantle': ['lament', 'manlet', 'mantel', 'mantle', 'mental'], + 'manto': ['manto', 'toman'], + 'mantodea': ['mantodea', 'nematoda'], + 'mantoidea': ['diatomean', 'mantoidea'], + 'mantra': ['mantra', 'tarman'], + 'mantrap': ['mantrap', 'rampant'], + 'mantua': ['anatum', 'mantua', 'tamanu'], + 'manual': ['alumna', 'manual'], + 'manualism': ['manualism', 'musalmani'], + 'manualiter': ['manualiter', 'unmaterial'], + 'manuel': ['manuel', 'unlame'], + 'manul': ['lanum', 'manul'], + 'manuma': ['amunam', 'manuma'], + 'manure': ['manure', 'menura'], + 'manward': ['manward', 'wardman'], + 'manwards': ['manwards', 'wardsman'], + 'manway': ['manway', 'wayman'], + 'manwise': ['manwise', 'wiseman'], + 'many': ['many', 'myna'], + 'mao': ['mao', 'oam'], + 'maori': ['maori', 'mario', 'moira'], + 'map': ['map', 'pam'], + 'mapach': ['champa', 'mapach'], + 'maple': ['ample', 'maple'], + 'mapper': ['mapper', 'pamper', 'pampre'], + 'mar': ['arm', 'mar', 'ram'], + 'mara': ['amar', 'amra', 'mara', 'rama'], + 'marabout': ['marabout', 'marabuto', 'tamboura'], + 'marabuto': ['marabout', 'marabuto', 'tamboura'], + 'maraca': ['acamar', 'camara', 'maraca'], + 'maral': ['alarm', 'malar', 'maral', 'marla', 'ramal'], + 'marang': ['amgarn', 'mangar', 'marang', 'ragman'], + 'mararie': ['armeria', 'mararie'], + 'marasca': ['marasca', 'mascara'], + 'maraschino': ['anachorism', 'chorasmian', 'maraschino'], + 'marasmic': ['macarism', 'marasmic'], + 'marbelize': ['marbelize', 'marbleize'], + 'marble': ['ambler', 'blamer', 'lamber', 'marble', 'ramble'], + 'marbleize': ['marbelize', 'marbleize'], + 'marbler': ['marbler', 'rambler'], + 'marbling': ['marbling', 'rambling'], + 'marc': ['cram', 'marc'], + 'marcan': ['carman', 'marcan'], + 'marcel': ['calmer', 'carmel', 'clamer', 'marcel', 'mercal'], + 'marcescent': ['marcescent', 'scarcement'], + 'march': ['charm', 'march'], + 'marcher': ['charmer', 'marcher', 'remarch'], + 'marchite': ['athermic', 'marchite', 'rhematic'], + 'marchpane': ['marchpane', 'preachman'], + 'marci': ['marci', 'mirac'], + 'marcionist': ['marcionist', 'romanistic'], + 'marcionite': ['marcionite', 'microtinae', 'remication'], + 'marco': ['carom', 'coram', 'macro', 'marco'], + 'marconi': ['amicron', 'marconi', 'minorca', 'romanic'], + 'mare': ['erma', 'mare', 'rame', 'ream'], + 'mareca': ['acream', 'camera', 'mareca'], + 'marek': ['maker', 'marek', 'merak'], + 'marengo': ['marengo', 'megaron'], + 'mareotid': ['mareotid', 'mediator'], + 'marfik': ['marfik', 'mirfak'], + 'marfire': ['firearm', 'marfire'], + 'margay': ['magyar', 'margay'], + 'marge': ['grame', 'marge', 'regma'], + 'margeline': ['margeline', 'regimenal'], + 'margent': ['garment', 'margent'], + 'margie': ['imager', 'maigre', 'margie', 'mirage'], + 'margin': ['arming', 'ingram', 'margin'], + 'marginal': ['alarming', 'marginal'], + 'marginally': ['alarmingly', 'marginally'], + 'marginate': ['armangite', 'marginate'], + 'marginated': ['argentamid', 'marginated'], + 'margined': ['dirgeman', 'margined', 'midrange'], + 'marginiform': ['graminiform', 'marginiform'], + 'margot': ['gomart', 'margot'], + 'marhala': ['harmala', 'marhala'], + 'mari': ['amir', 'irma', 'mari', 'mira', 'rami', 'rima'], + 'marialite': ['latimeria', 'marialite'], + 'marian': ['airman', 'amarin', 'marian', 'marina', 'mirana'], + 'mariana': ['aramina', 'mariana'], + 'marianne': ['armenian', 'marianne'], + 'marie': ['aimer', 'maire', 'marie', 'ramie'], + 'marigenous': ['germanious', 'gramineous', 'marigenous'], + 'marilla': ['armilla', 'marilla'], + 'marina': ['airman', 'amarin', 'marian', 'marina', 'mirana'], + 'marinade': ['madeiran', 'marinade'], + 'marinate': ['animater', 'marinate'], + 'marine': ['ermani', 'marine', 'remain'], + 'marinist': ['marinist', 'mistrain'], + 'mario': ['maori', 'mario', 'moira'], + 'marion': ['marion', 'romain'], + 'mariou': ['mariou', 'oarium'], + 'maris': ['maris', 'marsi', 'samir', 'simar'], + 'marish': ['marish', 'shamir'], + 'marishness': ['marishness', 'marshiness'], + 'marist': ['marist', 'matris', 'ramist'], + 'maritage': ['gematria', 'maritage'], + 'marital': ['marital', 'martial'], + 'maritality': ['maritality', 'martiality'], + 'maritally': ['maritally', 'martially'], + 'marka': ['karma', 'krama', 'marka'], + 'markeb': ['embark', 'markeb'], + 'marked': ['demark', 'marked'], + 'marker': ['marker', 'remark'], + 'marketable': ['marketable', 'tablemaker'], + 'marketeer': ['marketeer', 'treemaker'], + 'marketer': ['marketer', 'remarket'], + 'marko': ['marko', 'marok'], + 'marla': ['alarm', 'malar', 'maral', 'marla', 'ramal'], + 'marled': ['dermal', 'marled', 'medlar'], + 'marli': ['armil', 'marli', 'rimal'], + 'marline': ['marline', 'mineral', 'ramline'], + 'marlite': ['lamiter', 'marlite'], + 'marlock': ['lockram', 'marlock'], + 'maro': ['amor', 'maro', 'mora', 'omar', 'roam'], + 'marocain': ['armonica', 'macaroni', 'marocain'], + 'marok': ['marko', 'marok'], + 'maronian': ['maronian', 'romanian'], + 'maronist': ['maronist', 'romanist'], + 'maronite': ['maronite', 'martinoe', 'minorate', 'morenita', 'romanite'], + 'marquesan': ['marquesan', 'squareman'], + 'marquis': ['asquirm', 'marquis'], + 'marree': ['marree', 'reamer'], + 'married': ['admirer', 'madrier', 'married'], + 'marrot': ['marrot', 'mortar'], + 'marrowed': ['marrowed', 'romeward'], + 'marryer': ['marryer', 'remarry'], + 'mars': ['arms', 'mars'], + 'marsh': ['marsh', 'shram'], + 'marshaler': ['marshaler', 'remarshal'], + 'marshiness': ['marishness', 'marshiness'], + 'marshite': ['arthemis', 'marshite', 'meharist'], + 'marsi': ['maris', 'marsi', 'samir', 'simar'], + 'marsipobranchiata': ['basiparachromatin', 'marsipobranchiata'], + 'mart': ['mart', 'tram'], + 'martel': ['armlet', 'malter', 'martel'], + 'marteline': ['alimenter', 'marteline'], + 'marten': ['manter', 'marten', 'rament'], + 'martes': ['martes', 'master', 'remast', 'stream'], + 'martha': ['amarth', 'martha'], + 'martial': ['marital', 'martial'], + 'martiality': ['maritality', 'martiality'], + 'martially': ['maritally', 'martially'], + 'martian': ['martian', 'tamarin'], + 'martinet': ['intermat', 'martinet', 'tetramin'], + 'martinico': ['martinico', 'mortician'], + 'martinoe': ['maronite', 'martinoe', 'minorate', 'morenita', 'romanite'], + 'martite': ['martite', 'mitrate'], + 'martius': ['martius', 'matsuri', 'maurist'], + 'martu': ['martu', 'murat', 'turma'], + 'marty': ['marty', 'tryma'], + 'maru': ['arum', 'maru', 'mura'], + 'mary': ['army', 'mary', 'myra', 'yarm'], + 'marylander': ['aldermanry', 'marylander'], + 'marysole': ['marysole', 'ramosely'], + 'mas': ['mas', 'sam', 'sma'], + 'mascara': ['marasca', 'mascara'], + 'mascotry': ['arctomys', 'costmary', 'mascotry'], + 'masculine': ['masculine', 'semuncial', 'simulance'], + 'masculist': ['masculist', 'simulcast'], + 'masdeu': ['amused', 'masdeu', 'medusa'], + 'mash': ['mash', 'samh', 'sham'], + 'masha': ['hamsa', 'masha', 'shama'], + 'mashal': ['mashal', 'shamal'], + 'mashelton': ['malhonest', 'mashelton'], + 'masher': ['masher', 'ramesh', 'shamer'], + 'mashy': ['mashy', 'shyam'], + 'mask': ['kasm', 'mask'], + 'masker': ['masker', 'remask'], + 'mason': ['manso', 'mason', 'monas'], + 'masoner': ['masoner', 'romanes'], + 'masonic': ['anosmic', 'masonic'], + 'masonite': ['masonite', 'misatone'], + 'maspiter': ['maspiter', 'pastimer', 'primates'], + 'masque': ['masque', 'squame', 'squeam'], + 'massa': ['amass', 'assam', 'massa', 'samas'], + 'masse': ['masse', 'sesma'], + 'masser': ['masser', 'remass'], + 'masseter': ['masseter', 'seamster'], + 'masseur': ['assumer', 'erasmus', 'masseur'], + 'massicot': ['acosmist', 'massicot', 'somatics'], + 'massiness': ['amissness', 'massiness'], + 'masskanne': ['masskanne', 'sneaksman'], + 'mast': ['mast', 'mats', 'stam'], + 'masted': ['demast', 'masted'], + 'master': ['martes', 'master', 'remast', 'stream'], + 'masterate': ['masterate', 'metatarse'], + 'masterer': ['masterer', 'restream', 'streamer'], + 'masterful': ['masterful', 'streamful'], + 'masterless': ['masterless', 'streamless'], + 'masterlike': ['masterlike', 'streamlike'], + 'masterling': ['masterling', 'streamling'], + 'masterly': ['masterly', 'myrtales'], + 'mastership': ['mastership', 'shipmaster'], + 'masterwork': ['masterwork', 'workmaster'], + 'masterwort': ['masterwort', 'streamwort'], + 'mastery': ['mastery', 'streamy'], + 'mastic': ['mastic', 'misact'], + 'masticable': ['ablastemic', 'masticable'], + 'mastiche': ['mastiche', 'misteach'], + 'mastlike': ['kemalist', 'mastlike'], + 'mastoid': ['distoma', 'mastoid'], + 'mastoidale': ['diatomales', 'mastoidale', 'mastoideal'], + 'mastoideal': ['diatomales', 'mastoidale', 'mastoideal'], + 'mastological': ['malacologist', 'mastological'], + 'mastomenia': ['mastomenia', 'seminomata'], + 'mastotomy': ['mastotomy', 'stomatomy'], + 'masu': ['masu', 'musa', 'saum'], + 'mat': ['amt', 'mat', 'tam'], + 'matacan': ['matacan', 'tamanac'], + 'matai': ['amati', 'amita', 'matai'], + 'matar': ['matar', 'matra', 'trama'], + 'matara': ['armata', 'matara', 'tamara'], + 'matcher': ['matcher', 'rematch'], + 'mate': ['mate', 'meat', 'meta', 'tame', 'team', 'tema'], + 'mateless': ['mateless', 'meatless', 'tameless', 'teamless'], + 'matelessness': ['matelessness', 'tamelessness'], + 'mately': ['mately', 'tamely'], + 'mater': ['armet', + 'mater', + 'merat', + 'metra', + 'ramet', + 'tamer', + 'terma', + 'trame', + 'trema'], + 'materialism': ['immaterials', 'materialism'], + 'materiel': ['eremital', 'materiel'], + 'maternal': ['maternal', 'ramental'], + 'maternology': ['laryngotome', 'maternology'], + 'mateship': ['aphetism', 'mateship', 'shipmate', 'spithame'], + 'matey': ['matey', 'meaty'], + 'mathesis': ['mathesis', 'thamesis'], + 'mathetic': ['mathetic', 'thematic'], + 'matico': ['atomic', 'matico'], + 'matin': ['maint', 'matin'], + 'matinee': ['amenite', 'etamine', 'matinee'], + 'matins': ['manist', 'mantis', 'matins', 'stamin'], + 'matra': ['matar', 'matra', 'trama'], + 'matral': ['matral', 'tramal'], + 'matralia': ['altamira', 'matralia'], + 'matrices': ['camerist', 'ceramist', 'matrices'], + 'matricide': ['citramide', 'diametric', 'matricide'], + 'matricula': ['lactarium', 'matricula'], + 'matricular': ['matricular', 'trimacular'], + 'matris': ['marist', 'matris', 'ramist'], + 'matrocliny': ['matrocliny', 'romanticly'], + 'matronism': ['matronism', 'romantism'], + 'mats': ['mast', 'mats', 'stam'], + 'matsu': ['matsu', 'tamus', 'tsuma'], + 'matsuri': ['martius', 'matsuri', 'maurist'], + 'matter': ['matter', 'mettar'], + 'mattoir': ['mattoir', 'tritoma'], + 'maturable': ['maturable', 'metabular'], + 'maturation': ['maturation', 'natatorium'], + 'maturer': ['erratum', 'maturer'], + 'mau': ['aum', 'mau'], + 'maud': ['duma', 'maud'], + 'maudle': ['almude', 'maudle'], + 'mauger': ['mauger', 'murage'], + 'maul': ['alum', 'maul'], + 'mauler': ['mauler', 'merula', 'ramule'], + 'maun': ['maun', 'numa'], + 'maund': ['maund', 'munda', 'numda', 'undam', 'unmad'], + 'maunder': ['duramen', 'maunder', 'unarmed'], + 'maunderer': ['maunderer', 'underream'], + 'maunge': ['mangue', 'maunge'], + 'maureen': ['maureen', 'menurae'], + 'maurice': ['maurice', 'uraemic'], + 'maurist': ['martius', 'matsuri', 'maurist'], + 'mauser': ['amuser', 'mauser'], + 'mavis': ['amvis', 'mavis'], + 'maw': ['maw', 'mwa'], + 'mawp': ['mawp', 'wamp'], + 'may': ['amy', 'may', 'mya', 'yam'], + 'maybe': ['beamy', 'embay', 'maybe'], + 'mayer': ['mayer', 'reamy'], + 'maylike': ['maylike', 'yamilke'], + 'mayo': ['amoy', 'mayo'], + 'mayor': ['mayor', 'moray'], + 'maypoling': ['maypoling', 'pygmalion'], + 'maysin': ['maysin', 'minyas', 'mysian'], + 'maytide': ['daytime', 'maytide'], + 'mazer': ['mazer', 'zerma'], + 'mazur': ['mazur', 'murza'], + 'mbaya': ['ambay', 'mbaya'], + 'me': ['em', 'me'], + 'meable': ['bemeal', 'meable'], + 'mead': ['dame', 'made', 'mead'], + 'meader': ['meader', 'remade'], + 'meager': ['graeme', 'meager', 'meagre'], + 'meagre': ['graeme', 'meager', 'meagre'], + 'meak': ['kame', 'make', 'meak'], + 'meal': ['alem', 'alme', 'lame', 'leam', 'male', 'meal', 'mela'], + 'mealer': ['leamer', 'mealer'], + 'mealiness': ['mealiness', 'messaline'], + 'mealy': ['mealy', 'yamel'], + 'mean': ['amen', 'enam', 'mane', 'mean', 'name', 'nema'], + 'meander': ['amender', 'meander', 'reamend', 'reedman'], + 'meandrite': ['demetrian', 'dermatine', 'meandrite', 'minareted'], + 'meandrous': ['meandrous', 'roundseam'], + 'meaned': ['amende', 'demean', 'meaned', 'nadeem'], + 'meaner': ['enarme', 'meaner', 'rename'], + 'meanly': ['meanly', 'namely'], + 'meant': ['ament', 'meant', 'teman'], + 'mease': ['emesa', 'mease'], + 'measly': ['measly', 'samely'], + 'measuration': ['aeronautism', 'measuration'], + 'measure': ['measure', 'reamuse'], + 'measured': ['madurese', 'measured'], + 'meat': ['mate', 'meat', 'meta', 'tame', 'team', 'tema'], + 'meatal': ['malate', 'meatal', 'tamale'], + 'meatless': ['mateless', 'meatless', 'tameless', 'teamless'], + 'meatman': ['meatman', 'teamman'], + 'meatus': ['meatus', 'mutase'], + 'meaty': ['matey', 'meaty'], + 'mechanal': ['leachman', 'mechanal'], + 'mechanicochemical': ['chemicomechanical', 'mechanicochemical'], + 'mechanics': ['mechanics', 'mischance'], + 'mechir': ['chimer', 'mechir', 'micher'], + 'mecometry': ['cymometer', 'mecometry'], + 'meconic': ['comenic', 'encomic', 'meconic'], + 'meconin': ['ennomic', 'meconin'], + 'meconioid': ['meconioid', 'monoeidic'], + 'meconium': ['encomium', 'meconium'], + 'mecopteron': ['mecopteron', 'protocneme'], + 'medal': ['demal', 'medal'], + 'medallary': ['alarmedly', 'medallary'], + 'mede': ['deem', 'deme', 'mede', 'meed'], + 'media': ['amide', 'damie', 'media'], + 'mediacy': ['dicyema', 'mediacy'], + 'mediad': ['diadem', 'mediad'], + 'medial': ['aldime', 'mailed', 'medial'], + 'median': ['daimen', 'damine', 'maiden', 'median', 'medina'], + 'medianism': ['maidenism', 'medianism'], + 'medianly': ['lymnaeid', 'maidenly', 'medianly'], + 'mediator': ['mareotid', 'mediator'], + 'mediatress': ['mediatress', 'streamside'], + 'mediatrice': ['acidimeter', 'mediatrice'], + 'medical': ['camelid', 'decimal', 'declaim', 'medical'], + 'medically': ['decimally', 'medically'], + 'medicate': ['decimate', 'medicate'], + 'medication': ['decimation', 'medication'], + 'medicator': ['decimator', 'medicator', 'mordicate'], + 'medicatory': ['acidometry', 'medicatory', 'radiectomy'], + 'medicinal': ['adminicle', 'medicinal'], + 'medicophysical': ['medicophysical', 'physicomedical'], + 'medimnos': ['demonism', 'medimnos', 'misnomed'], + 'medina': ['daimen', 'damine', 'maiden', 'median', 'medina'], + 'medino': ['domine', 'domnei', 'emodin', 'medino'], + 'mediocrist': ['dosimetric', 'mediocrist'], + 'mediocrity': ['iridectomy', 'mediocrity'], + 'mediodorsal': ['dorsomedial', 'mediodorsal'], + 'medioventral': ['medioventral', 'ventromedial'], + 'meditate': ['admittee', 'meditate'], + 'meditator': ['meditator', 'trematoid'], + 'medlar': ['dermal', 'marled', 'medlar'], + 'medusa': ['amused', 'masdeu', 'medusa'], + 'medusan': ['medusan', 'sudamen'], + 'meece': ['emcee', 'meece'], + 'meed': ['deem', 'deme', 'mede', 'meed'], + 'meeks': ['meeks', 'smeek'], + 'meered': ['deemer', 'meered', 'redeem', 'remede'], + 'meet': ['meet', 'mete', 'teem'], + 'meeter': ['meeter', 'remeet', 'teemer'], + 'meethelp': ['helpmeet', 'meethelp'], + 'meeting': ['meeting', 'teeming', 'tegmine'], + 'meg': ['gem', 'meg'], + 'megabar': ['bergama', 'megabar'], + 'megachiropteran': ['cinematographer', 'megachiropteran'], + 'megadont': ['magnetod', 'megadont'], + 'megadyne': ['ganymede', 'megadyne'], + 'megaera': ['megaera', 'reamage'], + 'megalodon': ['megalodon', 'moonglade'], + 'megalohepatia': ['hepatomegalia', 'megalohepatia'], + 'megalophonous': ['megalophonous', 'omphalogenous'], + 'megalosplenia': ['megalosplenia', 'splenomegalia'], + 'megapod': ['megapod', 'pagedom'], + 'megapodius': ['megapodius', 'pseudimago'], + 'megarian': ['germania', 'megarian'], + 'megaric': ['gemaric', 'grimace', 'megaric'], + 'megaron': ['marengo', 'megaron'], + 'megaton': ['geomant', 'magneto', 'megaton', 'montage'], + 'megmho': ['megmho', 'megohm'], + 'megohm': ['megmho', 'megohm'], + 'megrim': ['gimmer', 'grimme', 'megrim'], + 'mehari': ['mehari', 'meriah'], + 'meharist': ['arthemis', 'marshite', 'meharist'], + 'meile': ['elemi', 'meile'], + 'mein': ['mein', 'mien', 'mine'], + 'meio': ['meio', 'oime'], + 'mel': ['elm', 'mel'], + 'mela': ['alem', 'alme', 'lame', 'leam', 'male', 'meal', 'mela'], + 'melaconite': ['colemanite', 'melaconite'], + 'melalgia': ['gamaliel', 'melalgia'], + 'melam': ['lemma', 'melam'], + 'melamine': ['ammeline', 'melamine'], + 'melange': ['gleeman', 'melange'], + 'melania': ['laminae', 'melania'], + 'melanian': ['alemanni', 'melanian'], + 'melanic': ['cnemial', 'melanic'], + 'melanilin': ['melanilin', 'millennia'], + 'melanin': ['lemnian', 'lineman', 'melanin'], + 'melanism': ['melanism', 'slimeman'], + 'melanite': ['melanite', 'meletian', 'metaline', 'nemalite'], + 'melanitic': ['alimentic', 'antilemic', 'melanitic', 'metanilic'], + 'melanochroi': ['chloroamine', 'melanochroi'], + 'melanogen': ['melanogen', 'melongena'], + 'melanoid': ['demonial', 'melanoid'], + 'melanorrhea': ['amenorrheal', 'melanorrhea'], + 'melanosis': ['loaminess', 'melanosis'], + 'melanotic': ['entomical', 'melanotic'], + 'melanuria': ['malurinae', 'melanuria'], + 'melanuric': ['ceruminal', 'melanuric', 'numerical'], + 'melas': ['amsel', 'melas', 'mesal', 'samel'], + 'melastoma': ['melastoma', 'metasomal'], + 'meldrop': ['meldrop', 'premold'], + 'melena': ['enamel', 'melena'], + 'melenic': ['celemin', 'melenic'], + 'meletian': ['melanite', 'meletian', 'metaline', 'nemalite'], + 'meletski': ['meletski', 'stemlike'], + 'melian': ['limean', 'maline', 'melian', 'menial'], + 'meliatin': ['meliatin', 'timaline'], + 'melic': ['clime', 'melic'], + 'melica': ['maleic', 'malice', 'melica'], + 'melicerta': ['carmelite', 'melicerta'], + 'melicraton': ['centimolar', 'melicraton'], + 'melinda': ['idleman', 'melinda'], + 'meline': ['elemin', 'meline'], + 'melinite': ['ilmenite', 'melinite', 'menilite'], + 'meliorant': ['meliorant', 'mentorial'], + 'melissa': ['aimless', 'melissa', 'seismal'], + 'melitose': ['melitose', 'mesolite'], + 'mellay': ['lamely', 'mellay'], + 'mellit': ['mellit', 'millet'], + 'melodia': ['melodia', 'molidae'], + 'melodica': ['cameloid', 'comedial', 'melodica'], + 'melodicon': ['clinodome', 'melodicon', 'monocleid'], + 'melodist': ['melodist', 'modelist'], + 'melomanic': ['commelina', 'melomanic'], + 'melon': ['lemon', 'melon', 'monel'], + 'melongena': ['melanogen', 'melongena'], + 'melonist': ['melonist', 'telonism'], + 'melonites': ['limestone', 'melonites', 'milestone'], + 'melonlike': ['lemonlike', 'melonlike'], + 'meloplasty': ['meloplasty', 'myeloplast'], + 'melosa': ['melosa', 'salome', 'semola'], + 'melotragic': ['algometric', 'melotragic'], + 'melotrope': ['melotrope', 'metropole'], + 'melter': ['melter', 'remelt'], + 'melters': ['melters', 'resmelt', 'smelter'], + 'melton': ['loment', 'melton', 'molten'], + 'melungeon': ['melungeon', 'nonlegume'], + 'mem': ['emm', 'mem'], + 'memnon': ['memnon', 'mennom'], + 'memo': ['memo', 'mome'], + 'memorandist': ['memorandist', 'moderantism', 'semidormant'], + 'menage': ['gamene', 'manege', 'menage'], + 'menald': ['lemnad', 'menald'], + 'menaspis': ['menaspis', 'semispan'], + 'mendaite': ['dementia', 'mendaite'], + 'mende': ['emend', 'mende'], + 'mender': ['mender', 'remend'], + 'mendi': ['denim', 'mendi'], + 'mendipite': ['impedient', 'mendipite'], + 'menial': ['limean', 'maline', 'melian', 'menial'], + 'menic': ['menic', 'mince'], + 'menilite': ['ilmenite', 'melinite', 'menilite'], + 'meningeal': ['enameling', 'malengine', 'meningeal'], + 'meningocephalitis': ['cephalomeningitis', 'meningocephalitis'], + 'meningocerebritis': ['cerebromeningitis', 'meningocerebritis'], + 'meningoencephalitis': ['encephalomeningitis', 'meningoencephalitis'], + 'meningoencephalocele': ['encephalomeningocele', 'meningoencephalocele'], + 'meningomyelitis': ['meningomyelitis', 'myelomeningitis'], + 'meningomyelocele': ['meningomyelocele', 'myelomeningocele'], + 'mennom': ['memnon', 'mennom'], + 'menostasia': ['anematosis', 'menostasia'], + 'mensa': ['manes', 'manse', 'mensa', 'samen', 'senam'], + 'mensal': ['anselm', 'mensal'], + 'mense': ['mense', 'mesne', 'semen'], + 'menstrual': ['menstrual', 'ulsterman'], + 'mensurable': ['lebensraum', 'mensurable'], + 'mentagra': ['grateman', 'mangrate', 'mentagra', 'targeman'], + 'mental': ['lament', 'manlet', 'mantel', 'mantle', 'mental'], + 'mentalis': ['mentalis', 'smaltine', 'stileman'], + 'mentalize': ['mentalize', 'mentzelia'], + 'mentation': ['mentation', 'montanite'], + 'mentha': ['anthem', 'hetman', 'mentha'], + 'menthane': ['enanthem', 'menthane'], + 'mentigerous': ['mentigerous', 'tergeminous'], + 'mentolabial': ['labiomental', 'mentolabial'], + 'mentor': ['mentor', 'merton', 'termon', 'tormen'], + 'mentorial': ['meliorant', 'mentorial'], + 'mentzelia': ['mentalize', 'mentzelia'], + 'menura': ['manure', 'menura'], + 'menurae': ['maureen', 'menurae'], + 'menyie': ['menyie', 'yemeni'], + 'meo': ['meo', 'moe'], + 'mephisto': ['mephisto', 'pithsome'], + 'merak': ['maker', 'marek', 'merak'], + 'merat': ['armet', + 'mater', + 'merat', + 'metra', + 'ramet', + 'tamer', + 'terma', + 'trame', + 'trema'], + 'meratia': ['ametria', 'artemia', 'meratia', 'ramaite'], + 'mercal': ['calmer', 'carmel', 'clamer', 'marcel', 'mercal'], + 'mercator': ['cremator', 'mercator'], + 'mercatorial': ['crematorial', 'mercatorial'], + 'mercian': ['armenic', 'carmine', 'ceriman', 'crimean', 'mercian'], + 'merciful': ['crimeful', 'merciful'], + 'merciless': ['crimeless', 'merciless'], + 'mercilessness': ['crimelessness', 'mercilessness'], + 'mere': ['mere', 'reem'], + 'merel': ['elmer', 'merel', 'merle'], + 'merely': ['merely', 'yelmer'], + 'merginae': ['ergamine', 'merginae'], + 'mergus': ['gersum', 'mergus'], + 'meriah': ['mehari', 'meriah'], + 'merice': ['eremic', 'merice'], + 'merida': ['admire', 'armied', 'damier', 'dimera', 'merida'], + 'meril': ['limer', 'meril', 'miler'], + 'meriones': ['emersion', 'meriones'], + 'merism': ['merism', 'mermis', 'simmer'], + 'merist': ['merist', 'mister', 'smiter'], + 'meristem': ['meristem', 'mimester'], + 'meristic': ['meristic', 'trimesic', 'trisemic'], + 'merit': ['merit', 'miter', 'mitre', 'remit', 'timer'], + 'merited': ['demerit', 'dimeter', 'merited', 'mitered'], + 'meriter': ['meriter', 'miterer', 'trireme'], + 'merle': ['elmer', 'merel', 'merle'], + 'merlin': ['limner', 'merlin', 'milner'], + 'mermaid': ['demiram', 'mermaid'], + 'mermis': ['merism', 'mermis', 'simmer'], + 'mero': ['mero', 'more', 'omer', 'rome'], + 'meroblastic': ['blastomeric', 'meroblastic'], + 'merocyte': ['cytomere', 'merocyte'], + 'merogony': ['gonomery', 'merogony'], + 'meroistic': ['eroticism', 'isometric', 'meroistic', 'trioecism'], + 'merop': ['merop', 'moper', 'proem', 'remop'], + 'meropia': ['emporia', 'meropia'], + 'meros': ['meros', 'mores', 'morse', 'sermo', 'smore'], + 'merosthenic': ['merosthenic', 'microsthene'], + 'merostome': ['merostome', 'osmometer'], + 'merrow': ['merrow', 'wormer'], + 'merse': ['merse', 'smeer'], + 'merton': ['mentor', 'merton', 'termon', 'tormen'], + 'merula': ['mauler', 'merula', 'ramule'], + 'meruline': ['lemurine', 'meruline', 'relumine'], + 'mesa': ['asem', 'mesa', 'same', 'seam'], + 'mesad': ['desma', 'mesad'], + 'mesadenia': ['deaminase', 'mesadenia'], + 'mesail': ['amiles', 'asmile', 'mesail', 'mesial', 'samiel'], + 'mesal': ['amsel', 'melas', 'mesal', 'samel'], + 'mesalike': ['mesalike', 'seamlike'], + 'mesaraic': ['cramasie', 'mesaraic'], + 'mesaticephaly': ['hemicatalepsy', 'mesaticephaly'], + 'mese': ['mese', 'seem', 'seme', 'smee'], + 'meshech': ['meshech', 'shechem'], + 'mesial': ['amiles', 'asmile', 'mesail', 'mesial', 'samiel'], + 'mesian': ['asimen', 'inseam', 'mesian'], + 'mesic': ['mesic', 'semic'], + 'mesion': ['eonism', 'mesion', 'oneism', 'simeon'], + 'mesitae': ['amesite', 'mesitae', 'semitae'], + 'mesne': ['mense', 'mesne', 'semen'], + 'meso': ['meso', 'mose', 'some'], + 'mesobar': ['ambrose', 'mesobar'], + 'mesocephaly': ['elaphomyces', 'mesocephaly'], + 'mesognathic': ['asthmogenic', 'mesognathic'], + 'mesohepar': ['mesohepar', 'semaphore'], + 'mesolite': ['melitose', 'mesolite'], + 'mesolithic': ['homiletics', 'mesolithic'], + 'mesological': ['mesological', 'semological'], + 'mesology': ['mesology', 'semology'], + 'mesomeric': ['mesomeric', 'microseme', 'semicrome'], + 'mesonotum': ['mesonotum', 'momentous'], + 'mesorectal': ['calotermes', 'mesorectal', 'metacresol'], + 'mesotonic': ['economist', 'mesotonic'], + 'mesoventral': ['mesoventral', 'ventromesal'], + 'mespil': ['mespil', 'simple'], + 'mesropian': ['mesropian', 'promnesia', 'spironema'], + 'messalian': ['messalian', 'seminasal'], + 'messaline': ['mealiness', 'messaline'], + 'messan': ['enmass', 'maness', 'messan'], + 'messelite': ['messelite', 'semisteel', 'teleseism'], + 'messines': ['essenism', 'messines'], + 'messor': ['messor', 'mosser', 'somers'], + 'mestee': ['esteem', 'mestee'], + 'mester': ['mester', 'restem', 'temser', 'termes'], + 'mesua': ['amuse', 'mesua'], + 'meta': ['mate', 'meat', 'meta', 'tame', 'team', 'tema'], + 'metabular': ['maturable', 'metabular'], + 'metaconid': ['comediant', 'metaconid'], + 'metacresol': ['calotermes', 'mesorectal', 'metacresol'], + 'metage': ['gamete', 'metage'], + 'metaler': ['lameter', 'metaler', 'remetal'], + 'metaline': ['melanite', 'meletian', 'metaline', 'nemalite'], + 'metaling': ['ligament', 'metaling', 'tegminal'], + 'metalist': ['metalist', 'smaltite'], + 'metallism': ['metallism', 'smalltime'], + 'metamer': ['ammeter', 'metamer'], + 'metanilic': ['alimentic', 'antilemic', 'melanitic', 'metanilic'], + 'metaphor': ['metaphor', 'trophema'], + 'metaphoric': ['amphoteric', 'metaphoric'], + 'metaphorical': ['metaphorical', 'pharmacolite'], + 'metaphysical': ['lymphectasia', 'metaphysical'], + 'metaplastic': ['metaplastic', 'palmatisect'], + 'metapore': ['ametrope', 'metapore'], + 'metasomal': ['melastoma', 'metasomal'], + 'metatarse': ['masterate', 'metatarse'], + 'metatheria': ['hemiterata', 'metatheria'], + 'metatrophic': ['metatrophic', 'metropathic'], + 'metaxenia': ['examinate', 'exanimate', 'metaxenia'], + 'mete': ['meet', 'mete', 'teem'], + 'meteor': ['meteor', 'remote'], + 'meteorgraph': ['graphometer', 'meteorgraph'], + 'meteorical': ['carmeloite', 'ectromelia', 'meteorical'], + 'meteoristic': ['meteoristic', 'meteoritics'], + 'meteoritics': ['meteoristic', 'meteoritics'], + 'meteoroid': ['meteoroid', 'odiometer'], + 'meter': ['meter', 'retem'], + 'meterless': ['meterless', 'metreless'], + 'metership': ['herpetism', 'metership', 'metreship', 'temperish'], + 'methanal': ['latheman', 'methanal'], + 'methanate': ['hetmanate', 'methanate'], + 'methanoic': ['hematonic', 'methanoic'], + 'mether': ['mether', 'themer'], + 'method': ['method', 'mothed'], + 'methylacetanilide': ['acetmethylanilide', 'methylacetanilide'], + 'methylic': ['methylic', 'thymelic'], + 'methylotic': ['lithectomy', 'methylotic'], + 'metier': ['metier', 'retime', 'tremie'], + 'metin': ['metin', 'temin', 'timne'], + 'metis': ['metis', 'smite', 'stime', 'times'], + 'metoac': ['comate', 'metoac', 'tecoma'], + 'metol': ['metol', 'motel'], + 'metonymical': ['laminectomy', 'metonymical'], + 'metope': ['metope', 'poemet'], + 'metopias': ['epistoma', 'metopias'], + 'metosteon': ['metosteon', 'tomentose'], + 'metra': ['armet', + 'mater', + 'merat', + 'metra', + 'ramet', + 'tamer', + 'terma', + 'trame', + 'trema'], + 'metrectasia': ['metrectasia', 'remasticate'], + 'metreless': ['meterless', 'metreless'], + 'metreship': ['herpetism', 'metership', 'metreship', 'temperish'], + 'metria': ['imaret', 'metria', 'mirate', 'rimate'], + 'metrician': ['antimeric', 'carminite', 'criminate', 'metrician'], + 'metrics': ['cretism', 'metrics'], + 'metrocratic': ['cratometric', 'metrocratic'], + 'metrological': ['logometrical', 'metrological'], + 'metronome': ['metronome', 'monometer', 'monotreme'], + 'metronomic': ['commorient', 'metronomic', 'monometric'], + 'metronomical': ['metronomical', 'monometrical'], + 'metropathic': ['metatrophic', 'metropathic'], + 'metrophlebitis': ['metrophlebitis', 'phlebometritis'], + 'metropole': ['melotrope', 'metropole'], + 'metroptosia': ['metroptosia', 'prostomiate'], + 'metrorrhea': ['arthromere', 'metrorrhea'], + 'metrostyle': ['metrostyle', 'stylometer'], + 'mettar': ['matter', 'mettar'], + 'metusia': ['metusia', 'suimate', 'timaeus'], + 'mew': ['mew', 'wem'], + 'meward': ['meward', 'warmed'], + 'mho': ['mho', 'ohm'], + 'mhometer': ['mhometer', 'ohmmeter'], + 'miamia': ['amimia', 'miamia'], + 'mian': ['amin', 'main', 'mani', 'mian', 'mina', 'naim'], + 'miaotse': ['miaotse', 'ostemia'], + 'miaotze': ['atomize', 'miaotze'], + 'mias': ['mias', 'saim', 'siam', 'sima'], + 'miasmal': ['lamaism', 'miasmal'], + 'miastor': ['amorist', 'aortism', 'miastor'], + 'miaul': ['aumil', 'miaul'], + 'miauler': ['lemuria', 'miauler'], + 'mib': ['bim', 'mib'], + 'mica': ['amic', 'mica'], + 'micah': ['chiam', 'machi', 'micah'], + 'micate': ['acmite', 'micate'], + 'mication': ['amniotic', 'mication'], + 'micellar': ['micellar', 'millrace'], + 'michael': ['michael', 'micheal'], + 'miche': ['chime', 'hemic', 'miche'], + 'micheal': ['michael', 'micheal'], + 'micher': ['chimer', 'mechir', 'micher'], + 'micht': ['micht', 'mitch'], + 'micranthropos': ['micranthropos', 'promonarchist'], + 'micro': ['micro', 'moric', 'romic'], + 'microcephal': ['microcephal', 'prochemical'], + 'microcephaly': ['microcephaly', 'pyrochemical'], + 'microcinema': ['microcinema', 'microcnemia'], + 'microcnemia': ['microcinema', 'microcnemia'], + 'microcrith': ['microcrith', 'trichromic'], + 'micropetalous': ['micropetalous', 'somatopleuric'], + 'microphagy': ['microphagy', 'myographic'], + 'microphone': ['microphone', 'neomorphic'], + 'microphot': ['microphot', 'morphotic'], + 'microphotograph': ['microphotograph', 'photomicrograph'], + 'microphotographic': ['microphotographic', 'photomicrographic'], + 'microphotography': ['microphotography', 'photomicrography'], + 'microphotoscope': ['microphotoscope', 'photomicroscope'], + 'micropterous': ['micropterous', 'prosectorium'], + 'micropyle': ['micropyle', 'polymeric'], + 'microradiometer': ['microradiometer', 'radiomicrometer'], + 'microseme': ['mesomeric', 'microseme', 'semicrome'], + 'microspectroscope': ['microspectroscope', 'spectromicroscope'], + 'microstat': ['microstat', 'stromatic'], + 'microsthene': ['merosthenic', 'microsthene'], + 'microstome': ['microstome', 'osmometric'], + 'microtia': ['amoritic', 'microtia'], + 'microtinae': ['marcionite', 'microtinae', 'remication'], + 'mid': ['dim', 'mid'], + 'midden': ['midden', 'minded'], + 'middler': ['middler', 'mildred'], + 'middy': ['didym', 'middy'], + 'mide': ['demi', 'diem', 'dime', 'mide'], + 'mider': ['dimer', 'mider'], + 'mididae': ['amidide', 'diamide', 'mididae'], + 'midrange': ['dirgeman', 'margined', 'midrange'], + 'midstory': ['midstory', 'modistry'], + 'miek': ['miek', 'mike'], + 'mien': ['mein', 'mien', 'mine'], + 'mig': ['gim', 'mig'], + 'migraine': ['imaginer', 'migraine'], + 'migrate': ['migrate', 'ragtime'], + 'migratory': ['gyromitra', 'migratory'], + 'mihrab': ['brahmi', 'mihrab'], + 'mikael': ['kelima', 'mikael'], + 'mike': ['miek', 'mike'], + 'mil': ['lim', 'mil'], + 'mila': ['amil', 'amli', 'lima', 'mail', 'mali', 'mila'], + 'milan': ['lamin', 'liman', 'milan'], + 'milden': ['milden', 'mindel'], + 'mildness': ['mildness', 'mindless'], + 'mildred': ['middler', 'mildred'], + 'mile': ['emil', 'lime', 'mile'], + 'milepost': ['milepost', 'polemist'], + 'miler': ['limer', 'meril', 'miler'], + 'miles': ['limes', 'miles', 'slime', 'smile'], + 'milesian': ['alienism', 'milesian'], + 'milestone': ['limestone', 'melonites', 'milestone'], + 'milicent': ['limnetic', 'milicent'], + 'military': ['limitary', 'military'], + 'militate': ['limitate', 'militate'], + 'militation': ['limitation', 'militation'], + 'milken': ['kimnel', 'milken'], + 'millennia': ['melanilin', 'millennia'], + 'miller': ['miller', 'remill'], + 'millet': ['mellit', 'millet'], + 'milliare': ['milliare', 'ramillie'], + 'millrace': ['micellar', 'millrace'], + 'milner': ['limner', 'merlin', 'milner'], + 'milo': ['milo', 'moil'], + 'milsie': ['milsie', 'simile'], + 'miltonia': ['limation', 'miltonia'], + 'mima': ['ammi', 'imam', 'maim', 'mima'], + 'mime': ['emim', 'mime'], + 'mimester': ['meristem', 'mimester'], + 'mimi': ['immi', 'mimi'], + 'mimidae': ['amimide', 'mimidae'], + 'mimosa': ['amomis', 'mimosa'], + 'min': ['min', 'nim'], + 'mina': ['amin', 'main', 'mani', 'mian', 'mina', 'naim'], + 'minacity': ['imitancy', 'intimacy', 'minacity'], + 'minar': ['inarm', 'minar'], + 'minaret': ['minaret', 'raiment', 'tireman'], + 'minareted': ['demetrian', 'dermatine', 'meandrite', 'minareted'], + 'minargent': ['germinant', 'minargent'], + 'minatory': ['minatory', 'romanity'], + 'mince': ['menic', 'mince'], + 'minchiate': ['hematinic', 'minchiate'], + 'mincopie': ['mincopie', 'poimenic'], + 'minded': ['midden', 'minded'], + 'mindel': ['milden', 'mindel'], + 'mindelian': ['eliminand', 'mindelian'], + 'minder': ['minder', 'remind'], + 'mindless': ['mildness', 'mindless'], + 'mine': ['mein', 'mien', 'mine'], + 'miner': ['inerm', 'miner'], + 'mineral': ['marline', 'mineral', 'ramline'], + 'minerva': ['minerva', 'vermian'], + 'minerval': ['minerval', 'verminal'], + 'mingler': ['gremlin', 'mingler'], + 'miniator': ['miniator', 'triamino'], + 'minish': ['minish', 'nimshi'], + 'minister': ['minister', 'misinter'], + 'ministry': ['ministry', 'myristin'], + 'minkish': ['minkish', 'nimkish'], + 'minnetaree': ['minnetaree', 'nemertinea'], + 'minoan': ['amnion', 'minoan', 'nomina'], + 'minometer': ['minometer', 'omnimeter'], + 'minor': ['minor', 'morin'], + 'minorate': ['maronite', 'martinoe', 'minorate', 'morenita', 'romanite'], + 'minorca': ['amicron', 'marconi', 'minorca', 'romanic'], + 'minos': ['minos', 'osmin', 'simon'], + 'minot': ['minot', 'timon', 'tomin'], + 'mintage': ['mintage', 'teaming', 'tegmina'], + 'minter': ['minter', 'remint', 'termin'], + 'minuend': ['minuend', 'unmined'], + 'minuet': ['minuet', 'minute'], + 'minute': ['minuet', 'minute'], + 'minutely': ['minutely', 'untimely'], + 'minuter': ['minuter', 'unmiter'], + 'minyas': ['maysin', 'minyas', 'mysian'], + 'mir': ['mir', 'rim'], + 'mira': ['amir', 'irma', 'mari', 'mira', 'rami', 'rima'], + 'mirabel': ['embrail', 'mirabel'], + 'mirac': ['marci', 'mirac'], + 'miracle': ['claimer', 'miracle', 'reclaim'], + 'mirage': ['imager', 'maigre', 'margie', 'mirage'], + 'mirana': ['airman', 'amarin', 'marian', 'marina', 'mirana'], + 'miranha': ['ahriman', 'miranha'], + 'mirate': ['imaret', 'metria', 'mirate', 'rimate'], + 'mirbane': ['ambrein', 'mirbane'], + 'mire': ['emir', 'imer', 'mire', 'reim', 'remi', 'riem', 'rime'], + 'mirfak': ['marfik', 'mirfak'], + 'mirounga': ['mirounga', 'moringua', 'origanum'], + 'miry': ['miry', 'rimy', 'yirm'], + 'mirza': ['mirza', 'mizar'], + 'misact': ['mastic', 'misact'], + 'misadvise': ['admissive', 'misadvise'], + 'misagent': ['misagent', 'steaming'], + 'misaim': ['misaim', 'misima'], + 'misandry': ['misandry', 'myrsinad'], + 'misassociation': ['associationism', 'misassociation'], + 'misatone': ['masonite', 'misatone'], + 'misattend': ['misattend', 'tandemist'], + 'misaunter': ['antiserum', 'misaunter'], + 'misbehavior': ['behaviorism', 'misbehavior'], + 'mischance': ['mechanics', 'mischance'], + 'misclass': ['classism', 'misclass'], + 'miscoin': ['iconism', 'imsonic', 'miscoin'], + 'misconfiguration': ['configurationism', 'misconfiguration'], + 'misconstitutional': ['constitutionalism', 'misconstitutional'], + 'misconstruction': ['constructionism', 'misconstruction'], + 'miscreant': ['encratism', 'miscreant'], + 'miscreation': ['anisometric', + 'creationism', + 'miscreation', + 'ramisection', + 'reactionism'], + 'miscue': ['cesium', 'miscue'], + 'misdate': ['diastem', 'misdate'], + 'misdaub': ['misdaub', 'submaid'], + 'misdeal': ['misdeal', 'mislead'], + 'misdealer': ['misdealer', 'misleader', 'misleared'], + 'misdeclare': ['creedalism', 'misdeclare'], + 'misdiet': ['misdiet', 'misedit', 'mistide'], + 'misdivision': ['divisionism', 'misdivision'], + 'misdread': ['disarmed', 'misdread'], + 'mise': ['mise', 'semi', 'sime'], + 'misease': ['misease', 'siamese'], + 'misecclesiastic': ['ecclesiasticism', 'misecclesiastic'], + 'misedit': ['misdiet', 'misedit', 'mistide'], + 'misexpression': ['expressionism', 'misexpression'], + 'mishmash': ['mishmash', 'shammish'], + 'misima': ['misaim', 'misima'], + 'misimpression': ['impressionism', 'misimpression'], + 'misinter': ['minister', 'misinter'], + 'mislabel': ['mislabel', 'semiball'], + 'mislabor': ['laborism', 'mislabor'], + 'mislead': ['misdeal', 'mislead'], + 'misleader': ['misdealer', 'misleader', 'misleared'], + 'mislear': ['mislear', 'realism'], + 'misleared': ['misdealer', 'misleader', 'misleared'], + 'misname': ['amenism', 'immanes', 'misname'], + 'misniac': ['cainism', 'misniac'], + 'misnomed': ['demonism', 'medimnos', 'misnomed'], + 'misoneism': ['misoneism', 'simeonism'], + 'mispage': ['impages', 'mispage'], + 'misperception': ['misperception', 'perceptionism'], + 'misperform': ['misperform', 'preformism'], + 'misphrase': ['misphrase', 'seraphism'], + 'misplay': ['impalsy', 'misplay'], + 'misplead': ['misplead', 'pedalism'], + 'misprisal': ['misprisal', 'spiralism'], + 'misproud': ['disporum', 'misproud'], + 'misprovide': ['disimprove', 'misprovide'], + 'misput': ['misput', 'sumpit'], + 'misquotation': ['antimosquito', 'misquotation'], + 'misrate': ['artemis', 'maestri', 'misrate'], + 'misread': ['misread', 'sidearm'], + 'misreform': ['misreform', 'reformism'], + 'misrelate': ['misrelate', 'salimeter'], + 'misrelation': ['misrelation', 'orientalism', 'relationism'], + 'misreliance': ['criminalese', 'misreliance'], + 'misreporter': ['misreporter', 'reporterism'], + 'misrepresentation': ['misrepresentation', 'representationism'], + 'misrepresenter': ['misrepresenter', 'remisrepresent'], + 'misrepute': ['misrepute', 'septerium'], + 'misrhyme': ['misrhyme', 'shimmery'], + 'misrule': ['misrule', 'simuler'], + 'missal': ['missal', 'salmis'], + 'missayer': ['emissary', 'missayer'], + 'misset': ['misset', 'tmesis'], + 'misshape': ['emphasis', 'misshape'], + 'missioner': ['missioner', 'remission'], + 'misspell': ['misspell', 'psellism'], + 'missuggestion': ['missuggestion', 'suggestionism'], + 'missy': ['missy', 'mysis'], + 'mist': ['mist', 'smit', 'stim'], + 'misteach': ['mastiche', 'misteach'], + 'mister': ['merist', 'mister', 'smiter'], + 'mistide': ['misdiet', 'misedit', 'mistide'], + 'mistle': ['mistle', 'smilet'], + 'mistone': ['mistone', 'moisten'], + 'mistradition': ['mistradition', 'traditionism'], + 'mistrain': ['marinist', 'mistrain'], + 'mistreat': ['mistreat', 'teratism'], + 'mistrial': ['mistrial', 'trialism'], + 'mistutor': ['mistutor', 'tutorism'], + 'misty': ['misty', 'stimy'], + 'misunderstander': ['misunderstander', 'remisunderstand'], + 'misura': ['misura', 'ramusi'], + 'misuser': ['misuser', 'surmise'], + 'mitannish': ['mitannish', 'sminthian'], + 'mitch': ['micht', 'mitch'], + 'mite': ['emit', 'item', 'mite', 'time'], + 'mitella': ['mitella', 'tellima'], + 'miteproof': ['miteproof', 'timeproof'], + 'miter': ['merit', 'miter', 'mitre', 'remit', 'timer'], + 'mitered': ['demerit', 'dimeter', 'merited', 'mitered'], + 'miterer': ['meriter', 'miterer', 'trireme'], + 'mithraic': ['arithmic', 'mithraic', 'mithriac'], + 'mithraicist': ['mithraicist', 'mithraistic'], + 'mithraistic': ['mithraicist', 'mithraistic'], + 'mithriac': ['arithmic', 'mithraic', 'mithriac'], + 'mitra': ['mitra', 'tarmi', 'timar', 'tirma'], + 'mitral': ['mitral', 'ramtil'], + 'mitrate': ['martite', 'mitrate'], + 'mitre': ['merit', 'miter', 'mitre', 'remit', 'timer'], + 'mitrer': ['mitrer', 'retrim', 'trimer'], + 'mitridae': ['dimetria', 'mitridae', 'tiremaid', 'triamide'], + 'mixer': ['mixer', 'remix'], + 'mizar': ['mirza', 'mizar'], + 'mnesic': ['cnemis', 'mnesic'], + 'mniaceous': ['acuminose', 'mniaceous'], + 'mniotiltidae': ['delimitation', 'mniotiltidae'], + 'mnium': ['mnium', 'nummi'], + 'mo': ['mo', 'om'], + 'moabitic': ['biatomic', 'moabitic'], + 'moan': ['mano', 'moan', 'mona', 'noam', 'noma', 'oman'], + 'moarian': ['amanori', 'moarian'], + 'moat': ['atmo', 'atom', 'moat', 'toma'], + 'mob': ['bom', 'mob'], + 'mobbable': ['bombable', 'mobbable'], + 'mobber': ['bomber', 'mobber'], + 'mobbish': ['hobbism', 'mobbish'], + 'mobed': ['demob', 'mobed'], + 'mobile': ['bemoil', 'mobile'], + 'mobilian': ['binomial', 'mobilian'], + 'mobocrat': ['mobocrat', 'motorcab'], + 'mobship': ['mobship', 'phobism'], + 'mobster': ['bestorm', 'mobster'], + 'mocker': ['mocker', 'remock'], + 'mocmain': ['ammonic', 'mocmain'], + 'mod': ['dom', 'mod'], + 'modal': ['domal', 'modal'], + 'mode': ['dome', 'mode', 'moed'], + 'modeler': ['demerol', 'modeler', 'remodel'], + 'modelist': ['melodist', 'modelist'], + 'modena': ['daemon', 'damone', 'modena'], + 'modenese': ['modenese', 'needsome'], + 'moderant': ['moderant', 'normated'], + 'moderantism': ['memorandist', 'moderantism', 'semidormant'], + 'modern': ['modern', 'morned'], + 'modernistic': ['modernistic', 'monstricide'], + 'modestly': ['modestly', 'styledom'], + 'modesty': ['dystome', 'modesty'], + 'modiste': ['distome', 'modiste'], + 'modistry': ['midstory', 'modistry'], + 'modius': ['modius', 'sodium'], + 'moe': ['meo', 'moe'], + 'moed': ['dome', 'mode', 'moed'], + 'moerithere': ['heteromeri', 'moerithere'], + 'mogdad': ['goddam', 'mogdad'], + 'moha': ['ahom', 'moha'], + 'mohair': ['homrai', 'mahori', 'mohair'], + 'mohel': ['hemol', 'mohel'], + 'mohican': ['mohican', 'monachi'], + 'moho': ['homo', 'moho'], + 'mohur': ['humor', 'mohur'], + 'moider': ['dormie', 'moider'], + 'moieter': ['moieter', 'romeite'], + 'moiety': ['moiety', 'moyite'], + 'moil': ['milo', 'moil'], + 'moiles': ['lemosi', 'limose', 'moiles'], + 'moineau': ['eunomia', 'moineau'], + 'moira': ['maori', 'mario', 'moira'], + 'moisten': ['mistone', 'moisten'], + 'moistener': ['moistener', 'neoterism'], + 'moisture': ['moisture', 'semitour'], + 'moit': ['itmo', 'moit', 'omit', 'timo'], + 'mojo': ['joom', 'mojo'], + 'moke': ['kome', 'moke'], + 'moki': ['komi', 'moki'], + 'mola': ['loam', 'loma', 'malo', 'mola', 'olam'], + 'molar': ['molar', 'moral', 'romal'], + 'molarity': ['molarity', 'morality'], + 'molary': ['amyrol', 'molary'], + 'molder': ['dermol', 'molder', 'remold'], + 'moler': ['moler', 'morel'], + 'molge': ['glome', 'golem', 'molge'], + 'molidae': ['melodia', 'molidae'], + 'molinia': ['molinia', 'monilia'], + 'mollusca': ['callosum', 'mollusca'], + 'moloid': ['moloid', 'oildom'], + 'molten': ['loment', 'melton', 'molten'], + 'molybdena': ['baldmoney', 'molybdena'], + 'molybdenic': ['combinedly', 'molybdenic'], + 'mome': ['memo', 'mome'], + 'moment': ['moment', 'montem'], + 'momentary': ['manometry', 'momentary'], + 'momentous': ['mesonotum', 'momentous'], + 'momotinae': ['amniotome', 'momotinae'], + 'mona': ['mano', 'moan', 'mona', 'noam', 'noma', 'oman'], + 'monachi': ['mohican', 'monachi'], + 'monactin': ['monactin', 'montanic'], + 'monad': ['damon', 'monad', 'nomad'], + 'monadic': ['monadic', 'nomadic'], + 'monadical': ['monadical', 'nomadical'], + 'monadically': ['monadically', 'nomadically'], + 'monadina': ['monadina', 'nomadian'], + 'monadism': ['monadism', 'nomadism'], + 'monaene': ['anemone', 'monaene'], + 'monal': ['almon', 'monal'], + 'monamniotic': ['commination', 'monamniotic'], + 'monanthous': ['anthonomus', 'monanthous'], + 'monarch': ['monarch', 'nomarch', 'onmarch'], + 'monarchial': ['harmonical', 'monarchial'], + 'monarchian': ['anharmonic', 'monarchian'], + 'monarchistic': ['chiromancist', 'monarchistic'], + 'monarchy': ['monarchy', 'nomarchy'], + 'monarda': ['anadrom', 'madrona', 'mandora', 'monarda', 'roadman'], + 'monas': ['manso', 'mason', 'monas'], + 'monasa': ['monasa', 'samoan'], + 'monase': ['monase', 'nosema'], + 'monaster': ['monaster', 'monstera', 'nearmost', 'storeman'], + 'monastery': ['monastery', 'oysterman'], + 'monastic': ['catonism', 'monastic'], + 'monastical': ['catmalison', 'monastical'], + 'monatomic': ['commation', 'monatomic'], + 'monaural': ['anomural', 'monaural'], + 'monday': ['dynamo', 'monday'], + 'mone': ['mone', 'nome', 'omen'], + 'monel': ['lemon', 'melon', 'monel'], + 'moner': ['enorm', 'moner', 'morne'], + 'monera': ['enamor', 'monera', 'oreman', 'romane'], + 'moneral': ['almoner', 'moneral', 'nemoral'], + 'monergist': ['gerontism', 'monergist'], + 'moneric': ['incomer', 'moneric'], + 'monesia': ['monesia', 'osamine', 'osmanie'], + 'monetary': ['monetary', 'myronate', 'naometry'], + 'money': ['money', 'moyen'], + 'moneybag': ['bogeyman', 'moneybag'], + 'moneyless': ['moneyless', 'moyenless'], + 'monger': ['germon', 'monger', 'morgen'], + 'mongler': ['mongler', 'mongrel'], + 'mongoose': ['gonosome', 'mongoose'], + 'mongrel': ['mongler', 'mongrel'], + 'mongrelity': ['longimetry', 'mongrelity'], + 'monial': ['monial', 'nomial', 'oilman'], + 'monias': ['monias', 'osamin', 'osmina'], + 'monica': ['camion', 'conima', 'manioc', 'monica'], + 'monilated': ['antimodel', 'maldonite', 'monilated'], + 'monilia': ['molinia', 'monilia'], + 'monism': ['monism', 'nomism', 'simmon'], + 'monist': ['inmost', 'monist', 'omnist'], + 'monistic': ['monistic', 'nicotism', 'nomistic'], + 'monitory': ['monitory', 'moronity'], + 'monitress': ['monitress', 'sermonist'], + 'mono': ['mono', 'moon'], + 'monoacid': ['damonico', 'monoacid'], + 'monoazo': ['monoazo', 'monozoa'], + 'monocleid': ['clinodome', 'melodicon', 'monocleid'], + 'monoclinous': ['monoclinous', 'monoclonius'], + 'monoclonius': ['monoclinous', 'monoclonius'], + 'monocracy': ['monocracy', 'nomocracy'], + 'monocystidae': ['monocystidae', 'monocystidea'], + 'monocystidea': ['monocystidae', 'monocystidea'], + 'monodactylous': ['condylomatous', 'monodactylous'], + 'monodactyly': ['dactylonomy', 'monodactyly'], + 'monodelphia': ['amidophenol', 'monodelphia'], + 'monodonta': ['anomodont', 'monodonta'], + 'monodram': ['monodram', 'romandom'], + 'monoecian': ['monoecian', 'neocomian'], + 'monoecism': ['economism', 'monoecism', 'monosemic'], + 'monoeidic': ['meconioid', 'monoeidic'], + 'monogastric': ['gastronomic', 'monogastric'], + 'monogenist': ['monogenist', 'nomogenist'], + 'monogenous': ['monogenous', 'nomogenous'], + 'monogeny': ['monogeny', 'nomogeny'], + 'monogram': ['monogram', 'nomogram'], + 'monograph': ['monograph', 'nomograph', 'phonogram'], + 'monographer': ['geranomorph', 'monographer', 'nomographer'], + 'monographic': ['gramophonic', 'monographic', 'nomographic', 'phonogramic'], + 'monographical': ['gramophonical', 'monographical', 'nomographical'], + 'monographically': ['gramophonically', + 'monographically', + 'nomographically', + 'phonogramically'], + 'monographist': ['gramophonist', 'monographist'], + 'monography': ['monography', 'nomography'], + 'monoid': ['domino', 'monoid'], + 'monological': ['monological', 'nomological'], + 'monologist': ['monologist', 'nomologist', 'ontologism'], + 'monology': ['monology', 'nomology'], + 'monometer': ['metronome', 'monometer', 'monotreme'], + 'monometric': ['commorient', 'metronomic', 'monometric'], + 'monometrical': ['metronomical', 'monometrical'], + 'monomorphic': ['monomorphic', 'morphonomic'], + 'monont': ['monont', 'monton'], + 'monopathy': ['monopathy', 'pathonomy'], + 'monopersulphuric': ['monopersulphuric', 'permonosulphuric'], + 'monophote': ['monophote', 'motophone'], + 'monophylite': ['entomophily', 'monophylite'], + 'monophyllous': ['monophyllous', 'nomophyllous'], + 'monoplanist': ['monoplanist', 'postnominal'], + 'monopsychism': ['monopsychism', 'psychomonism'], + 'monopteral': ['monopteral', 'protonemal'], + 'monosemic': ['economism', 'monoecism', 'monosemic'], + 'monosodium': ['monosodium', 'omnimodous', 'onosmodium'], + 'monotheism': ['monotheism', 'nomotheism'], + 'monotheist': ['monotheist', 'thomsonite'], + 'monothetic': ['monothetic', 'nomothetic'], + 'monotreme': ['metronome', 'monometer', 'monotreme'], + 'monotypal': ['monotypal', 'toponymal'], + 'monotypic': ['monotypic', 'toponymic'], + 'monotypical': ['monotypical', 'toponymical'], + 'monozoa': ['monoazo', 'monozoa'], + 'monozoic': ['monozoic', 'zoonomic'], + 'monroeism': ['monroeism', 'semimoron'], + 'monsieur': ['inermous', 'monsieur'], + 'monstera': ['monaster', 'monstera', 'nearmost', 'storeman'], + 'monstricide': ['modernistic', 'monstricide'], + 'montage': ['geomant', 'magneto', 'megaton', 'montage'], + 'montagnais': ['antagonism', 'montagnais'], + 'montanic': ['monactin', 'montanic'], + 'montanite': ['mentation', 'montanite'], + 'montem': ['moment', 'montem'], + 'montes': ['montes', 'ostmen'], + 'montia': ['atimon', 'manito', 'montia'], + 'monticule': ['ctenolium', 'monticule'], + 'monton': ['monont', 'monton'], + 'montu': ['montu', 'mount', 'notum'], + 'monture': ['monture', 'mounter', 'remount'], + 'monumentary': ['monumentary', 'unmomentary'], + 'mood': ['doom', 'mood'], + 'mooder': ['doomer', 'mooder', 'redoom', 'roomed'], + 'mool': ['loom', 'mool'], + 'mools': ['mools', 'sloom'], + 'moon': ['mono', 'moon'], + 'moonglade': ['megalodon', 'moonglade'], + 'moonite': ['emotion', 'moonite'], + 'moonja': ['majoon', 'moonja'], + 'moonscape': ['manoscope', 'moonscape'], + 'moonseed': ['endosome', 'moonseed'], + 'moontide': ['demotion', 'entomoid', 'moontide'], + 'moop': ['moop', 'pomo'], + 'moor': ['moor', 'moro', 'room'], + 'moorage': ['moorage', 'roomage'], + 'moorball': ['ballroom', 'moorball'], + 'moore': ['moore', 'romeo'], + 'moorn': ['moorn', 'moron'], + 'moorship': ['isomorph', 'moorship'], + 'moorup': ['moorup', 'uproom'], + 'moorwort': ['moorwort', 'rootworm', 'tomorrow', 'wormroot'], + 'moory': ['moory', 'roomy'], + 'moost': ['moost', 'smoot'], + 'moot': ['moot', 'toom'], + 'mooth': ['mooth', 'thoom'], + 'mootstead': ['mootstead', 'stomatode'], + 'mop': ['mop', 'pom'], + 'mopane': ['mopane', 'pomane'], + 'mope': ['mope', 'poem', 'pome'], + 'moper': ['merop', 'moper', 'proem', 'remop'], + 'mophead': ['hemapod', 'mophead'], + 'mopish': ['mopish', 'ophism'], + 'mopla': ['mopla', 'palmo'], + 'mopsy': ['mopsy', 'myops'], + 'mora': ['amor', 'maro', 'mora', 'omar', 'roam'], + 'morainal': ['manorial', 'morainal'], + 'moraine': ['moraine', 'romaine'], + 'moral': ['molar', 'moral', 'romal'], + 'morality': ['molarity', 'morality'], + 'morals': ['morals', 'morsal'], + 'moran': ['manor', 'moran', 'norma', 'ramon', 'roman'], + 'morat': ['amort', 'morat', 'torma'], + 'morate': ['amoret', 'morate'], + 'moray': ['mayor', 'moray'], + 'morbid': ['dibrom', 'morbid'], + 'mordancy': ['dormancy', 'mordancy'], + 'mordant': ['dormant', 'mordant'], + 'mordenite': ['interdome', 'mordenite', 'nemertoid'], + 'mordicate': ['decimator', 'medicator', 'mordicate'], + 'more': ['mero', 'more', 'omer', 'rome'], + 'moreish': ['heroism', 'moreish'], + 'morel': ['moler', 'morel'], + 'morencite': ['entomeric', 'intercome', 'morencite'], + 'morenita': ['maronite', 'martinoe', 'minorate', 'morenita', 'romanite'], + 'moreote': ['moreote', 'oometer'], + 'mores': ['meros', 'mores', 'morse', 'sermo', 'smore'], + 'morga': ['agrom', 'morga'], + 'morganatic': ['actinogram', 'morganatic'], + 'morgay': ['gyroma', 'morgay'], + 'morgen': ['germon', 'monger', 'morgen'], + 'moribund': ['moribund', 'unmorbid'], + 'moric': ['micro', 'moric', 'romic'], + 'moriche': ['homeric', 'moriche'], + 'morin': ['minor', 'morin'], + 'moringa': ['ingomar', 'moringa', 'roaming'], + 'moringua': ['mirounga', 'moringua', 'origanum'], + 'morn': ['morn', 'norm'], + 'morne': ['enorm', 'moner', 'morne'], + 'morned': ['modern', 'morned'], + 'mornless': ['mornless', 'normless'], + 'moro': ['moor', 'moro', 'room'], + 'morocota': ['coatroom', 'morocota'], + 'moron': ['moorn', 'moron'], + 'moronic': ['moronic', 'omicron'], + 'moronity': ['monitory', 'moronity'], + 'morphea': ['amphore', 'morphea'], + 'morphonomic': ['monomorphic', 'morphonomic'], + 'morphotic': ['microphot', 'morphotic'], + 'morphotropic': ['morphotropic', 'protomorphic'], + 'morrisean': ['morrisean', 'rosmarine'], + 'morsal': ['morals', 'morsal'], + 'morse': ['meros', 'mores', 'morse', 'sermo', 'smore'], + 'mortacious': ['mortacious', 'urosomatic'], + 'mortar': ['marrot', 'mortar'], + 'mortician': ['martinico', 'mortician'], + 'mortise': ['erotism', 'mortise', 'trisome'], + 'morton': ['morton', 'tomorn'], + 'mortuarian': ['mortuarian', 'muratorian'], + 'mortuary': ['mortuary', 'outmarry'], + 'mortuous': ['mortuous', 'tumorous'], + 'morus': ['morus', 'mosur'], + 'mosaic': ['aosmic', 'mosaic'], + 'mosandrite': ['mosandrite', 'tarsonemid'], + 'mosasauri': ['amaurosis', 'mosasauri'], + 'moschate': ['chatsome', 'moschate'], + 'mose': ['meso', 'mose', 'some'], + 'mosker': ['mosker', 'smoker'], + 'mosser': ['messor', 'mosser', 'somers'], + 'moste': ['moste', 'smote'], + 'mosting': ['gnomist', 'mosting'], + 'mosul': ['mosul', 'mouls', 'solum'], + 'mosur': ['morus', 'mosur'], + 'mot': ['mot', 'tom'], + 'mote': ['mote', 'tome'], + 'motel': ['metol', 'motel'], + 'motet': ['motet', 'motte', 'totem'], + 'mothed': ['method', 'mothed'], + 'mother': ['mother', 'thermo'], + 'motherland': ['enthraldom', 'motherland'], + 'motherward': ['motherward', 'threadworm'], + 'motograph': ['motograph', 'photogram'], + 'motographic': ['motographic', 'tomographic'], + 'motophone': ['monophote', 'motophone'], + 'motorcab': ['mobocrat', 'motorcab'], + 'motte': ['motet', 'motte', 'totem'], + 'moud': ['doum', 'moud', 'odum'], + 'moudy': ['moudy', 'yomud'], + 'moul': ['moul', 'ulmo'], + 'mouls': ['mosul', 'mouls', 'solum'], + 'mound': ['donum', 'mound'], + 'mount': ['montu', 'mount', 'notum'], + 'mountained': ['emundation', 'mountained'], + 'mountaineer': ['enumeration', 'mountaineer'], + 'mounted': ['demount', 'mounted'], + 'mounter': ['monture', 'mounter', 'remount'], + 'mousery': ['mousery', 'seymour'], + 'mousoni': ['mousoni', 'ominous'], + 'mousse': ['mousse', 'smouse'], + 'moutan': ['amount', 'moutan', 'outman'], + 'mouther': ['mouther', 'theorum'], + 'mover': ['mover', 'vomer'], + 'moy': ['moy', 'yom'], + 'moyen': ['money', 'moyen'], + 'moyenless': ['moneyless', 'moyenless'], + 'moyite': ['moiety', 'moyite'], + 'mru': ['mru', 'rum'], + 'mu': ['mu', 'um'], + 'muang': ['muang', 'munga'], + 'much': ['chum', 'much'], + 'mucic': ['cumic', 'mucic'], + 'mucilage': ['glucemia', 'mucilage'], + 'mucin': ['cumin', 'mucin'], + 'mucinoid': ['conidium', 'mucinoid', 'oncidium'], + 'mucofibrous': ['fibromucous', 'mucofibrous'], + 'mucoid': ['codium', 'mucoid'], + 'muconic': ['muconic', 'uncomic'], + 'mucor': ['mucor', 'mucro'], + 'mucoserous': ['mucoserous', 'seromucous'], + 'mucro': ['mucor', 'mucro'], + 'mucrones': ['consumer', 'mucrones'], + 'mud': ['dum', 'mud'], + 'mudar': ['mudar', 'mudra'], + 'mudden': ['edmund', 'mudden'], + 'mudir': ['mudir', 'murid'], + 'mudra': ['mudar', 'mudra'], + 'mudstone': ['mudstone', 'unmodest'], + 'mug': ['gum', 'mug'], + 'muga': ['gaum', 'muga'], + 'muggles': ['muggles', 'smuggle'], + 'mugweed': ['gumweed', 'mugweed'], + 'muid': ['duim', 'muid'], + 'muilla': ['allium', 'alulim', 'muilla'], + 'muir': ['muir', 'rimu'], + 'muishond': ['muishond', 'unmodish'], + 'muist': ['muist', 'tuism'], + 'mukri': ['kurmi', 'mukri'], + 'muleta': ['amulet', 'muleta'], + 'mulga': ['algum', 'almug', 'glaum', 'gluma', 'mulga'], + 'mulier': ['mulier', 'muriel'], + 'mulita': ['mulita', 'ultima'], + 'mulk': ['kulm', 'mulk'], + 'multani': ['multani', 'talinum'], + 'multinervose': ['multinervose', 'volunteerism'], + 'multipole': ['impollute', 'multipole'], + 'mumbler': ['bummler', 'mumbler'], + 'munda': ['maund', 'munda', 'numda', 'undam', 'unmad'], + 'mundane': ['mundane', 'unamend', 'unmaned', 'unnamed'], + 'munga': ['muang', 'munga'], + 'mungo': ['mungo', 'muong'], + 'munia': ['maniu', 'munia', 'unami'], + 'munity': ['munity', 'mutiny'], + 'muong': ['mungo', 'muong'], + 'mura': ['arum', 'maru', 'mura'], + 'murage': ['mauger', 'murage'], + 'mural': ['mural', 'rumal'], + 'muralist': ['altruism', 'muralist', 'traulism', 'ultraism'], + 'muran': ['muran', 'ruman', 'unarm', 'unram', 'urman'], + 'murat': ['martu', 'murat', 'turma'], + 'muratorian': ['mortuarian', 'muratorian'], + 'murderer': ['demurrer', 'murderer'], + 'murdering': ['demurring', 'murdering'], + 'murderingly': ['demurringly', 'murderingly'], + 'murex': ['murex', 'rumex'], + 'murga': ['garum', 'murga'], + 'muricate': ['ceratium', 'muricate'], + 'muricine': ['irenicum', 'muricine'], + 'murid': ['mudir', 'murid'], + 'muriel': ['mulier', 'muriel'], + 'murine': ['murine', 'nerium'], + 'murly': ['murly', 'rumly'], + 'murmurer': ['murmurer', 'remurmur'], + 'murrain': ['murrain', 'murrina'], + 'murrina': ['murrain', 'murrina'], + 'murut': ['murut', 'utrum'], + 'murza': ['mazur', 'murza'], + 'mus': ['mus', 'sum'], + 'musa': ['masu', 'musa', 'saum'], + 'musal': ['lamus', 'malus', 'musal', 'slaum'], + 'musalmani': ['manualism', 'musalmani'], + 'musang': ['magnus', 'musang'], + 'musar': ['musar', 'ramus', 'rusma', 'surma'], + 'musca': ['camus', 'musca', 'scaum', 'sumac'], + 'muscade': ['camused', 'muscade'], + 'muscarine': ['muscarine', 'sucramine'], + 'musci': ['musci', 'music'], + 'muscicole': ['leucocism', 'muscicole'], + 'muscinae': ['muscinae', 'semuncia'], + 'muscle': ['clumse', 'muscle'], + 'muscly': ['clumsy', 'muscly'], + 'muscone': ['consume', 'muscone'], + 'muscot': ['custom', 'muscot'], + 'mused': ['mused', 'sedum'], + 'museography': ['hypergamous', 'museography'], + 'muser': ['muser', 'remus', 'serum'], + 'musha': ['hamus', 'musha'], + 'music': ['musci', 'music'], + 'musicate': ['autecism', 'musicate'], + 'musico': ['musico', 'suomic'], + 'musie': ['iseum', 'musie'], + 'musing': ['musing', 'signum'], + 'muslined': ['muslined', 'unmisled', 'unsmiled'], + 'musophagine': ['amphigenous', 'musophagine'], + 'mussaenda': ['mussaenda', 'unamassed'], + 'must': ['must', 'smut', 'stum'], + 'mustang': ['mustang', 'stagnum'], + 'mustard': ['durmast', 'mustard'], + 'muster': ['muster', 'sertum', 'stumer'], + 'musterer': ['musterer', 'remuster'], + 'mustily': ['mustily', 'mytilus'], + 'muta': ['muta', 'taum'], + 'mutable': ['atumble', 'mutable'], + 'mutant': ['mutant', 'tantum', 'tutman'], + 'mutase': ['meatus', 'mutase'], + 'mute': ['mute', 'tume'], + 'muteness': ['muteness', 'tenesmus'], + 'mutescence': ['mutescence', 'tumescence'], + 'mutilate': ['mutilate', 'ultimate'], + 'mutilation': ['mutilation', 'ultimation'], + 'mutiny': ['munity', 'mutiny'], + 'mutism': ['mutism', 'summit'], + 'mutual': ['mutual', 'umlaut'], + 'mutulary': ['mutulary', 'tumulary'], + 'muysca': ['cyamus', 'muysca'], + 'mwa': ['maw', 'mwa'], + 'my': ['my', 'ym'], + 'mya': ['amy', 'may', 'mya', 'yam'], + 'myal': ['amyl', 'lyam', 'myal'], + 'myaria': ['amiray', 'myaria'], + 'myatonic': ['cymation', 'myatonic', 'onymatic'], + 'mycelia': ['amyelic', 'mycelia'], + 'mycelian': ['clymenia', 'mycelian'], + 'mycoid': ['cymoid', 'mycoid'], + 'mycophagist': ['mycophagist', 'phagocytism'], + 'mycose': ['cymose', 'mycose'], + 'mycosterol': ['mycosterol', 'sclerotomy'], + 'mycotrophic': ['chromotypic', 'cormophytic', 'mycotrophic'], + 'mycterism': ['mycterism', 'symmetric'], + 'myctodera': ['myctodera', 'radectomy'], + 'mydaleine': ['amylidene', 'mydaleine'], + 'myeloencephalitis': ['encephalomyelitis', 'myeloencephalitis'], + 'myelomeningitis': ['meningomyelitis', 'myelomeningitis'], + 'myelomeningocele': ['meningomyelocele', 'myelomeningocele'], + 'myelon': ['lemony', 'myelon'], + 'myelonal': ['amylenol', 'myelonal'], + 'myeloneuritis': ['myeloneuritis', 'neuromyelitis'], + 'myeloplast': ['meloplasty', 'myeloplast'], + 'mygale': ['gamely', 'gleamy', 'mygale'], + 'myitis': ['myitis', 'simity'], + 'myliobatid': ['bimodality', 'myliobatid'], + 'mymar': ['mymar', 'rammy'], + 'myna': ['many', 'myna'], + 'myoatrophy': ['amyotrophy', 'myoatrophy'], + 'myocolpitis': ['myocolpitis', 'polysomitic'], + 'myofibroma': ['fibromyoma', 'myofibroma'], + 'myoglobin': ['boomingly', 'myoglobin'], + 'myographic': ['microphagy', 'myographic'], + 'myographist': ['myographist', 'pythagorism'], + 'myolipoma': ['lipomyoma', 'myolipoma'], + 'myomohysterectomy': ['hysteromyomectomy', 'myomohysterectomy'], + 'myope': ['myope', 'pomey'], + 'myoplastic': ['myoplastic', 'polymastic'], + 'myoplasty': ['myoplasty', 'polymasty'], + 'myopolar': ['myopolar', 'playroom'], + 'myops': ['mopsy', 'myops'], + 'myosin': ['isonym', 'myosin', 'simony'], + 'myosote': ['myosote', 'toysome'], + 'myotenotomy': ['myotenotomy', 'tenomyotomy'], + 'myotic': ['comity', 'myotic'], + 'myra': ['army', 'mary', 'myra', 'yarm'], + 'myrcia': ['myrcia', 'myrica'], + 'myrialiter': ['myrialiter', 'myrialitre'], + 'myrialitre': ['myrialiter', 'myrialitre'], + 'myriameter': ['myriameter', 'myriametre'], + 'myriametre': ['myriameter', 'myriametre'], + 'myrianida': ['dimyarian', 'myrianida'], + 'myrica': ['myrcia', 'myrica'], + 'myristate': ['myristate', 'tasimetry'], + 'myristin': ['ministry', 'myristin'], + 'myristone': ['myristone', 'smyrniote'], + 'myronate': ['monetary', 'myronate', 'naometry'], + 'myrsinad': ['misandry', 'myrsinad'], + 'myrtales': ['masterly', 'myrtales'], + 'myrtle': ['myrtle', 'termly'], + 'mysell': ['mysell', 'smelly'], + 'mysian': ['maysin', 'minyas', 'mysian'], + 'mysis': ['missy', 'mysis'], + 'mysterial': ['mysterial', 'salimetry'], + 'mystes': ['mystes', 'system'], + 'mythographer': ['mythographer', 'thermography'], + 'mythogreen': ['mythogreen', 'thermogeny'], + 'mythologer': ['mythologer', 'thermology'], + 'mythopoeic': ['homeotypic', 'mythopoeic'], + 'mythus': ['mythus', 'thymus'], + 'mytilid': ['mytilid', 'timidly'], + 'mytilus': ['mustily', 'mytilus'], + 'myxochondroma': ['chondromyxoma', 'myxochondroma'], + 'myxochondrosarcoma': ['chondromyxosarcoma', 'myxochondrosarcoma'], + 'myxocystoma': ['cystomyxoma', 'myxocystoma'], + 'myxofibroma': ['fibromyxoma', 'myxofibroma'], + 'myxofibrosarcoma': ['fibromyxosarcoma', 'myxofibrosarcoma'], + 'myxoinoma': ['inomyxoma', 'myxoinoma'], + 'myxolipoma': ['lipomyxoma', 'myxolipoma'], + 'myxotheca': ['chemotaxy', 'myxotheca'], + 'na': ['an', 'na'], + 'naa': ['ana', 'naa'], + 'naam': ['anam', 'mana', 'naam', 'nama'], + 'nab': ['ban', 'nab'], + 'nabak': ['banak', 'nabak'], + 'nabal': ['alban', 'balan', 'banal', 'laban', 'nabal', 'nabla'], + 'nabalism': ['bailsman', 'balanism', 'nabalism'], + 'nabalite': ['albanite', 'balanite', 'nabalite'], + 'nabalus': ['balanus', 'nabalus', 'subanal'], + 'nabk': ['bank', 'knab', 'nabk'], + 'nabla': ['alban', 'balan', 'banal', 'laban', 'nabal', 'nabla'], + 'nable': ['leban', 'nable'], + 'nabobishly': ['babylonish', 'nabobishly'], + 'nabothian': ['bathonian', 'nabothian'], + 'nabs': ['nabs', 'snab'], + 'nabu': ['baun', 'buna', 'nabu', 'nuba'], + 'nacarat': ['cantara', 'nacarat'], + 'nace': ['acne', 'cane', 'nace'], + 'nachitoch': ['chanchito', 'nachitoch'], + 'nacre': ['caner', 'crane', 'crena', 'nacre', 'rance'], + 'nacred': ['cedarn', 'dancer', 'nacred'], + 'nacreous': ['carneous', 'nacreous'], + 'nacrite': ['centiar', 'certain', 'citrean', 'nacrite', 'nectria'], + 'nacrous': ['carnous', 'nacrous', 'narcous'], + 'nadder': ['dander', 'darned', 'nadder'], + 'nadeem': ['amende', 'demean', 'meaned', 'nadeem'], + 'nadir': ['darin', 'dinar', 'drain', 'indra', 'nadir', 'ranid'], + 'nadorite': ['andorite', 'nadorite', 'ordinate', 'rodentia'], + 'nae': ['ean', 'nae', 'nea'], + 'nael': ['alen', 'lane', 'lean', 'lena', 'nael', 'neal'], + 'naether': ['earthen', 'enheart', 'hearten', 'naether', 'teheran', 'traheen'], + 'nag': ['gan', 'nag'], + 'nagara': ['angara', 'aranga', 'nagara'], + 'nagari': ['graian', 'nagari'], + 'nagatelite': ['gelatinate', 'nagatelite'], + 'nagger': ['ganger', 'grange', 'nagger'], + 'nagging': ['ganging', 'nagging'], + 'naggle': ['laggen', 'naggle'], + 'naggly': ['gangly', 'naggly'], + 'nagmaal': ['malanga', 'nagmaal'], + 'nagnag': ['gangan', 'nagnag'], + 'nagnail': ['alangin', 'anginal', 'anglian', 'nagnail'], + 'nagor': ['angor', + 'argon', + 'goran', + 'grano', + 'groan', + 'nagor', + 'orang', + 'organ', + 'rogan', + 'ronga'], + 'nagster': ['angster', 'garnets', 'nagster', 'strange'], + 'nagual': ['angula', 'nagual'], + 'nahani': ['hainan', 'nahani'], + 'nahor': ['nahor', 'norah', 'rohan'], + 'nahum': ['human', 'nahum'], + 'naiad': ['danai', 'diana', 'naiad'], + 'naiant': ['naiant', 'tainan'], + 'naias': ['asian', 'naias', 'sanai'], + 'naid': ['adin', 'andi', 'dain', 'dani', 'dian', 'naid'], + 'naif': ['fain', 'naif'], + 'naifly': ['fainly', 'naifly'], + 'naig': ['gain', 'inga', 'naig', 'ngai'], + 'naik': ['akin', 'kina', 'naik'], + 'nail': ['alin', 'anil', 'lain', 'lina', 'nail'], + 'nailer': ['arline', 'larine', 'linear', 'nailer', 'renail'], + 'naileress': ['earliness', 'naileress'], + 'nailery': ['inlayer', 'nailery'], + 'nailless': ['nailless', 'sensilla'], + 'nailrod': ['nailrod', 'ordinal', 'rinaldo', 'rodinal'], + 'nailshop': ['nailshop', 'siphonal'], + 'naily': ['inlay', 'naily'], + 'naim': ['amin', 'main', 'mani', 'mian', 'mina', 'naim'], + 'nain': ['nain', 'nina'], + 'naio': ['aion', 'naio'], + 'nair': ['arni', 'iran', 'nair', 'rain', 'rani'], + 'nairy': ['nairy', 'rainy'], + 'nais': ['anis', 'nais', 'nasi', 'nias', 'sain', 'sina'], + 'naish': ['naish', 'shina'], + 'naither': ['anither', 'inearth', 'naither'], + 'naive': ['avine', 'naive', 'vinea'], + 'naivete': ['naivete', 'nieveta'], + 'nak': ['kan', 'nak'], + 'naked': ['kande', 'knead', 'naked'], + 'nakedish': ['headskin', 'nakedish', 'sinkhead'], + 'naker': ['anker', 'karen', 'naker'], + 'nakir': ['inkra', 'krina', 'nakir', 'rinka'], + 'nako': ['kona', 'nako'], + 'nalita': ['antlia', 'latian', 'nalita'], + 'nallah': ['hallan', 'nallah'], + 'nam': ['man', 'nam'], + 'nama': ['anam', 'mana', 'naam', 'nama'], + 'namaz': ['namaz', 'zaman'], + 'nambe': ['beman', 'nambe'], + 'namda': ['adman', 'daman', 'namda'], + 'name': ['amen', 'enam', 'mane', 'mean', 'name', 'nema'], + 'nameability': ['amenability', 'nameability'], + 'nameable': ['amenable', 'nameable'], + 'nameless': ['lameness', 'maleness', 'maneless', 'nameless'], + 'nameling': ['mangelin', 'nameling'], + 'namely': ['meanly', 'namely'], + 'namer': ['enarm', 'namer', 'reman'], + 'nammad': ['madman', 'nammad'], + 'nan': ['ann', 'nan'], + 'nana': ['anan', 'anna', 'nana'], + 'nanaimo': ['nanaimo', 'omniana'], + 'nancy': ['canny', 'nancy'], + 'nandi': ['indan', 'nandi'], + 'nane': ['anne', 'nane'], + 'nanes': ['nanes', 'senna'], + 'nanoid': ['adonin', 'nanoid', 'nonaid'], + 'nanosomia': ['nanosomia', 'nosomania'], + 'nanpie': ['nanpie', 'pennia', 'pinnae'], + 'naological': ['colonalgia', 'naological'], + 'naometry': ['monetary', 'myronate', 'naometry'], + 'naomi': ['amino', 'inoma', 'naomi', 'omani', 'omina'], + 'naoto': ['naoto', 'toona'], + 'nap': ['nap', 'pan'], + 'napaean': ['anapnea', 'napaean'], + 'nape': ['nape', 'neap', 'nepa', 'pane', 'pean'], + 'napead': ['napead', 'panade'], + 'napery': ['napery', 'pyrena'], + 'naphthalize': ['naphthalize', 'phthalazine'], + 'naphtol': ['haplont', 'naphtol'], + 'napkin': ['napkin', 'pankin'], + 'napped': ['append', 'napped'], + 'napper': ['napper', 'papern'], + 'napron': ['napron', 'nonpar'], + 'napthionic': ['antiphonic', 'napthionic'], + 'napu': ['napu', 'puan', 'puna'], + 'nar': ['arn', 'nar', 'ran'], + 'narcaciontes': ['narcaciontes', 'transoceanic'], + 'narcose': ['carnose', 'coarsen', 'narcose'], + 'narcotia': ['craniota', 'croatian', 'narcotia', 'raincoat'], + 'narcoticism': ['intracosmic', 'narcoticism'], + 'narcotina': ['anarcotin', 'cantorian', 'carnation', 'narcotina'], + 'narcotine': ['connarite', 'container', 'cotarnine', 'crenation', 'narcotine'], + 'narcotism': ['narcotism', 'romancist'], + 'narcotist': ['narcotist', 'stratonic'], + 'narcotize': ['narcotize', 'zirconate'], + 'narcous': ['carnous', 'nacrous', 'narcous'], + 'nard': ['darn', 'nard', 'rand'], + 'nardine': ['adrenin', 'nardine'], + 'nardus': ['nardus', 'sundar', 'sundra'], + 'nares': ['anser', 'nares', 'rasen', 'snare'], + 'nargil': ['nargil', 'raglin'], + 'naric': ['cairn', 'crain', 'naric'], + 'narica': ['acinar', + 'arnica', + 'canari', + 'carian', + 'carina', + 'crania', + 'narica'], + 'nariform': ['nariform', 'raniform'], + 'narine': ['narine', 'ranine'], + 'nark': ['knar', 'kran', 'nark', 'rank'], + 'narration': ['narration', 'tornarian'], + 'narthecium': ['anthericum', 'narthecium'], + 'nary': ['nary', 'yarn'], + 'nasab': ['nasab', 'saban'], + 'nasal': ['alans', 'lanas', 'nasal'], + 'nasalism': ['nasalism', 'sailsman'], + 'nasard': ['nasard', 'sandra'], + 'nascapi': ['capsian', 'caspian', 'nascapi', 'panisca'], + 'nash': ['hans', 'nash', 'shan'], + 'nashgab': ['bangash', 'nashgab'], + 'nasi': ['anis', 'nais', 'nasi', 'nias', 'sain', 'sina'], + 'nasial': ['anisal', 'nasial', 'salian', 'salina'], + 'nasitis': ['nasitis', 'sistani'], + 'nasoantral': ['antronasal', 'nasoantral'], + 'nasobuccal': ['bucconasal', 'nasobuccal'], + 'nasofrontal': ['frontonasal', 'nasofrontal'], + 'nasolabial': ['labionasal', 'nasolabial'], + 'nasolachrymal': ['lachrymonasal', 'nasolachrymal'], + 'nasonite': ['estonian', 'nasonite'], + 'nasoorbital': ['nasoorbital', 'orbitonasal'], + 'nasopalatal': ['nasopalatal', 'palatonasal'], + 'nasoseptal': ['nasoseptal', 'septonasal'], + 'nassa': ['nassa', 'sasan'], + 'nassidae': ['assidean', 'nassidae'], + 'nast': ['nast', 'sant', 'stan'], + 'nastic': ['incast', 'nastic'], + 'nastily': ['nastily', 'saintly', 'staynil'], + 'nasturtion': ['antrustion', 'nasturtion'], + 'nasty': ['nasty', 'styan', 'tansy'], + 'nasua': ['nasua', 'sauna'], + 'nasus': ['nasus', 'susan'], + 'nasute': ['nasute', 'nauset', 'unseat'], + 'nat': ['ant', 'nat', 'tan'], + 'nataka': ['nataka', 'tanaka'], + 'natal': ['antal', 'natal'], + 'natalia': ['altaian', 'latania', 'natalia'], + 'natalie': ['laniate', 'natalie', 'taenial'], + 'nataloin': ['latonian', 'nataloin', 'national'], + 'natals': ['aslant', 'lansat', 'natals', 'santal'], + 'natator': ['arnotta', 'natator'], + 'natatorium': ['maturation', 'natatorium'], + 'natch': ['chant', 'natch'], + 'nate': ['ante', 'aten', 'etna', 'nate', 'neat', 'taen', 'tane', 'tean'], + 'nates': ['antes', 'nates', 'stane', 'stean'], + 'nathan': ['nathan', 'thanan'], + 'nathe': ['enhat', 'ethan', 'nathe', 'neath', 'thane'], + 'nather': ['anther', 'nather', 'tharen', 'thenar'], + 'natica': ['actian', 'natica', 'tanica'], + 'naticiform': ['actiniform', 'naticiform'], + 'naticine': ['actinine', 'naticine'], + 'natick': ['catkin', 'natick'], + 'naticoid': ['actinoid', 'diatonic', 'naticoid'], + 'nation': ['anoint', 'nation'], + 'national': ['latonian', 'nataloin', 'national'], + 'native': ['native', 'navite'], + 'natively': ['natively', 'venality'], + 'nativist': ['nativist', 'visitant'], + 'natr': ['natr', 'rant', 'tarn', 'tran'], + 'natricinae': ['natricinae', 'nectarinia'], + 'natricine': ['crinanite', 'natricine'], + 'natrolite': ['natrolite', 'tentorial'], + 'natter': ['attern', 'natter', 'ratten', 'tarten'], + 'nattered': ['attender', 'nattered', 'reattend'], + 'nattily': ['nattily', 'titanyl'], + 'nattle': ['latent', 'latten', 'nattle', 'talent', 'tantle'], + 'naturalistic': ['naturalistic', 'unartistical'], + 'naturing': ['gainturn', 'naturing'], + 'naturism': ['naturism', 'sturmian', 'turanism'], + 'naturist': ['antirust', 'naturist'], + 'naturistic': ['naturistic', 'unartistic'], + 'naturistically': ['naturistically', 'unartistically'], + 'nauger': ['nauger', 'raunge', 'ungear'], + 'naumk': ['kuman', 'naumk'], + 'naunt': ['naunt', 'tunna'], + 'nauntle': ['annulet', 'nauntle'], + 'nauplius': ['nauplius', 'paulinus'], + 'nauset': ['nasute', 'nauset', 'unseat'], + 'naut': ['antu', 'aunt', 'naut', 'taun', 'tuan', 'tuna'], + 'nauther': ['haunter', 'nauther', 'unearth', 'unheart', 'urethan'], + 'nautic': ['anicut', 'nautic', 'ticuna', 'tunica'], + 'nautical': ['actinula', 'nautical'], + 'nautiloid': ['lutianoid', 'nautiloid'], + 'nautilus': ['lutianus', 'nautilus', 'ustulina'], + 'naval': ['alvan', 'naval'], + 'navalist': ['navalist', 'salivant'], + 'navar': ['navar', 'varan', 'varna'], + 'nave': ['evan', 'nave', 'vane'], + 'navel': ['elvan', 'navel', 'venal'], + 'naviculare': ['naviculare', 'uncavalier'], + 'navigant': ['navigant', 'vaginant'], + 'navigate': ['navigate', 'vaginate'], + 'navite': ['native', 'navite'], + 'naw': ['awn', 'naw', 'wan'], + 'nawt': ['nawt', 'tawn', 'want'], + 'nay': ['any', 'nay', 'yan'], + 'nayar': ['aryan', 'nayar', 'rayan'], + 'nazarite': ['nazarite', 'nazirate', 'triazane'], + 'nazi': ['nazi', 'zain'], + 'nazim': ['nazim', 'nizam'], + 'nazirate': ['nazarite', 'nazirate', 'triazane'], + 'nazirite': ['nazirite', 'triazine'], + 'ne': ['en', 'ne'], + 'nea': ['ean', 'nae', 'nea'], + 'neal': ['alen', 'lane', 'lean', 'lena', 'nael', 'neal'], + 'neanic': ['canine', 'encina', 'neanic'], + 'neap': ['nape', 'neap', 'nepa', 'pane', 'pean'], + 'neapolitan': ['antelopian', 'neapolitan', 'panelation'], + 'nearby': ['barney', 'nearby'], + 'nearctic': ['acentric', 'encratic', 'nearctic'], + 'nearest': ['earnest', 'eastern', 'nearest'], + 'nearish': ['arshine', 'nearish', 'rhesian', 'sherani'], + 'nearly': ['anerly', 'nearly'], + 'nearmost': ['monaster', 'monstera', 'nearmost', 'storeman'], + 'nearthrosis': ['enarthrosis', 'nearthrosis'], + 'neat': ['ante', 'aten', 'etna', 'nate', 'neat', 'taen', 'tane', 'tean'], + 'neaten': ['etnean', 'neaten'], + 'neath': ['enhat', 'ethan', 'nathe', 'neath', 'thane'], + 'neatherd': ['adherent', 'headrent', 'neatherd', 'threaden'], + 'neatherdess': ['heartedness', 'neatherdess'], + 'neb': ['ben', 'neb'], + 'neback': ['backen', 'neback'], + 'nebaioth': ['boethian', 'nebaioth'], + 'nebalia': ['abelian', 'nebalia'], + 'nebelist': ['nebelist', 'stilbene', 'tensible'], + 'nebula': ['nebula', 'unable', 'unbale'], + 'nebulose': ['bluenose', 'nebulose'], + 'necator': ['enactor', 'necator', 'orcanet'], + 'necessarian': ['necessarian', 'renaissance'], + 'neckar': ['canker', 'neckar'], + 'necrogenic': ['congeneric', 'necrogenic'], + 'necrogenous': ['congenerous', 'necrogenous'], + 'necrology': ['crenology', 'necrology'], + 'necropoles': ['necropoles', 'preconsole'], + 'necropolis': ['clinospore', 'necropolis'], + 'necrotic': ['crocetin', 'necrotic'], + 'necrotomic': ['necrotomic', 'oncometric'], + 'necrotomy': ['necrotomy', 'normocyte', 'oncometry'], + 'nectar': ['canter', + 'creant', + 'cretan', + 'nectar', + 'recant', + 'tanrec', + 'trance'], + 'nectareal': ['lactarene', 'nectareal'], + 'nectared': ['crenated', 'decanter', 'nectared'], + 'nectareous': ['countersea', 'nectareous'], + 'nectarial': ['carnalite', 'claretian', 'lacertian', 'nectarial'], + 'nectarian': ['cratinean', 'incarnate', 'nectarian'], + 'nectaried': ['nectaried', 'tridecane'], + 'nectarine': ['inertance', 'nectarine'], + 'nectarinia': ['natricinae', 'nectarinia'], + 'nectarious': ['nectarious', 'recusation'], + 'nectarlike': ['nectarlike', 'trancelike'], + 'nectarous': ['acentrous', 'courtesan', 'nectarous'], + 'nectary': ['encraty', 'nectary'], + 'nectophore': ['ctenophore', 'nectophore'], + 'nectria': ['centiar', 'certain', 'citrean', 'nacrite', 'nectria'], + 'ned': ['den', 'end', 'ned'], + 'nedder': ['nedder', 'redden'], + 'neebor': ['boreen', 'enrobe', 'neebor', 'rebone'], + 'need': ['dene', 'eden', 'need'], + 'needer': ['endere', 'needer', 'reeden'], + 'needfire': ['needfire', 'redefine'], + 'needily': ['needily', 'yielden'], + 'needle': ['lendee', 'needle'], + 'needless': ['needless', 'seldseen'], + 'needs': ['dense', 'needs'], + 'needsome': ['modenese', 'needsome'], + 'neeger': ['neeger', 'reenge', 'renege'], + 'neeld': ['leden', 'neeld'], + 'neep': ['neep', 'peen'], + 'neepour': ['neepour', 'neurope'], + 'neer': ['erne', 'neer', 'reen'], + 'neet': ['neet', 'nete', 'teen'], + 'neetup': ['neetup', 'petune'], + 'nef': ['fen', 'nef'], + 'nefast': ['fasten', 'nefast', 'stefan'], + 'neftgil': ['felting', 'neftgil'], + 'negate': ['geneat', 'negate', 'tegean'], + 'negation': ['antigone', 'negation'], + 'negative': ['agentive', 'negative'], + 'negativism': ['negativism', 'timesaving'], + 'negator': ['negator', 'tronage'], + 'negatron': ['argenton', 'negatron'], + 'neger': ['genre', 'green', 'neger', 'reneg'], + 'neglecter': ['neglecter', 'reneglect'], + 'negritian': ['negritian', 'retaining'], + 'negrito': ['ergotin', 'genitor', 'negrito', 'ogtiern', 'trigone'], + 'negritoid': ['negritoid', 'rodingite'], + 'negro': ['ergon', 'genro', 'goner', 'negro'], + 'negroid': ['groined', 'negroid'], + 'negroidal': ['girandole', 'negroidal'], + 'negroize': ['genizero', 'negroize'], + 'negroloid': ['gondolier', 'negroloid'], + 'negrotic': ['gerontic', 'negrotic'], + 'negundo': ['dungeon', 'negundo'], + 'negus': ['genus', 'negus'], + 'neif': ['enif', 'fine', 'neif', 'nife'], + 'neigh': ['hinge', 'neigh'], + 'neil': ['lien', 'line', 'neil', 'nile'], + 'neiper': ['neiper', 'perine', 'pirene', 'repine'], + 'neist': ['inset', 'neist', 'snite', 'stein', 'stine', 'tsine'], + 'neither': ['enherit', 'etherin', 'neither', 'therein'], + 'nekkar': ['kraken', 'nekkar'], + 'nekton': ['kenton', 'nekton'], + 'nelken': ['kennel', 'nelken'], + 'nelsonite': ['nelsonite', 'solentine'], + 'nelumbian': ['nelumbian', 'unminable'], + 'nema': ['amen', 'enam', 'mane', 'mean', 'name', 'nema'], + 'nemalite': ['melanite', 'meletian', 'metaline', 'nemalite'], + 'nematoda': ['mantodea', 'nematoda'], + 'nematoid': ['dominate', 'nematoid'], + 'nematophyton': ['nematophyton', 'tenontophyma'], + 'nemertinea': ['minnetaree', 'nemertinea'], + 'nemertini': ['intermine', 'nemertini', 'terminine'], + 'nemertoid': ['interdome', 'mordenite', 'nemertoid'], + 'nemoral': ['almoner', 'moneral', 'nemoral'], + 'nenta': ['anent', 'annet', 'nenta'], + 'neo': ['eon', 'neo', 'one'], + 'neoarctic': ['accretion', 'anorectic', 'neoarctic'], + 'neocomian': ['monoecian', 'neocomian'], + 'neocosmic': ['economics', 'neocosmic'], + 'neocyte': ['enocyte', 'neocyte'], + 'neogaea': ['eogaean', 'neogaea'], + 'neogenesis': ['neogenesis', 'noegenesis'], + 'neogenetic': ['neogenetic', 'noegenetic'], + 'neognathous': ['anthogenous', 'neognathous'], + 'neolatry': ['neolatry', 'ornately', 'tyrolean'], + 'neolithic': ['ichnolite', 'neolithic'], + 'neomiracle': ['ceremonial', 'neomiracle'], + 'neomorphic': ['microphone', 'neomorphic'], + 'neon': ['neon', 'none'], + 'neophilism': ['neophilism', 'philoneism'], + 'neophytic': ['hypnoetic', 'neophytic'], + 'neoplasm': ['neoplasm', 'pleonasm', 'polesman', 'splenoma'], + 'neoplastic': ['neoplastic', 'pleonastic'], + 'neorama': ['neorama', 'romaean'], + 'neornithes': ['neornithes', 'rhinestone'], + 'neossin': ['neossin', 'sension'], + 'neoteric': ['erection', 'neoteric', 'nocerite', 'renotice'], + 'neoterism': ['moistener', 'neoterism'], + 'neotragus': ['argentous', 'neotragus'], + 'neotropic': ['ectropion', 'neotropic'], + 'neotropical': ['neotropical', 'percolation'], + 'neoza': ['neoza', 'ozena'], + 'nep': ['nep', 'pen'], + 'nepa': ['nape', 'neap', 'nepa', 'pane', 'pean'], + 'nepal': ['alpen', 'nepal', 'panel', 'penal', 'plane'], + 'nepali': ['alpine', 'nepali', 'penial', 'pineal'], + 'neper': ['neper', 'preen', 'repen'], + 'nepheloscope': ['nepheloscope', 'phonelescope'], + 'nephite': ['heptine', 'nephite'], + 'nephogram': ['gomphrena', 'nephogram'], + 'nephological': ['nephological', 'phenological'], + 'nephologist': ['nephologist', 'phenologist'], + 'nephology': ['nephology', 'phenology'], + 'nephria': ['heparin', 'nephria'], + 'nephric': ['nephric', 'phrenic', 'pincher'], + 'nephrite': ['nephrite', 'prehnite', 'trephine'], + 'nephritic': ['nephritic', 'phrenitic', 'prehnitic'], + 'nephritis': ['inspreith', 'nephritis', 'phrenitis'], + 'nephrocardiac': ['nephrocardiac', 'phrenocardiac'], + 'nephrocolic': ['nephrocolic', 'phrenocolic'], + 'nephrocystosis': ['cystonephrosis', 'nephrocystosis'], + 'nephrogastric': ['gastrophrenic', 'nephrogastric', 'phrenogastric'], + 'nephrohydrosis': ['hydronephrosis', 'nephrohydrosis'], + 'nephrolithotomy': ['lithonephrotomy', 'nephrolithotomy'], + 'nephrologist': ['nephrologist', 'phrenologist'], + 'nephrology': ['nephrology', 'phrenology'], + 'nephropathic': ['nephropathic', 'phrenopathic'], + 'nephropathy': ['nephropathy', 'phrenopathy'], + 'nephropsidae': ['nephropsidae', 'praesphenoid'], + 'nephroptosia': ['nephroptosia', 'prosiphonate'], + 'nephropyelitis': ['nephropyelitis', 'pyelonephritis'], + 'nephropyosis': ['nephropyosis', 'pyonephrosis'], + 'nephrosis': ['nephrosis', 'phronesis'], + 'nephrostoma': ['nephrostoma', 'strophomena'], + 'nephrotome': ['nephrotome', 'phonometer'], + 'nephrotomy': ['nephrotomy', 'phonometry'], + 'nepman': ['nepman', 'penman'], + 'nepotal': ['lepanto', 'nepotal', 'petalon', 'polenta'], + 'nepote': ['nepote', 'pontee', 'poteen'], + 'nepotic': ['entopic', 'nepotic', 'pentoic'], + 'nereid': ['denier', 'nereid'], + 'nereis': ['inseer', 'nereis', 'seiner', 'serine', 'sirene'], + 'neri': ['neri', 'rein', 'rine'], + 'nerita': ['nerita', 'ratine', 'retain', 'retina', 'tanier'], + 'neritic': ['citrine', 'crinite', 'inciter', 'neritic'], + 'neritina': ['neritina', 'retinian'], + 'neritoid': ['neritoid', 'retinoid'], + 'nerium': ['murine', 'nerium'], + 'neroic': ['cerion', 'coiner', 'neroic', 'orcein', 'recoin'], + 'neronic': ['corinne', 'cornein', 'neronic'], + 'nerval': ['nerval', 'vernal'], + 'nervate': ['nervate', 'veteran'], + 'nervation': ['nervation', 'vernation'], + 'nerve': ['nerve', 'never'], + 'nervid': ['driven', 'nervid', 'verdin'], + 'nervine': ['innerve', 'nervine', 'vernine'], + 'nerviness': ['inverness', 'nerviness'], + 'nervish': ['nervish', 'shriven'], + 'nervulose': ['nervulose', 'unresolve', 'vulnerose'], + 'nese': ['ense', 'esne', 'nese', 'seen', 'snee'], + 'nesh': ['nesh', 'shen'], + 'nesiot': ['nesiot', 'ostein'], + 'neskhi': ['kishen', 'neskhi'], + 'neslia': ['alsine', 'neslia', 'saline', 'selina', 'silane'], + 'nest': ['nest', 'sent', 'sten'], + 'nester': ['ernest', 'nester', 'resent', 'streen'], + 'nestiatria': ['intarsiate', 'nestiatria'], + 'nestlike': ['nestlike', 'skeletin'], + 'nestor': ['nestor', 'sterno', 'stoner', 'strone', 'tensor'], + 'net': ['net', 'ten'], + 'netcha': ['entach', 'netcha'], + 'nete': ['neet', 'nete', 'teen'], + 'neter': ['enter', 'neter', 'renet', 'terne', 'treen'], + 'netful': ['fluent', 'netful', 'unfelt', 'unleft'], + 'neth': ['hent', 'neth', 'then'], + 'nether': ['erthen', 'henter', 'nether', 'threne'], + 'neti': ['iten', 'neti', 'tien', 'tine'], + 'netman': ['manent', 'netman'], + 'netsuke': ['kuneste', 'netsuke'], + 'nettable': ['nettable', 'tentable'], + 'nettapus': ['nettapus', 'stepaunt'], + 'netted': ['detent', 'netted', 'tented'], + 'netter': ['netter', 'retent', 'tenter'], + 'nettion': ['nettion', 'tention', 'tontine'], + 'nettle': ['letten', 'nettle'], + 'nettler': ['nettler', 'ternlet'], + 'netty': ['netty', 'tenty'], + 'neurad': ['endura', 'neurad', 'undear', 'unread'], + 'neural': ['lunare', 'neural', 'ulnare', 'unreal'], + 'neuralgic': ['genicular', 'neuralgic'], + 'neuralist': ['neuralist', 'ulsterian', 'unrealist'], + 'neurectopia': ['eucatropine', 'neurectopia'], + 'neuric': ['curine', 'erucin', 'neuric'], + 'neurilema': ['lemurinae', 'neurilema'], + 'neurin': ['enruin', 'neurin', 'unrein'], + 'neurism': ['neurism', 'semiurn'], + 'neurite': ['neurite', 'retinue', 'reunite', 'uterine'], + 'neuroblast': ['neuroblast', 'unsortable'], + 'neurodermatosis': ['dermatoneurosis', 'neurodermatosis'], + 'neurofibroma': ['fibroneuroma', 'neurofibroma'], + 'neurofil': ['fluorine', 'neurofil'], + 'neuroganglion': ['ganglioneuron', 'neuroganglion'], + 'neurogenic': ['encoignure', 'neurogenic'], + 'neuroid': ['dourine', 'neuroid'], + 'neurolysis': ['neurolysis', 'resinously'], + 'neuromast': ['anoestrum', 'neuromast'], + 'neuromyelitis': ['myeloneuritis', 'neuromyelitis'], + 'neuronal': ['enaluron', 'neuronal'], + 'neurope': ['neepour', 'neurope'], + 'neuropsychological': ['neuropsychological', 'psychoneurological'], + 'neuropsychosis': ['neuropsychosis', 'psychoneurosis'], + 'neuropteris': ['interposure', 'neuropteris'], + 'neurosis': ['neurosis', 'resinous'], + 'neurotic': ['eruction', 'neurotic'], + 'neurotripsy': ['neurotripsy', 'tripyrenous'], + 'neustrian': ['neustrian', 'saturnine', 'sturninae'], + 'neuter': ['neuter', 'retune', 'runtee', 'tenure', 'tureen'], + 'neuterly': ['neuterly', 'rutylene'], + 'neutral': ['laurent', 'neutral', 'unalert'], + 'neutralism': ['neutralism', 'trimensual'], + 'neutrally': ['neutrally', 'unalertly'], + 'neutralness': ['neutralness', 'unalertness'], + 'nevada': ['nevada', 'vedana', 'venada'], + 'neve': ['even', 'neve', 'veen'], + 'never': ['nerve', 'never'], + 'nevo': ['nevo', 'oven'], + 'nevoy': ['envoy', 'nevoy', 'yoven'], + 'nevus': ['nevus', 'venus'], + 'new': ['new', 'wen'], + 'newar': ['awner', 'newar'], + 'newari': ['newari', 'wainer'], + 'news': ['news', 'sewn', 'snew'], + 'newt': ['newt', 'went'], + 'nexus': ['nexus', 'unsex'], + 'ngai': ['gain', 'inga', 'naig', 'ngai'], + 'ngaio': ['gonia', 'ngaio', 'nogai'], + 'ngapi': ['aping', 'ngapi', 'pangi'], + 'ngoko': ['kongo', 'ngoko'], + 'ni': ['in', 'ni'], + 'niagara': ['agrania', 'angaria', 'niagara'], + 'nias': ['anis', 'nais', 'nasi', 'nias', 'sain', 'sina'], + 'niata': ['anita', 'niata', 'tania'], + 'nib': ['bin', 'nib'], + 'nibs': ['nibs', 'snib'], + 'nibsome': ['nibsome', 'nimbose'], + 'nicarao': ['aaronic', 'nicarao', 'ocarina'], + 'niccolous': ['niccolous', 'occlusion'], + 'nice': ['cine', 'nice'], + 'nicene': ['cinene', 'nicene'], + 'nicenist': ['inscient', 'nicenist'], + 'nicesome': ['nicesome', 'semicone'], + 'nichael': ['chilean', 'echinal', 'nichael'], + 'niche': ['chien', 'chine', 'niche'], + 'nicher': ['enrich', 'nicher', 'richen'], + 'nicholas': ['lichanos', 'nicholas'], + 'nickel': ['nickel', 'nickle'], + 'nickle': ['nickel', 'nickle'], + 'nicol': ['colin', 'nicol'], + 'nicolas': ['nicolas', 'scaloni'], + 'nicolette': ['lecontite', 'nicolette'], + 'nicotian': ['aconitin', 'inaction', 'nicotian'], + 'nicotianin': ['nicotianin', 'nicotinian'], + 'nicotined': ['incondite', 'nicotined'], + 'nicotinian': ['nicotianin', 'nicotinian'], + 'nicotism': ['monistic', 'nicotism', 'nomistic'], + 'nicotize': ['nicotize', 'tonicize'], + 'nictate': ['nictate', 'tetanic'], + 'nictation': ['antitonic', 'nictation'], + 'nid': ['din', 'ind', 'nid'], + 'nidal': ['danli', 'ladin', 'linda', 'nidal'], + 'nidana': ['andian', 'danian', 'nidana'], + 'nidation': ['nidation', 'notidani'], + 'niddle': ['dindle', 'niddle'], + 'nide': ['dine', 'enid', 'inde', 'nide'], + 'nidge': ['deign', 'dinge', 'nidge'], + 'nidget': ['nidget', 'tinged'], + 'niding': ['dining', 'indign', 'niding'], + 'nidologist': ['indologist', 'nidologist'], + 'nidology': ['indology', 'nidology'], + 'nidularia': ['nidularia', 'uniradial'], + 'nidulate': ['nidulate', 'untailed'], + 'nidus': ['dinus', 'indus', 'nidus'], + 'niello': ['lionel', 'niello'], + 'niels': ['elsin', 'lenis', 'niels', 'silen', 'sline'], + 'nieve': ['nieve', 'venie'], + 'nieveta': ['naivete', 'nieveta'], + 'nievling': ['levining', 'nievling'], + 'nife': ['enif', 'fine', 'neif', 'nife'], + 'nifle': ['elfin', 'nifle'], + 'nig': ['gin', 'ing', 'nig'], + 'nigel': ['ingle', 'ligne', 'linge', 'nigel'], + 'nigella': ['gallein', 'galline', 'nigella'], + 'nigerian': ['arginine', 'nigerian'], + 'niggard': ['grading', 'niggard'], + 'nigger': ['ginger', 'nigger'], + 'niggery': ['gingery', 'niggery'], + 'nigh': ['hing', 'nigh'], + 'night': ['night', 'thing'], + 'nightless': ['lightness', 'nightless', 'thingless'], + 'nightlike': ['nightlike', 'thinglike'], + 'nightly': ['nightly', 'thingly'], + 'nightman': ['nightman', 'thingman'], + 'nignye': ['ginney', 'nignye'], + 'nigori': ['nigori', 'origin'], + 'nigre': ['grein', 'inger', 'nigre', 'regin', 'reign', 'ringe'], + 'nigrous': ['nigrous', 'rousing', 'souring'], + 'nihal': ['linha', 'nihal'], + 'nikau': ['kunai', 'nikau'], + 'nil': ['lin', 'nil'], + 'nile': ['lien', 'line', 'neil', 'nile'], + 'nilgai': ['ailing', 'angili', 'nilgai'], + 'nilometer': ['linometer', 'nilometer'], + 'niloscope': ['niloscope', 'scopoline'], + 'nilotic': ['clition', 'nilotic'], + 'nilous': ['insoul', 'linous', 'nilous', 'unsoil'], + 'nim': ['min', 'nim'], + 'nimbed': ['embind', 'nimbed'], + 'nimbose': ['nibsome', 'nimbose'], + 'nimkish': ['minkish', 'nimkish'], + 'nimshi': ['minish', 'nimshi'], + 'nina': ['nain', 'nina'], + 'ninescore': ['ninescore', 'recension'], + 'nineted': ['dentine', 'nineted'], + 'ninevite': ['ninevite', 'nivenite'], + 'ningpo': ['ningpo', 'pignon'], + 'nintu': ['nintu', 'ninut', 'untin'], + 'ninut': ['nintu', 'ninut', 'untin'], + 'niota': ['niota', 'taino'], + 'nip': ['nip', 'pin'], + 'nipa': ['nipa', 'pain', 'pani', 'pian', 'pina'], + 'nippers': ['nippers', 'snipper'], + 'nipple': ['lippen', 'nipple'], + 'nipter': ['nipter', 'terpin'], + 'nisaean': ['nisaean', 'sinaean'], + 'nisqualli': ['nisqualli', 'squillian'], + 'nisus': ['nisus', 'sinus'], + 'nit': ['nit', 'tin'], + 'nitch': ['chint', 'nitch'], + 'nitella': ['nitella', 'tellina'], + 'nitently': ['intently', 'nitently'], + 'niter': ['inert', 'inter', 'niter', 'retin', 'trine'], + 'nitered': ['nitered', 'redient', 'teinder'], + 'nither': ['hinter', 'nither', 'theirn'], + 'nito': ['into', 'nito', 'oint', 'tino'], + 'niton': ['niton', 'noint'], + 'nitrate': ['intreat', 'iterant', 'nitrate', 'tertian'], + 'nitratine': ['itinerant', 'nitratine'], + 'nitric': ['citrin', 'nitric'], + 'nitride': ['inditer', 'nitride'], + 'nitrifaction': ['antifriction', 'nitrifaction'], + 'nitriot': ['introit', 'nitriot'], + 'nitrobenzol': ['benzonitrol', 'nitrobenzol'], + 'nitrogelatin': ['intolerating', 'nitrogelatin'], + 'nitrosate': ['nitrosate', 'stationer'], + 'nitrous': ['nitrous', 'trusion'], + 'nitter': ['nitter', 'tinter'], + 'nitty': ['nitty', 'tinty'], + 'niue': ['niue', 'unie'], + 'nival': ['alvin', 'anvil', 'nival', 'vinal'], + 'nivenite': ['ninevite', 'nivenite'], + 'niveous': ['envious', 'niveous', 'veinous'], + 'nivosity': ['nivosity', 'vinosity'], + 'nizam': ['nazim', 'nizam'], + 'no': ['no', 'on'], + 'noa': ['noa', 'ona'], + 'noachite': ['inchoate', 'noachite'], + 'noah': ['hano', 'noah'], + 'noahic': ['chinoa', 'noahic'], + 'noam': ['mano', 'moan', 'mona', 'noam', 'noma', 'oman'], + 'nob': ['bon', 'nob'], + 'nobleman': ['blennoma', 'nobleman'], + 'noblesse': ['boneless', 'noblesse'], + 'nobs': ['bosn', 'nobs', 'snob'], + 'nocardia': ['nocardia', 'orcadian'], + 'nocent': ['nocent', 'nocten'], + 'nocerite': ['erection', 'neoteric', 'nocerite', 'renotice'], + 'nock': ['conk', 'nock'], + 'nocten': ['nocent', 'nocten'], + 'noctiluca': ['ciclatoun', 'noctiluca'], + 'noctuid': ['conduit', 'duction', 'noctuid'], + 'noctuidae': ['coadunite', 'education', 'noctuidae'], + 'nocturia': ['curation', 'nocturia'], + 'nod': ['don', 'nod'], + 'nodal': ['donal', 'nodal'], + 'nodated': ['donated', 'nodated'], + 'node': ['done', 'node'], + 'nodi': ['dion', 'nodi', 'odin'], + 'nodiak': ['daikon', 'nodiak'], + 'nodical': ['dolcian', 'nodical'], + 'nodicorn': ['corindon', 'nodicorn'], + 'nodule': ['louden', 'nodule'], + 'nodus': ['nodus', 'ounds', 'sound'], + 'noegenesis': ['neogenesis', 'noegenesis'], + 'noegenetic': ['neogenetic', 'noegenetic'], + 'noel': ['elon', 'enol', 'leno', 'leon', 'lone', 'noel'], + 'noetic': ['eciton', 'noetic', 'notice', 'octine'], + 'noetics': ['contise', 'noetics', 'section'], + 'nog': ['gon', 'nog'], + 'nogai': ['gonia', 'ngaio', 'nogai'], + 'nogal': ['along', 'gonal', 'lango', 'longa', 'nogal'], + 'noil': ['lino', 'lion', 'loin', 'noil'], + 'noilage': ['goniale', 'noilage'], + 'noiler': ['elinor', 'lienor', 'lorien', 'noiler'], + 'noint': ['niton', 'noint'], + 'noir': ['inro', 'iron', 'noir', 'nori'], + 'noise': ['eosin', 'noise'], + 'noiseless': ['noiseless', 'selenosis'], + 'noisette': ['noisette', 'teosinte'], + 'nolo': ['loon', 'nolo'], + 'noma': ['mano', 'moan', 'mona', 'noam', 'noma', 'oman'], + 'nomad': ['damon', 'monad', 'nomad'], + 'nomadian': ['monadina', 'nomadian'], + 'nomadic': ['monadic', 'nomadic'], + 'nomadical': ['monadical', 'nomadical'], + 'nomadically': ['monadically', 'nomadically'], + 'nomadism': ['monadism', 'nomadism'], + 'nomarch': ['monarch', 'nomarch', 'onmarch'], + 'nomarchy': ['monarchy', 'nomarchy'], + 'nome': ['mone', 'nome', 'omen'], + 'nomeus': ['nomeus', 'unsome'], + 'nomial': ['monial', 'nomial', 'oilman'], + 'nomina': ['amnion', 'minoan', 'nomina'], + 'nominate': ['antinome', 'nominate'], + 'nominated': ['dentinoma', 'nominated'], + 'nominature': ['nominature', 'numeration'], + 'nomism': ['monism', 'nomism', 'simmon'], + 'nomismata': ['anatomism', 'nomismata'], + 'nomistic': ['monistic', 'nicotism', 'nomistic'], + 'nomocracy': ['monocracy', 'nomocracy'], + 'nomogenist': ['monogenist', 'nomogenist'], + 'nomogenous': ['monogenous', 'nomogenous'], + 'nomogeny': ['monogeny', 'nomogeny'], + 'nomogram': ['monogram', 'nomogram'], + 'nomograph': ['monograph', 'nomograph', 'phonogram'], + 'nomographer': ['geranomorph', 'monographer', 'nomographer'], + 'nomographic': ['gramophonic', 'monographic', 'nomographic', 'phonogramic'], + 'nomographical': ['gramophonical', 'monographical', 'nomographical'], + 'nomographically': ['gramophonically', + 'monographically', + 'nomographically', + 'phonogramically'], + 'nomography': ['monography', 'nomography'], + 'nomological': ['monological', 'nomological'], + 'nomologist': ['monologist', 'nomologist', 'ontologism'], + 'nomology': ['monology', 'nomology'], + 'nomophyllous': ['monophyllous', 'nomophyllous'], + 'nomotheism': ['monotheism', 'nomotheism'], + 'nomothetic': ['monothetic', 'nomothetic'], + 'nona': ['anon', 'nona', 'onan'], + 'nonaccession': ['connoissance', 'nonaccession'], + 'nonact': ['cannot', 'canton', 'conant', 'nonact'], + 'nonaction': ['connation', 'nonaction'], + 'nonagent': ['nonagent', 'tannogen'], + 'nonaid': ['adonin', 'nanoid', 'nonaid'], + 'nonaltruistic': ['instructional', 'nonaltruistic'], + 'nonanimal': ['nonanimal', 'nonmanila'], + 'nonbilabiate': ['inobtainable', 'nonbilabiate'], + 'noncaste': ['noncaste', 'tsonecan'], + 'noncereal': ['aleconner', 'noncereal'], + 'noncertified': ['noncertified', 'nonrectified'], + 'nonclaim': ['cinnamol', 'nonclaim'], + 'noncreation': ['noncreation', 'nonreaction'], + 'noncreative': ['noncreative', 'nonreactive'], + 'noncurantist': ['noncurantist', 'unconstraint'], + 'nonda': ['donna', 'nonda'], + 'nondesecration': ['nondesecration', 'recondensation'], + 'none': ['neon', 'none'], + 'nonempirical': ['nonempirical', 'prenominical'], + 'nonerudite': ['nonerudite', 'unoriented'], + 'nonesuch': ['nonesuch', 'unchosen'], + 'nonet': ['nonet', 'tenon'], + 'nonfertile': ['florentine', 'nonfertile'], + 'nongeometrical': ['inconglomerate', 'nongeometrical'], + 'nonglare': ['algernon', 'nonglare'], + 'nongod': ['dongon', 'nongod'], + 'nonhepatic': ['nonhepatic', 'pantheonic'], + 'nonic': ['conin', 'nonic', 'oncin'], + 'nonideal': ['anneloid', 'nonideal'], + 'nonidealist': ['alstonidine', 'nonidealist'], + 'nonirate': ['anointer', 'inornate', 'nonirate', 'reanoint'], + 'nonius': ['nonius', 'unison'], + 'nonlegato': ['nonlegato', 'ontogenal'], + 'nonlegume': ['melungeon', 'nonlegume'], + 'nonliable': ['bellonian', 'nonliable'], + 'nonlicet': ['contline', 'nonlicet'], + 'nonly': ['nonly', 'nonyl', 'nylon'], + 'nonmanila': ['nonanimal', 'nonmanila'], + 'nonmarital': ['antinormal', 'nonmarital', 'nonmartial'], + 'nonmartial': ['antinormal', 'nonmarital', 'nonmartial'], + 'nonmatter': ['nonmatter', 'remontant'], + 'nonmetric': ['comintern', 'nonmetric'], + 'nonmetrical': ['centinormal', 'conterminal', 'nonmetrical'], + 'nonmolar': ['nonmolar', 'nonmoral'], + 'nonmoral': ['nonmolar', 'nonmoral'], + 'nonnat': ['nonnat', 'nontan'], + 'nonoriental': ['nonoriental', 'nonrelation'], + 'nonpaid': ['dipnoan', 'nonpaid', 'pandion'], + 'nonpar': ['napron', 'nonpar'], + 'nonparental': ['nonparental', 'nonpaternal'], + 'nonpaternal': ['nonparental', 'nonpaternal'], + 'nonpearlitic': ['nonpearlitic', 'pratincoline'], + 'nonpenal': ['nonpenal', 'nonplane'], + 'nonplane': ['nonpenal', 'nonplane'], + 'nonracial': ['carniolan', 'nonracial'], + 'nonrated': ['nonrated', 'nontrade'], + 'nonreaction': ['noncreation', 'nonreaction'], + 'nonreactive': ['noncreative', 'nonreactive'], + 'nonrebel': ['ennobler', 'nonrebel'], + 'nonrecital': ['interconal', 'nonrecital'], + 'nonrectified': ['noncertified', 'nonrectified'], + 'nonrelation': ['nonoriental', 'nonrelation'], + 'nonreserve': ['nonreserve', 'nonreverse'], + 'nonreverse': ['nonreserve', 'nonreverse'], + 'nonrigid': ['girondin', 'nonrigid'], + 'nonsanction': ['inconsonant', 'nonsanction'], + 'nonscientist': ['inconsistent', 'nonscientist'], + 'nonsecret': ['consenter', 'nonsecret', 'reconsent'], + 'nontan': ['nonnat', 'nontan'], + 'nontrade': ['nonrated', 'nontrade'], + 'nonunited': ['nonunited', 'unintoned'], + 'nonuse': ['nonuse', 'unnose'], + 'nonvaginal': ['nonvaginal', 'novanglian'], + 'nonvisitation': ['innovationist', 'nonvisitation'], + 'nonya': ['annoy', 'nonya'], + 'nonyl': ['nonly', 'nonyl', 'nylon'], + 'nooking': ['kongoni', 'nooking'], + 'noontide': ['noontide', 'notioned'], + 'noontime': ['entomion', 'noontime'], + 'noop': ['noop', 'poon'], + 'noose': ['noose', 'osone'], + 'nooser': ['nooser', 'seroon', 'sooner'], + 'nopal': ['lapon', 'nopal'], + 'nope': ['nope', 'open', 'peon', 'pone'], + 'nor': ['nor', 'ron'], + 'nora': ['nora', 'orna', 'roan'], + 'norah': ['nahor', 'norah', 'rohan'], + 'norate': ['atoner', 'norate', 'ornate'], + 'noration': ['noration', 'ornation', 'orotinan'], + 'nordic': ['dornic', 'nordic'], + 'nordicity': ['nordicity', 'tyrocidin'], + 'noreast': ['noreast', 'rosetan', 'seatron', 'senator', 'treason'], + 'nori': ['inro', 'iron', 'noir', 'nori'], + 'noria': ['arion', 'noria'], + 'noric': ['corin', 'noric', 'orcin'], + 'norie': ['irone', 'norie'], + 'norite': ['norite', 'orient'], + 'norm': ['morn', 'norm'], + 'norma': ['manor', 'moran', 'norma', 'ramon', 'roman'], + 'normality': ['normality', 'trionymal'], + 'normated': ['moderant', 'normated'], + 'normless': ['mornless', 'normless'], + 'normocyte': ['necrotomy', 'normocyte', 'oncometry'], + 'norse': ['norse', 'noser', 'seron', 'snore'], + 'norsk': ['norsk', 'snork'], + 'north': ['north', 'thorn'], + 'norther': ['horrent', 'norther'], + 'northing': ['inthrong', 'northing'], + 'nosairi': ['nosairi', 'osirian'], + 'nose': ['enos', 'nose'], + 'nosean': ['nosean', 'oannes'], + 'noseless': ['noseless', 'soleness'], + 'noselite': ['noselite', 'solenite'], + 'nosema': ['monase', 'nosema'], + 'noser': ['norse', 'noser', 'seron', 'snore'], + 'nosesmart': ['nosesmart', 'storesman'], + 'nosism': ['nosism', 'simson'], + 'nosomania': ['nanosomia', 'nosomania'], + 'nostalgia': ['analogist', 'nostalgia'], + 'nostalgic': ['gnostical', 'nostalgic'], + 'nostic': ['nostic', 'sintoc', 'tocsin'], + 'nostoc': ['nostoc', 'oncost'], + 'nosu': ['nosu', 'nous', 'onus'], + 'not': ['not', 'ton'], + 'notability': ['bitonality', 'notability'], + 'notaeal': ['anatole', 'notaeal'], + 'notaeum': ['notaeum', 'outname'], + 'notal': ['notal', 'ontal', 'talon', 'tolan', 'tonal'], + 'notalgia': ['galtonia', 'notalgia'], + 'notalia': ['ailanto', 'alation', 'laotian', 'notalia'], + 'notan': ['anton', 'notan', 'tonna'], + 'notarial': ['notarial', 'rational', 'rotalian'], + 'notarially': ['notarially', 'rationally'], + 'notariate': ['notariate', 'rationate'], + 'notation': ['notation', 'tonation'], + 'notator': ['arnotto', 'notator'], + 'notcher': ['chorten', 'notcher'], + 'note': ['note', 'tone'], + 'noted': ['donet', 'noted', 'toned'], + 'notehead': ['headnote', 'notehead'], + 'noteless': ['noteless', 'toneless'], + 'notelessly': ['notelessly', 'tonelessly'], + 'notelessness': ['notelessness', 'tonelessness'], + 'noter': ['noter', 'tenor', 'toner', 'trone'], + 'nother': ['hornet', 'nother', 'theron', 'throne'], + 'nothous': ['hontous', 'nothous'], + 'notice': ['eciton', 'noetic', 'notice', 'octine'], + 'noticer': ['cerotin', 'cointer', 'cotrine', 'cretion', 'noticer', 'rection'], + 'notidani': ['nidation', 'notidani'], + 'notify': ['notify', 'tonify'], + 'notioned': ['noontide', 'notioned'], + 'notochordal': ['chordotonal', 'notochordal'], + 'notopterus': ['notopterus', 'portentous'], + 'notorhizal': ['horizontal', 'notorhizal'], + 'nototrema': ['antrotome', 'nototrema'], + 'notour': ['notour', 'unroot'], + 'notropis': ['notropis', 'positron', 'sorption'], + 'notum': ['montu', 'mount', 'notum'], + 'notus': ['notus', 'snout', 'stoun', 'tonus'], + 'nought': ['hognut', 'nought'], + 'noup': ['noup', 'puno', 'upon'], + 'nourisher': ['nourisher', 'renourish'], + 'nous': ['nosu', 'nous', 'onus'], + 'novalia': ['novalia', 'valonia'], + 'novanglian': ['nonvaginal', 'novanglian'], + 'novem': ['novem', 'venom'], + 'novitiate': ['evitation', 'novitiate'], + 'now': ['now', 'own', 'won'], + 'nowanights': ['nowanights', 'washington'], + 'nowed': ['endow', 'nowed'], + 'nowhere': ['nowhere', 'whereon'], + 'nowise': ['nowise', 'snowie'], + 'nowness': ['nowness', 'ownness'], + 'nowt': ['nowt', 'town', 'wont'], + 'noxa': ['axon', 'noxa', 'oxan'], + 'noy': ['noy', 'yon'], + 'nozi': ['nozi', 'zion'], + 'nu': ['nu', 'un'], + 'nub': ['bun', 'nub'], + 'nuba': ['baun', 'buna', 'nabu', 'nuba'], + 'nubian': ['nubian', 'unbain'], + 'nubilate': ['antiblue', 'nubilate'], + 'nubile': ['nubile', 'unible'], + 'nucal': ['lucan', 'nucal'], + 'nucellar': ['lucernal', 'nucellar', 'uncellar'], + 'nuchal': ['chulan', 'launch', 'nuchal'], + 'nuciferous': ['nuciferous', 'unciferous'], + 'nuciform': ['nuciform', 'unciform'], + 'nuclear': ['crenula', 'lucarne', 'nuclear', 'unclear'], + 'nucleator': ['nucleator', 'recountal'], + 'nucleoid': ['nucleoid', 'uncoiled'], + 'nuclide': ['include', 'nuclide'], + 'nuculid': ['nuculid', 'unlucid'], + 'nuculidae': ['duculinae', 'nuculidae'], + 'nudate': ['nudate', 'undate'], + 'nuddle': ['ludden', 'nuddle'], + 'nude': ['dune', 'nude', 'unde'], + 'nudeness': ['nudeness', 'unsensed'], + 'nudger': ['dunger', 'gerund', 'greund', 'nudger'], + 'nudist': ['dustin', 'nudist'], + 'nudity': ['nudity', 'untidy'], + 'nuisancer': ['insurance', 'nuisancer'], + 'numa': ['maun', 'numa'], + 'numberer': ['numberer', 'renumber'], + 'numda': ['maund', 'munda', 'numda', 'undam', 'unmad'], + 'numeration': ['nominature', 'numeration'], + 'numerical': ['ceruminal', 'melanuric', 'numerical'], + 'numerist': ['numerist', 'terminus'], + 'numida': ['numida', 'unmaid'], + 'numidae': ['numidae', 'unaimed'], + 'nummi': ['mnium', 'nummi'], + 'nunciate': ['nunciate', 'uncinate'], + 'nuncio': ['nuncio', 'uncoin'], + 'nuncioship': ['nuncioship', 'pincushion'], + 'nunki': ['nunki', 'unkin'], + 'nunlet': ['nunlet', 'tunnel', 'unlent'], + 'nunlike': ['nunlike', 'unliken'], + 'nunnated': ['nunnated', 'untanned'], + 'nunni': ['nunni', 'uninn'], + 'nuptial': ['nuptial', 'unplait'], + 'nurse': ['nurse', 'resun'], + 'nusfiah': ['faunish', 'nusfiah'], + 'nut': ['nut', 'tun'], + 'nutarian': ['nutarian', 'turanian'], + 'nutate': ['attune', 'nutate', 'tauten'], + 'nutgall': ['gallnut', 'nutgall'], + 'nuthatch': ['nuthatch', 'unthatch'], + 'nutlike': ['nutlike', 'tunlike'], + 'nutmeg': ['gnetum', 'nutmeg'], + 'nutramin': ['nutramin', 'ruminant'], + 'nutrice': ['nutrice', 'teucrin'], + 'nycteridae': ['encyrtidae', 'nycteridae'], + 'nycterine': ['nycterine', 'renitency'], + 'nycteris': ['nycteris', 'stycerin'], + 'nycturia': ['nycturia', 'tunicary'], + 'nye': ['eyn', 'nye', 'yen'], + 'nylast': ['nylast', 'stanly'], + 'nylon': ['nonly', 'nonyl', 'nylon'], + 'nymphalidae': ['lymphadenia', 'nymphalidae'], + 'nyroca': ['canroy', 'crayon', 'cyrano', 'nyroca'], + 'nystagmic': ['gymnastic', 'nystagmic'], + 'oak': ['ako', 'koa', 'oak', 'oka'], + 'oaky': ['kayo', 'oaky'], + 'oam': ['mao', 'oam'], + 'oannes': ['nosean', 'oannes'], + 'oar': ['aro', 'oar', 'ora'], + 'oared': ['adore', 'oared', 'oread'], + 'oaric': ['cairo', 'oaric'], + 'oaritis': ['isotria', 'oaritis'], + 'oarium': ['mariou', 'oarium'], + 'oarless': ['lassoer', 'oarless', 'rosales'], + 'oarman': ['oarman', 'ramona'], + 'oasal': ['alosa', 'loasa', 'oasal'], + 'oasis': ['oasis', 'sosia'], + 'oast': ['oast', 'stoa', 'taos'], + 'oat': ['oat', 'tao', 'toa'], + 'oatbin': ['batino', 'oatbin', 'obtain'], + 'oaten': ['atone', 'oaten'], + 'oatlike': ['keitloa', 'oatlike'], + 'obclude': ['becloud', 'obclude'], + 'obeah': ['bahoe', 'bohea', 'obeah'], + 'obeisant': ['obeisant', 'sabotine'], + 'obelial': ['bolelia', 'lobelia', 'obelial'], + 'obeliscal': ['escobilla', 'obeliscal'], + 'obelus': ['besoul', 'blouse', 'obelus'], + 'oberon': ['borneo', 'oberon'], + 'obi': ['ibo', 'obi'], + 'obispo': ['boopis', 'obispo'], + 'obit': ['bito', 'obit'], + 'objectative': ['objectative', 'objectivate'], + 'objectivate': ['objectative', 'objectivate'], + 'oblate': ['lobate', 'oblate'], + 'oblately': ['lobately', 'oblately'], + 'oblation': ['boltonia', 'lobation', 'oblation'], + 'obligant': ['bloating', 'obligant'], + 'obliviality': ['obliviality', 'violability'], + 'obol': ['bolo', 'bool', 'lobo', 'obol'], + 'obscurant': ['obscurant', 'subcantor'], + 'obscurantic': ['obscurantic', 'subnarcotic'], + 'obscurantist': ['obscurantist', 'substraction'], + 'obscure': ['bescour', 'buceros', 'obscure'], + 'obscurer': ['crebrous', 'obscurer'], + 'obsecrate': ['bracteose', 'obsecrate'], + 'observe': ['observe', 'obverse', 'verbose'], + 'obsessor': ['berossos', 'obsessor'], + 'obstinate': ['bastionet', 'obstinate'], + 'obtain': ['batino', 'oatbin', 'obtain'], + 'obtainal': ['ablation', 'obtainal'], + 'obtainer': ['abrotine', 'baritone', 'obtainer', 'reobtain'], + 'obtrude': ['doubter', 'obtrude', 'outbred', 'redoubt'], + 'obtruncation': ['conturbation', 'obtruncation'], + 'obturate': ['obturate', 'tabouret'], + 'obverse': ['observe', 'obverse', 'verbose'], + 'obversely': ['obversely', 'verbosely'], + 'ocarina': ['aaronic', 'nicarao', 'ocarina'], + 'occasioner': ['occasioner', 'reoccasion'], + 'occipitofrontal': ['frontooccipital', 'occipitofrontal'], + 'occipitotemporal': ['occipitotemporal', 'temporooccipital'], + 'occlusion': ['niccolous', 'occlusion'], + 'occurrent': ['cocurrent', 'occurrent', 'uncorrect'], + 'ocean': ['acone', 'canoe', 'ocean'], + 'oceanet': ['acetone', 'oceanet'], + 'oceanic': ['cocaine', 'oceanic'], + 'ocellar': ['collare', 'corella', 'ocellar'], + 'ocellate': ['collatee', 'ocellate'], + 'ocellated': ['decollate', 'ocellated'], + 'ocelli': ['collie', 'ocelli'], + 'och': ['cho', 'och'], + 'ocher': ['chore', 'ocher'], + 'ocherous': ['ocherous', 'ochreous'], + 'ochidore': ['choreoid', 'ochidore'], + 'ochlesis': ['helcosis', 'ochlesis'], + 'ochlesitic': ['cochleitis', 'ochlesitic'], + 'ochletic': ['helcotic', 'lochetic', 'ochletic'], + 'ochlocrat': ['colcothar', 'ochlocrat'], + 'ochrea': ['chorea', 'ochrea', 'rochea'], + 'ochreous': ['ocherous', 'ochreous'], + 'ochroid': ['choroid', 'ochroid'], + 'ochroma': ['amchoor', 'ochroma'], + 'ocht': ['coth', 'ocht'], + 'ocque': ['coque', 'ocque'], + 'ocreated': ['decorate', 'ocreated'], + 'octadic': ['cactoid', 'octadic'], + 'octaeteric': ['ecorticate', 'octaeteric'], + 'octakishexahedron': ['hexakisoctahedron', 'octakishexahedron'], + 'octan': ['acton', 'canto', 'octan'], + 'octandrian': ['dracontian', 'octandrian'], + 'octarius': ['cotarius', 'octarius', 'suctoria'], + 'octastrophic': ['octastrophic', 'postthoracic'], + 'octave': ['avocet', 'octave', 'vocate'], + 'octavian': ['octavian', 'octavina', 'vacation'], + 'octavina': ['octavian', 'octavina', 'vacation'], + 'octenary': ['enactory', 'octenary'], + 'octet': ['cotte', 'octet'], + 'octillion': ['cotillion', 'octillion'], + 'octine': ['eciton', 'noetic', 'notice', 'octine'], + 'octometer': ['octometer', 'rectotome', 'tocometer'], + 'octonal': ['coolant', 'octonal'], + 'octonare': ['coronate', 'octonare', 'otocrane'], + 'octonarius': ['acutorsion', 'octonarius'], + 'octoroon': ['coonroot', 'octoroon'], + 'octuple': ['couplet', 'octuple'], + 'ocularist': ['ocularist', 'suctorial'], + 'oculate': ['caulote', 'colutea', 'oculate'], + 'oculinid': ['lucinoid', 'oculinid'], + 'ocypete': ['ecotype', 'ocypete'], + 'od': ['do', 'od'], + 'oda': ['ado', 'dao', 'oda'], + 'odal': ['alod', 'dola', 'load', 'odal'], + 'odalman': ['mandola', 'odalman'], + 'odax': ['doxa', 'odax'], + 'odd': ['dod', 'odd'], + 'oddman': ['dodman', 'oddman'], + 'ode': ['doe', 'edo', 'ode'], + 'odel': ['dole', 'elod', 'lode', 'odel'], + 'odin': ['dion', 'nodi', 'odin'], + 'odinism': ['diosmin', 'odinism'], + 'odinite': ['edition', 'odinite', 'otidine', 'tineoid'], + 'odiometer': ['meteoroid', 'odiometer'], + 'odious': ['iodous', 'odious'], + 'odor': ['door', 'odor', 'oord', 'rood'], + 'odorant': ['donator', 'odorant', 'tornado'], + 'odored': ['doored', 'odored'], + 'odorless': ['doorless', 'odorless'], + 'ods': ['dos', 'ods', 'sod'], + 'odum': ['doum', 'moud', 'odum'], + 'odyl': ['loyd', 'odyl'], + 'odylist': ['odylist', 'styloid'], + 'oecanthus': ['ceanothus', 'oecanthus'], + 'oecist': ['cotise', 'oecist'], + 'oedipal': ['elapoid', 'oedipal'], + 'oenin': ['inone', 'oenin'], + 'oenocarpus': ['oenocarpus', 'uranoscope'], + 'oer': ['oer', 'ore', 'roe'], + 'oes': ['oes', 'ose', 'soe'], + 'oestrian': ['arsonite', 'asterion', 'oestrian', 'rosinate', 'serotina'], + 'oestrid': ['oestrid', 'steroid', 'storied'], + 'oestridae': ['oestridae', 'ostreidae', 'sorediate'], + 'oestrin': ['oestrin', 'tersion'], + 'oestriol': ['oestriol', 'rosolite'], + 'oestroid': ['oestroid', 'ordosite', 'ostreoid'], + 'oestrual': ['oestrual', 'rosulate'], + 'oestrum': ['oestrum', 'rosetum'], + 'oestrus': ['estrous', 'oestrus', 'sestuor', 'tussore'], + 'of': ['fo', 'of'], + 'ofer': ['fore', 'froe', 'ofer'], + 'offcast': ['castoff', 'offcast'], + 'offcut': ['cutoff', 'offcut'], + 'offender': ['offender', 'reoffend'], + 'offerer': ['offerer', 'reoffer'], + 'offlet': ['letoff', 'offlet'], + 'offset': ['offset', 'setoff'], + 'offuscate': ['offuscate', 'suffocate'], + 'offuscation': ['offuscation', 'suffocation'], + 'offward': ['drawoff', 'offward'], + 'ofo': ['foo', 'ofo'], + 'oft': ['fot', 'oft'], + 'oftens': ['oftens', 'soften'], + 'ofter': ['fetor', 'forte', 'ofter'], + 'oftly': ['lofty', 'oftly'], + 'og': ['go', 'og'], + 'ogam': ['goma', 'ogam'], + 'ogeed': ['geode', 'ogeed'], + 'ogle': ['egol', 'goel', 'loge', 'ogle', 'oleg'], + 'ogler': ['glore', 'ogler'], + 'ogpu': ['goup', 'ogpu', 'upgo'], + 'ogre': ['goer', 'gore', 'ogre'], + 'ogreism': ['ergoism', 'ogreism'], + 'ogtiern': ['ergotin', 'genitor', 'negrito', 'ogtiern', 'trigone'], + 'oh': ['ho', 'oh'], + 'ohm': ['mho', 'ohm'], + 'ohmage': ['homage', 'ohmage'], + 'ohmmeter': ['mhometer', 'ohmmeter'], + 'oilcan': ['alnico', 'cliona', 'oilcan'], + 'oilcup': ['oilcup', 'upcoil'], + 'oildom': ['moloid', 'oildom'], + 'oiler': ['oiler', 'oriel', 'reoil'], + 'oillet': ['elliot', 'oillet'], + 'oilman': ['monial', 'nomial', 'oilman'], + 'oilstone': ['leonotis', 'oilstone'], + 'oime': ['meio', 'oime'], + 'oinomania': ['oinomania', 'oniomania'], + 'oint': ['into', 'nito', 'oint', 'tino'], + 'oireachtas': ['oireachtas', 'theocrasia'], + 'ok': ['ko', 'ok'], + 'oka': ['ako', 'koa', 'oak', 'oka'], + 'oket': ['keto', 'oket', 'toke'], + 'oki': ['koi', 'oki'], + 'okie': ['ekoi', 'okie'], + 'okra': ['karo', 'kora', 'okra', 'roka'], + 'olaf': ['foal', 'loaf', 'olaf'], + 'olam': ['loam', 'loma', 'malo', 'mola', 'olam'], + 'olamic': ['colima', 'olamic'], + 'olcha': ['chola', 'loach', 'olcha'], + 'olchi': ['choil', 'choli', 'olchi'], + 'old': ['dol', 'lod', 'old'], + 'older': ['lored', 'older'], + 'oldhamite': ['ethmoidal', 'oldhamite'], + 'ole': ['leo', 'ole'], + 'olea': ['aloe', 'olea'], + 'olecranal': ['lanceolar', 'olecranal'], + 'olecranoid': ['lecanoroid', 'olecranoid'], + 'olecranon': ['encoronal', 'olecranon'], + 'olefin': ['enfoil', 'olefin'], + 'oleg': ['egol', 'goel', 'loge', 'ogle', 'oleg'], + 'olein': ['enoil', 'ileon', 'olein'], + 'olena': ['alone', 'anole', 'olena'], + 'olenid': ['doline', 'indole', 'leonid', 'loined', 'olenid'], + 'olent': ['lento', 'olent'], + 'olenus': ['ensoul', 'olenus', 'unsole'], + 'oleosity': ['oleosity', 'otiosely'], + 'olga': ['gaol', 'goal', 'gola', 'olga'], + 'oliban': ['albino', 'albion', 'alboin', 'oliban'], + 'olibanum': ['olibanum', 'umbonial'], + 'olid': ['dilo', 'diol', 'doli', 'idol', 'olid'], + 'oligoclase': ['oligoclase', 'sociolegal'], + 'oligomyoid': ['idiomology', 'oligomyoid'], + 'oligonephria': ['oligonephria', 'oligophrenia'], + 'oligonephric': ['oligonephric', 'oligophrenic'], + 'oligophrenia': ['oligonephria', 'oligophrenia'], + 'oligophrenic': ['oligonephric', 'oligophrenic'], + 'oliprance': ['oliprance', 'porcelain'], + 'oliva': ['oliva', 'viola'], + 'olivaceous': ['olivaceous', 'violaceous'], + 'olive': ['olive', 'ovile', 'voile'], + 'olived': ['livedo', 'olived'], + 'oliver': ['oliver', 'violer', 'virole'], + 'olivescent': ['olivescent', 'violescent'], + 'olivet': ['olivet', 'violet'], + 'olivetan': ['olivetan', 'velation'], + 'olivette': ['olivette', 'violette'], + 'olivine': ['olivine', 'violine'], + 'olla': ['lalo', 'lola', 'olla'], + 'olof': ['fool', 'loof', 'olof'], + 'olonets': ['enstool', 'olonets'], + 'olor': ['loro', 'olor', 'orlo', 'rool'], + 'olpe': ['lope', 'olpe', 'pole'], + 'olson': ['olson', 'solon'], + 'olympian': ['olympian', 'polymnia'], + 'om': ['mo', 'om'], + 'omaha': ['haoma', 'omaha'], + 'oman': ['mano', 'moan', 'mona', 'noam', 'noma', 'oman'], + 'omani': ['amino', 'inoma', 'naomi', 'omani', 'omina'], + 'omar': ['amor', 'maro', 'mora', 'omar', 'roam'], + 'omasitis': ['amitosis', 'omasitis'], + 'omber': ['brome', 'omber'], + 'omelet': ['omelet', 'telome'], + 'omen': ['mone', 'nome', 'omen'], + 'omened': ['endome', 'omened'], + 'omental': ['omental', 'telamon'], + 'omentotomy': ['entomotomy', 'omentotomy'], + 'omer': ['mero', 'more', 'omer', 'rome'], + 'omicron': ['moronic', 'omicron'], + 'omina': ['amino', 'inoma', 'naomi', 'omani', 'omina'], + 'ominous': ['mousoni', 'ominous'], + 'omit': ['itmo', 'moit', 'omit', 'timo'], + 'omitis': ['itoism', 'omitis'], + 'omniana': ['nanaimo', 'omniana'], + 'omniarch': ['choirman', 'harmonic', 'omniarch'], + 'omnigerent': ['ignorement', 'omnigerent'], + 'omnilegent': ['eloignment', 'omnilegent'], + 'omnimeter': ['minometer', 'omnimeter'], + 'omnimodous': ['monosodium', 'omnimodous', 'onosmodium'], + 'omnist': ['inmost', 'monist', 'omnist'], + 'omnitenent': ['intonement', 'omnitenent'], + 'omphalogenous': ['megalophonous', 'omphalogenous'], + 'on': ['no', 'on'], + 'ona': ['noa', 'ona'], + 'onager': ['onager', 'orange'], + 'onagra': ['agroan', 'angora', 'anogra', 'arango', 'argoan', 'onagra'], + 'onan': ['anon', 'nona', 'onan'], + 'onanism': ['mansion', 'onanism'], + 'onanistic': ['anconitis', 'antiscion', 'onanistic'], + 'onca': ['coan', 'onca'], + 'once': ['cone', 'once'], + 'oncetta': ['oncetta', 'tectona'], + 'onchidiidae': ['chionididae', 'onchidiidae'], + 'oncia': ['acoin', 'oncia'], + 'oncidium': ['conidium', 'mucinoid', 'oncidium'], + 'oncin': ['conin', 'nonic', 'oncin'], + 'oncometric': ['necrotomic', 'oncometric'], + 'oncometry': ['necrotomy', 'normocyte', 'oncometry'], + 'oncoming': ['gnomonic', 'oncoming'], + 'oncosimeter': ['oncosimeter', 'semicoronet'], + 'oncost': ['nostoc', 'oncost'], + 'ondagram': ['dragoman', 'garamond', 'ondagram'], + 'ondameter': ['emendator', 'ondameter'], + 'ondatra': ['adorant', 'ondatra'], + 'ondine': ['donnie', 'indone', 'ondine'], + 'ondy': ['ondy', 'yond'], + 'one': ['eon', 'neo', 'one'], + 'oneida': ['daoine', 'oneida'], + 'oneiric': ['ironice', 'oneiric'], + 'oneism': ['eonism', 'mesion', 'oneism', 'simeon'], + 'oneness': ['oneness', 'senones'], + 'oner': ['oner', 'rone'], + 'onery': ['eryon', 'onery'], + 'oniomania': ['oinomania', 'oniomania'], + 'oniomaniac': ['iconomania', 'oniomaniac'], + 'oniscidae': ['oniscidae', 'oscinidae', 'sciaenoid'], + 'onisciform': ['onisciform', 'somnorific'], + 'oniscoidea': ['iodocasein', 'oniscoidea'], + 'onkos': ['onkos', 'snook'], + 'onlepy': ['onlepy', 'openly'], + 'onliest': ['leonist', 'onliest'], + 'only': ['lyon', 'only'], + 'onmarch': ['monarch', 'nomarch', 'onmarch'], + 'onosmodium': ['monosodium', 'omnimodous', 'onosmodium'], + 'ons': ['ons', 'son'], + 'onset': ['onset', 'seton', 'steno', 'stone'], + 'onshore': ['onshore', 'sorehon'], + 'onside': ['deinos', 'donsie', 'inodes', 'onside'], + 'onsight': ['hosting', 'onsight'], + 'ontal': ['notal', 'ontal', 'talon', 'tolan', 'tonal'], + 'ontaric': ['anticor', 'carotin', 'cortina', 'ontaric'], + 'onto': ['onto', 'oont', 'toon'], + 'ontogenal': ['nonlegato', 'ontogenal'], + 'ontological': ['ontological', 'tonological'], + 'ontologism': ['monologist', 'nomologist', 'ontologism'], + 'ontology': ['ontology', 'tonology'], + 'onus': ['nosu', 'nous', 'onus'], + 'onymal': ['amylon', 'onymal'], + 'onymatic': ['cymation', 'myatonic', 'onymatic'], + 'onza': ['azon', 'onza', 'ozan'], + 'oocyte': ['coyote', 'oocyte'], + 'oodles': ['dolose', 'oodles', 'soodle'], + 'ooid': ['iodo', 'ooid'], + 'oolak': ['lokao', 'oolak'], + 'oolite': ['lootie', 'oolite'], + 'oometer': ['moreote', 'oometer'], + 'oons': ['oons', 'soon'], + 'oont': ['onto', 'oont', 'toon'], + 'oopak': ['oopak', 'pooka'], + 'oord': ['door', 'odor', 'oord', 'rood'], + 'opacate': ['opacate', 'peacoat'], + 'opacite': ['ectopia', 'opacite'], + 'opah': ['opah', 'paho', 'poha'], + 'opal': ['alop', 'opal'], + 'opalina': ['opalina', 'pianola'], + 'opalinine': ['opalinine', 'pleionian'], + 'opalize': ['epizoal', 'lopezia', 'opalize'], + 'opata': ['opata', 'patao', 'tapoa'], + 'opdalite': ['opdalite', 'petaloid'], + 'ope': ['ope', 'poe'], + 'opelet': ['eelpot', 'opelet'], + 'open': ['nope', 'open', 'peon', 'pone'], + 'opencast': ['capstone', 'opencast'], + 'opener': ['opener', 'reopen', 'repone'], + 'openly': ['onlepy', 'openly'], + 'openside': ['disponee', 'openside'], + 'operable': ['operable', 'ropeable'], + 'operae': ['aerope', 'operae'], + 'operant': ['operant', 'pronate', 'protean'], + 'operatic': ['aporetic', 'capriote', 'operatic'], + 'operatical': ['aporetical', 'operatical'], + 'operating': ['operating', 'pignorate'], + 'operatrix': ['expirator', 'operatrix'], + 'opercular': ['opercular', 'preocular'], + 'ophidion': ['ophidion', 'ophionid'], + 'ophionid': ['ophidion', 'ophionid'], + 'ophism': ['mopish', 'ophism'], + 'ophite': ['ethiop', 'ophite', 'peitho'], + 'opinant': ['opinant', 'pintano'], + 'opinator': ['opinator', 'tropaion'], + 'opiner': ['opiner', 'orpine', 'ponier'], + 'opiniaster': ['opiniaster', 'opiniastre'], + 'opiniastre': ['opiniaster', 'opiniastre'], + 'opiniatrety': ['opiniatrety', 'petitionary'], + 'opisometer': ['opisometer', 'opsiometer'], + 'opisthenar': ['opisthenar', 'spheration'], + 'opisthorchis': ['chirosophist', 'opisthorchis'], + 'oppian': ['oppian', 'papion', 'popian'], + 'opposer': ['opposer', 'propose'], + 'oppugn': ['oppugn', 'popgun'], + 'opsiometer': ['opisometer', 'opsiometer'], + 'opsonic': ['opsonic', 'pocosin'], + 'opsy': ['opsy', 'posy'], + 'opt': ['opt', 'pot', 'top'], + 'optable': ['optable', 'potable'], + 'optableness': ['optableness', 'potableness'], + 'optate': ['aptote', 'optate', 'potate', 'teapot'], + 'optation': ['optation', 'potation'], + 'optative': ['optative', 'potative'], + 'optic': ['optic', 'picot', 'topic'], + 'optical': ['capitol', 'coalpit', 'optical', 'topical'], + 'optically': ['optically', 'topically'], + 'optics': ['copist', 'coptis', 'optics', 'postic'], + 'optimal': ['optimal', 'palmito'], + 'option': ['option', 'potion'], + 'optional': ['antipolo', 'antipool', 'optional'], + 'optography': ['optography', 'topography'], + 'optological': ['optological', 'topological'], + 'optologist': ['optologist', 'topologist'], + 'optology': ['optology', 'topology'], + 'optometer': ['optometer', 'potometer'], + 'optophone': ['optophone', 'topophone'], + 'optotype': ['optotype', 'topotype'], + 'opulaster': ['opulaster', 'sportulae', 'sporulate'], + 'opulus': ['lupous', 'opulus'], + 'opuntia': ['opuntia', 'utopian'], + 'opus': ['opus', 'soup'], + 'opuscular': ['crapulous', 'opuscular'], + 'or': ['or', 'ro'], + 'ora': ['aro', 'oar', 'ora'], + 'orach': ['achor', 'chora', 'corah', 'orach', 'roach'], + 'oracle': ['carole', 'coaler', 'coelar', 'oracle', 'recoal'], + 'orad': ['dora', 'orad', 'road'], + 'oral': ['lora', 'oral'], + 'oralist': ['aristol', 'oralist', 'ortalis', 'striola'], + 'orality': ['orality', 'tailory'], + 'orang': ['angor', + 'argon', + 'goran', + 'grano', + 'groan', + 'nagor', + 'orang', + 'organ', + 'rogan', + 'ronga'], + 'orange': ['onager', 'orange'], + 'orangeist': ['goniaster', 'orangeist'], + 'oranger': ['groaner', 'oranger', 'organer'], + 'orangism': ['orangism', 'organism', 'sinogram'], + 'orangist': ['orangist', 'organist', 'roasting', 'signator'], + 'orangize': ['agonizer', 'orangize', 'organize'], + 'orant': ['orant', 'rotan', 'toran', 'trona'], + 'oraon': ['aroon', 'oraon'], + 'oratress': ['assertor', 'assorter', 'oratress', 'reassort'], + 'orb': ['bor', 'orb', 'rob'], + 'orbed': ['boder', 'orbed'], + 'orbic': ['boric', 'cribo', 'orbic'], + 'orbicle': ['bricole', 'corbeil', 'orbicle'], + 'orbicular': ['courbaril', 'orbicular'], + 'orbitale': ['betailor', 'laborite', 'orbitale'], + 'orbitelar': ['liberator', 'orbitelar'], + 'orbitelarian': ['irrationable', 'orbitelarian'], + 'orbitofrontal': ['frontoorbital', 'orbitofrontal'], + 'orbitonasal': ['nasoorbital', 'orbitonasal'], + 'orblet': ['bolter', 'orblet', 'reblot', 'rebolt'], + 'orbulina': ['orbulina', 'unilobar'], + 'orc': ['cor', 'cro', 'orc', 'roc'], + 'orca': ['acor', 'caro', 'cora', 'orca'], + 'orcadian': ['nocardia', 'orcadian'], + 'orcanet': ['enactor', 'necator', 'orcanet'], + 'orcein': ['cerion', 'coiner', 'neroic', 'orcein', 'recoin'], + 'orchat': ['cathro', 'orchat'], + 'orchel': ['chlore', 'choler', 'orchel'], + 'orchester': ['orchester', 'orchestre'], + 'orchestre': ['orchester', 'orchestre'], + 'orchic': ['choric', 'orchic'], + 'orchid': ['orchid', 'rhodic'], + 'orchidist': ['chorditis', 'orchidist'], + 'orchiocele': ['choriocele', 'orchiocele'], + 'orchitis': ['historic', 'orchitis'], + 'orcin': ['corin', 'noric', 'orcin'], + 'orcinol': ['colorin', 'orcinol'], + 'ordain': ['dorian', 'inroad', 'ordain'], + 'ordainer': ['inroader', 'ordainer', 'reordain'], + 'ordainment': ['antimodern', 'ordainment'], + 'ordanchite': ['achondrite', 'ditrochean', 'ordanchite'], + 'ordeal': ['loader', 'ordeal', 'reload'], + 'orderer': ['orderer', 'reorder'], + 'ordinable': ['bolderian', 'ordinable'], + 'ordinal': ['nailrod', 'ordinal', 'rinaldo', 'rodinal'], + 'ordinance': ['cerdonian', 'ordinance'], + 'ordinate': ['andorite', 'nadorite', 'ordinate', 'rodentia'], + 'ordinative': ['derivation', 'ordinative'], + 'ordinator': ['ordinator', 'radiotron'], + 'ordines': ['indorse', 'ordines', 'siredon', 'sordine'], + 'ordosite': ['oestroid', 'ordosite', 'ostreoid'], + 'ordu': ['dour', 'duro', 'ordu', 'roud'], + 'ore': ['oer', 'ore', 'roe'], + 'oread': ['adore', 'oared', 'oread'], + 'oreas': ['arose', 'oreas'], + 'orectic': ['cerotic', 'orectic'], + 'oreman': ['enamor', 'monera', 'oreman', 'romane'], + 'orenda': ['denaro', 'orenda'], + 'orendite': ['enteroid', 'orendite'], + 'orestean': ['orestean', 'resonate', 'stearone'], + 'orf': ['for', 'fro', 'orf'], + 'organ': ['angor', + 'argon', + 'goran', + 'grano', + 'groan', + 'nagor', + 'orang', + 'organ', + 'rogan', + 'ronga'], + 'organal': ['angolar', 'organal'], + 'organer': ['groaner', 'oranger', 'organer'], + 'organicism': ['organicism', 'organismic'], + 'organicist': ['organicist', 'organistic'], + 'organing': ['groaning', 'organing'], + 'organism': ['orangism', 'organism', 'sinogram'], + 'organismic': ['organicism', 'organismic'], + 'organist': ['orangist', 'organist', 'roasting', 'signator'], + 'organistic': ['organicist', 'organistic'], + 'organity': ['gyration', 'organity', 'ortygian'], + 'organize': ['agonizer', 'orangize', 'organize'], + 'organized': ['dragonize', 'organized'], + 'organoid': ['gordonia', 'organoid', 'rigadoon'], + 'organonymic': ['craniognomy', 'organonymic'], + 'organotin': ['gortonian', 'organotin'], + 'organule': ['lagunero', 'organule', 'uroglena'], + 'orgiasm': ['isogram', 'orgiasm'], + 'orgiast': ['agistor', 'agrotis', 'orgiast'], + 'orgic': ['corgi', 'goric', 'orgic'], + 'orgue': ['orgue', 'rogue', 'rouge'], + 'orgy': ['gory', 'gyro', 'orgy'], + 'oriel': ['oiler', 'oriel', 'reoil'], + 'orient': ['norite', 'orient'], + 'oriental': ['oriental', 'relation', 'tirolean'], + 'orientalism': ['misrelation', 'orientalism', 'relationism'], + 'orientalist': ['orientalist', 'relationist'], + 'orientate': ['anoterite', 'orientate'], + 'origanum': ['mirounga', 'moringua', 'origanum'], + 'origin': ['nigori', 'origin'], + 'orle': ['lore', 'orle', 'role'], + 'orlean': ['lenora', 'loaner', 'orlean', 'reloan'], + 'orleanist': ['lairstone', 'orleanist', 'serotinal'], + 'orleanistic': ['intersocial', 'orleanistic', 'sclerotinia'], + 'orlet': ['lerot', 'orlet', 'relot'], + 'orlo': ['loro', 'olor', 'orlo', 'rool'], + 'orna': ['nora', 'orna', 'roan'], + 'ornamenter': ['ornamenter', 'reornament'], + 'ornate': ['atoner', 'norate', 'ornate'], + 'ornately': ['neolatry', 'ornately', 'tyrolean'], + 'ornation': ['noration', 'ornation', 'orotinan'], + 'ornis': ['ornis', 'rosin'], + 'orniscopic': ['orniscopic', 'scorpionic'], + 'ornithomantic': ['ornithomantic', 'orthantimonic'], + 'ornithoptera': ['ornithoptera', 'prototherian'], + 'orogenetic': ['erotogenic', 'geocronite', 'orogenetic'], + 'orographical': ['colporrhagia', 'orographical'], + 'orography': ['gyrophora', 'orography'], + 'orotinan': ['noration', 'ornation', 'orotinan'], + 'orotund': ['orotund', 'rotundo'], + 'orphanism': ['manorship', 'orphanism'], + 'orpheon': ['orpheon', 'phorone'], + 'orpheus': ['ephorus', 'orpheus', 'upshore'], + 'orphical': ['orphical', 'rhopalic'], + 'orphism': ['orphism', 'rompish'], + 'orphize': ['orphize', 'phiroze'], + 'orpine': ['opiner', 'orpine', 'ponier'], + 'orsel': ['loser', 'orsel', 'rosel', 'soler'], + 'orselle': ['orselle', 'roselle'], + 'ort': ['ort', 'rot', 'tor'], + 'ortalid': ['dilator', 'ortalid'], + 'ortalis': ['aristol', 'oralist', 'ortalis', 'striola'], + 'ortet': ['ortet', 'otter', 'toter'], + 'orthal': ['harlot', 'orthal', 'thoral'], + 'orthantimonic': ['ornithomantic', 'orthantimonic'], + 'orthian': ['orthian', 'thorina'], + 'orthic': ['chorti', 'orthic', 'thoric', 'trochi'], + 'orthite': ['hortite', 'orthite', 'thorite'], + 'ortho': ['ortho', 'thoro'], + 'orthodromy': ['hydromotor', 'orthodromy'], + 'orthogamy': ['orthogamy', 'othygroma'], + 'orthogonial': ['orthogonial', 'orthologian'], + 'orthologian': ['orthogonial', 'orthologian'], + 'orthose': ['orthose', 'reshoot', 'shooter', 'soother'], + 'ortiga': ['agrito', 'ortiga'], + 'ortstein': ['ortstein', 'tenorist'], + 'ortygian': ['gyration', 'organity', 'ortygian'], + 'ortygine': ['genitory', 'ortygine'], + 'ory': ['ory', 'roy', 'yor'], + 'oryx': ['oryx', 'roxy'], + 'os': ['os', 'so'], + 'osamin': ['monias', 'osamin', 'osmina'], + 'osamine': ['monesia', 'osamine', 'osmanie'], + 'osc': ['cos', 'osc', 'soc'], + 'oscan': ['ascon', 'canso', 'oscan'], + 'oscar': ['arcos', 'crosa', 'oscar', 'sacro'], + 'oscella': ['callose', 'oscella'], + 'oscheal': ['oscheal', 'scholae'], + 'oscillance': ['clinoclase', 'oscillance'], + 'oscillaria': ['iliosacral', 'oscillaria'], + 'oscillation': ['colonialist', 'oscillation'], + 'oscin': ['oscin', 'scion', 'sonic'], + 'oscine': ['cosine', 'oscine'], + 'oscines': ['cession', 'oscines'], + 'oscinian': ['oscinian', 'socinian'], + 'oscinidae': ['oniscidae', 'oscinidae', 'sciaenoid'], + 'oscitant': ['actinost', 'oscitant'], + 'oscular': ['carolus', 'oscular'], + 'osculate': ['lacteous', 'osculate'], + 'osculatory': ['cotylosaur', 'osculatory'], + 'oscule': ['coleus', 'oscule'], + 'ose': ['oes', 'ose', 'soe'], + 'osela': ['alose', 'osela', 'solea'], + 'oshac': ['chaos', 'oshac'], + 'oside': ['diose', 'idose', 'oside'], + 'osier': ['osier', 'serio'], + 'osirian': ['nosairi', 'osirian'], + 'osiride': ['isidore', 'osiride'], + 'oskar': ['krosa', 'oskar'], + 'osmanie': ['monesia', 'osamine', 'osmanie'], + 'osmanli': ['malison', 'manolis', 'osmanli', 'somnial'], + 'osmatic': ['atomics', 'catoism', 'cosmati', 'osmatic', 'somatic'], + 'osmatism': ['osmatism', 'somatism'], + 'osmerus': ['osmerus', 'smouser'], + 'osmin': ['minos', 'osmin', 'simon'], + 'osmina': ['monias', 'osamin', 'osmina'], + 'osmiridium': ['iridosmium', 'osmiridium'], + 'osmogene': ['gonesome', 'osmogene'], + 'osmometer': ['merostome', 'osmometer'], + 'osmometric': ['microstome', 'osmometric'], + 'osmophore': ['osmophore', 'sophomore'], + 'osmotactic': ['osmotactic', 'scotomatic'], + 'osmunda': ['damnous', 'osmunda'], + 'osone': ['noose', 'osone'], + 'osprey': ['eryops', 'osprey'], + 'ossal': ['lasso', 'ossal'], + 'ossein': ['essoin', 'ossein'], + 'osselet': ['osselet', 'sestole', 'toeless'], + 'ossetian': ['assiento', 'ossetian'], + 'ossetine': ['essonite', 'ossetine'], + 'ossicle': ['loessic', 'ossicle'], + 'ossiculate': ['acleistous', 'ossiculate'], + 'ossicule': ['coulisse', 'leucosis', 'ossicule'], + 'ossuary': ['ossuary', 'suasory'], + 'ostara': ['aroast', 'ostara'], + 'osteal': ['lotase', 'osteal', 'solate', 'stolae', 'talose'], + 'ostearthritis': ['arthrosteitis', 'ostearthritis'], + 'ostectomy': ['cystotome', 'cytostome', 'ostectomy'], + 'ostein': ['nesiot', 'ostein'], + 'ostemia': ['miaotse', 'ostemia'], + 'ostent': ['ostent', 'teston'], + 'ostentation': ['ostentation', 'tionontates'], + 'ostentous': ['ostentous', 'sostenuto'], + 'osteometric': ['osteometric', 'stereotomic'], + 'osteometrical': ['osteometrical', 'stereotomical'], + 'osteometry': ['osteometry', 'stereotomy'], + 'ostic': ['ostic', 'sciot', 'stoic'], + 'ostmen': ['montes', 'ostmen'], + 'ostracea': ['ceratosa', 'ostracea'], + 'ostracean': ['ostracean', 'socratean'], + 'ostracine': ['atroscine', 'certosina', 'ostracine', 'tinoceras', 'tricosane'], + 'ostracism': ['ostracism', 'socratism'], + 'ostracize': ['ostracize', 'socratize'], + 'ostracon': ['ostracon', 'socotran'], + 'ostraite': ['astroite', 'ostraite', 'storiate'], + 'ostreidae': ['oestridae', 'ostreidae', 'sorediate'], + 'ostreiform': ['forritsome', 'ostreiform'], + 'ostreoid': ['oestroid', 'ordosite', 'ostreoid'], + 'ostrich': ['chorist', 'ostrich'], + 'oswald': ['dowlas', 'oswald'], + 'otalgy': ['goatly', 'otalgy'], + 'otaria': ['atorai', 'otaria'], + 'otarian': ['aration', 'otarian'], + 'otarine': ['otarine', 'torenia'], + 'other': ['other', 'thore', 'throe', 'toher'], + 'otherism': ['homerist', 'isotherm', 'otherism', 'theorism'], + 'otherist': ['otherist', 'theorist'], + 'othygroma': ['orthogamy', 'othygroma'], + 'otiant': ['otiant', 'titano'], + 'otidae': ['idotea', 'iodate', 'otidae'], + 'otidine': ['edition', 'odinite', 'otidine', 'tineoid'], + 'otiosely': ['oleosity', 'otiosely'], + 'otitis': ['itoist', 'otitis'], + 'oto': ['oto', 'too'], + 'otocephalic': ['hepatocolic', 'otocephalic'], + 'otocrane': ['coronate', 'octonare', 'otocrane'], + 'otogenic': ['geotonic', 'otogenic'], + 'otomian': ['amotion', 'otomian'], + 'otomyces': ['cytosome', 'otomyces'], + 'ottar': ['ottar', 'tarot', 'torta', 'troat'], + 'otter': ['ortet', 'otter', 'toter'], + 'otto': ['otto', 'toot', 'toto'], + 'otus': ['otus', 'oust', 'suto'], + 'otyak': ['otyak', 'tokay'], + 'ouch': ['chou', 'ouch'], + 'ouf': ['fou', 'ouf'], + 'ough': ['hugo', 'ough'], + 'ought': ['ought', 'tough'], + 'oughtness': ['oughtness', 'toughness'], + 'ounds': ['nodus', 'ounds', 'sound'], + 'our': ['our', 'uro'], + 'ours': ['ours', 'sour'], + 'oust': ['otus', 'oust', 'suto'], + 'ouster': ['ouster', 'souter', 'touser', 'trouse'], + 'out': ['out', 'tou'], + 'outarde': ['outarde', 'outdare', 'outread'], + 'outban': ['outban', 'unboat'], + 'outbar': ['outbar', 'rubato', 'tabour'], + 'outbeg': ['bouget', 'outbeg'], + 'outblow': ['blowout', 'outblow', 'outbowl'], + 'outblunder': ['outblunder', 'untroubled'], + 'outbowl': ['blowout', 'outblow', 'outbowl'], + 'outbreak': ['breakout', 'outbreak'], + 'outbred': ['doubter', 'obtrude', 'outbred', 'redoubt'], + 'outburn': ['burnout', 'outburn'], + 'outburst': ['outburst', 'subtutor'], + 'outbustle': ['outbustle', 'outsubtle'], + 'outcarol': ['outcarol', 'taurocol'], + 'outcarry': ['curatory', 'outcarry'], + 'outcase': ['acetous', 'outcase'], + 'outcharm': ['outcharm', 'outmarch'], + 'outcrier': ['courtier', 'outcrier'], + 'outcut': ['cutout', 'outcut'], + 'outdance': ['outdance', 'uncoated'], + 'outdare': ['outarde', 'outdare', 'outread'], + 'outdraw': ['drawout', 'outdraw', 'outward'], + 'outer': ['outer', 'outre', 'route'], + 'outerness': ['outerness', 'outreness'], + 'outferret': ['foreutter', 'outferret'], + 'outfit': ['fitout', 'outfit'], + 'outflare': ['fluorate', 'outflare'], + 'outfling': ['flouting', 'outfling'], + 'outfly': ['outfly', 'toyful'], + 'outgoer': ['outgoer', 'rougeot'], + 'outgrin': ['outgrin', 'outring', 'routing', 'touring'], + 'outhire': ['outhire', 'routhie'], + 'outhold': ['holdout', 'outhold'], + 'outkick': ['kickout', 'outkick'], + 'outlance': ['cleanout', 'outlance'], + 'outlay': ['layout', 'lutayo', 'outlay'], + 'outleap': ['outleap', 'outpeal'], + 'outler': ['elutor', 'louter', 'outler'], + 'outlet': ['outlet', 'tutelo'], + 'outline': ['elution', 'outline'], + 'outlinear': ['outlinear', 'uranolite'], + 'outlined': ['outlined', 'untoiled'], + 'outlook': ['lookout', 'outlook'], + 'outly': ['louty', 'outly'], + 'outman': ['amount', 'moutan', 'outman'], + 'outmarch': ['outcharm', 'outmarch'], + 'outmarry': ['mortuary', 'outmarry'], + 'outmaster': ['outmaster', 'outstream'], + 'outname': ['notaeum', 'outname'], + 'outpaint': ['outpaint', 'putation'], + 'outpass': ['outpass', 'passout'], + 'outpay': ['outpay', 'tapuyo'], + 'outpeal': ['outleap', 'outpeal'], + 'outpitch': ['outpitch', 'pitchout'], + 'outplace': ['copulate', 'outplace'], + 'outprice': ['eutropic', 'outprice'], + 'outpromise': ['outpromise', 'peritomous'], + 'outrance': ['cornuate', 'courante', 'cuneator', 'outrance'], + 'outrate': ['outrate', 'outtear', 'torteau'], + 'outre': ['outer', 'outre', 'route'], + 'outread': ['outarde', 'outdare', 'outread'], + 'outremer': ['outremer', 'urometer'], + 'outreness': ['outerness', 'outreness'], + 'outring': ['outgrin', 'outring', 'routing', 'touring'], + 'outrun': ['outrun', 'runout'], + 'outsaint': ['outsaint', 'titanous'], + 'outscream': ['castoreum', 'outscream'], + 'outsell': ['outsell', 'sellout'], + 'outset': ['outset', 'setout'], + 'outshake': ['outshake', 'shakeout'], + 'outshape': ['outshape', 'taphouse'], + 'outshine': ['outshine', 'tinhouse'], + 'outshut': ['outshut', 'shutout'], + 'outside': ['outside', 'tedious'], + 'outsideness': ['outsideness', 'tediousness'], + 'outsigh': ['goutish', 'outsigh'], + 'outsin': ['outsin', 'ustion'], + 'outslide': ['outslide', 'solitude'], + 'outsnore': ['outsnore', 'urosteon'], + 'outsoler': ['outsoler', 'torulose'], + 'outspend': ['outspend', 'unposted'], + 'outspit': ['outspit', 'utopist'], + 'outspring': ['outspring', 'sprouting'], + 'outspurn': ['outspurn', 'portunus'], + 'outstair': ['outstair', 'ratitous'], + 'outstand': ['outstand', 'standout'], + 'outstate': ['outstate', 'outtaste'], + 'outstream': ['outmaster', 'outstream'], + 'outstreet': ['outstreet', 'tetterous'], + 'outsubtle': ['outbustle', 'outsubtle'], + 'outtaste': ['outstate', 'outtaste'], + 'outtear': ['outrate', 'outtear', 'torteau'], + 'outthrough': ['outthrough', 'throughout'], + 'outthrow': ['outthrow', 'outworth', 'throwout'], + 'outtrail': ['outtrail', 'tutorial'], + 'outturn': ['outturn', 'turnout'], + 'outturned': ['outturned', 'untutored'], + 'outwalk': ['outwalk', 'walkout'], + 'outward': ['drawout', 'outdraw', 'outward'], + 'outwash': ['outwash', 'washout'], + 'outwatch': ['outwatch', 'watchout'], + 'outwith': ['outwith', 'without'], + 'outwork': ['outwork', 'workout'], + 'outworth': ['outthrow', 'outworth', 'throwout'], + 'ova': ['avo', 'ova'], + 'ovaloid': ['ovaloid', 'ovoidal'], + 'ovarial': ['ovarial', 'variola'], + 'ovariotubal': ['ovariotubal', 'tuboovarial'], + 'ovational': ['avolation', 'ovational'], + 'oven': ['nevo', 'oven'], + 'ovenly': ['lenvoy', 'ovenly'], + 'ovenpeel': ['envelope', 'ovenpeel'], + 'over': ['over', 'rove'], + 'overaction': ['overaction', 'revocation'], + 'overactive': ['overactive', 'revocative'], + 'overall': ['allover', 'overall'], + 'overblame': ['overblame', 'removable'], + 'overblow': ['overblow', 'overbowl'], + 'overboil': ['boilover', 'overboil'], + 'overbowl': ['overblow', 'overbowl'], + 'overbreak': ['breakover', 'overbreak'], + 'overburden': ['overburden', 'overburned'], + 'overburn': ['burnover', 'overburn'], + 'overburned': ['overburden', 'overburned'], + 'overcall': ['overcall', 'vocaller'], + 'overcare': ['overcare', 'overrace'], + 'overcirculate': ['overcirculate', 'uterocervical'], + 'overcoat': ['evocator', 'overcoat'], + 'overcross': ['crossover', 'overcross'], + 'overcup': ['overcup', 'upcover'], + 'overcurious': ['erucivorous', 'overcurious'], + 'overcurtain': ['countervair', 'overcurtain', 'recurvation'], + 'overcut': ['cutover', 'overcut'], + 'overdamn': ['overdamn', 'ravendom'], + 'overdare': ['overdare', 'overdear', 'overread'], + 'overdeal': ['overdeal', 'overlade', 'overlead'], + 'overdear': ['overdare', 'overdear', 'overread'], + 'overdraw': ['overdraw', 'overward'], + 'overdrawer': ['overdrawer', 'overreward'], + 'overdrip': ['overdrip', 'provider'], + 'overdure': ['devourer', 'overdure', 'overrude'], + 'overdust': ['overdust', 'overstud'], + 'overedit': ['overedit', 'overtide'], + 'overfar': ['favorer', 'overfar', 'refavor'], + 'overfile': ['forelive', 'overfile'], + 'overfilm': ['overfilm', 'veliform'], + 'overflower': ['overflower', 'reoverflow'], + 'overforce': ['forecover', 'overforce'], + 'overgaiter': ['overgaiter', 'revigorate'], + 'overglint': ['overglint', 'revolting'], + 'overgo': ['groove', 'overgo'], + 'overgrain': ['granivore', 'overgrain'], + 'overhate': ['overhate', 'overheat'], + 'overheat': ['overhate', 'overheat'], + 'overheld': ['overheld', 'verdelho'], + 'overidle': ['evildoer', 'overidle'], + 'overink': ['invoker', 'overink'], + 'overinsist': ['overinsist', 'versionist'], + 'overkeen': ['overkeen', 'overknee'], + 'overknee': ['overkeen', 'overknee'], + 'overlade': ['overdeal', 'overlade', 'overlead'], + 'overlast': ['overlast', 'oversalt'], + 'overlate': ['elevator', 'overlate'], + 'overlay': ['layover', 'overlay'], + 'overlead': ['overdeal', 'overlade', 'overlead'], + 'overlean': ['overlean', 'valerone'], + 'overleg': ['overleg', 'reglove'], + 'overlie': ['overlie', 'relievo'], + 'overling': ['lovering', 'overling'], + 'overlisten': ['overlisten', 'oversilent'], + 'overlive': ['overlive', 'overveil'], + 'overly': ['overly', 'volery'], + 'overmantel': ['overmantel', 'overmantle'], + 'overmantle': ['overmantel', 'overmantle'], + 'overmaster': ['overmaster', 'overstream'], + 'overmean': ['overmean', 'overname'], + 'overmerit': ['overmerit', 'overtimer'], + 'overname': ['overmean', 'overname'], + 'overneat': ['overneat', 'renovate'], + 'overnew': ['overnew', 'rewoven'], + 'overnigh': ['hovering', 'overnigh'], + 'overpaint': ['overpaint', 'pronative'], + 'overpass': ['overpass', 'passover'], + 'overpet': ['overpet', 'preveto', 'prevote'], + 'overpick': ['overpick', 'pickover'], + 'overplain': ['overplain', 'parvoline'], + 'overply': ['overply', 'plovery'], + 'overpointed': ['overpointed', 'predevotion'], + 'overpot': ['overpot', 'overtop'], + 'overrace': ['overcare', 'overrace'], + 'overrate': ['overrate', 'overtare'], + 'overread': ['overdare', 'overdear', 'overread'], + 'overreward': ['overdrawer', 'overreward'], + 'overrude': ['devourer', 'overdure', 'overrude'], + 'overrun': ['overrun', 'runover'], + 'oversad': ['oversad', 'savored'], + 'oversale': ['oversale', 'overseal'], + 'oversalt': ['overlast', 'oversalt'], + 'oversauciness': ['oversauciness', 'veraciousness'], + 'overseal': ['oversale', 'overseal'], + 'overseen': ['overseen', 'veronese'], + 'overset': ['overset', 'setover'], + 'oversilent': ['overlisten', 'oversilent'], + 'overslip': ['overslip', 'slipover'], + 'overspread': ['overspread', 'spreadover'], + 'overstain': ['overstain', 'servation', 'versation'], + 'overstir': ['overstir', 'servitor'], + 'overstrain': ['overstrain', 'traversion'], + 'overstream': ['overmaster', 'overstream'], + 'overstrew': ['overstrew', 'overwrest'], + 'overstud': ['overdust', 'overstud'], + 'overt': ['overt', 'rovet', 'torve', 'trove', 'voter'], + 'overtare': ['overrate', 'overtare'], + 'overthrow': ['overthrow', 'overwroth'], + 'overthwart': ['overthwart', 'thwartover'], + 'overtide': ['overedit', 'overtide'], + 'overtime': ['overtime', 'remotive'], + 'overtimer': ['overmerit', 'overtimer'], + 'overtip': ['overtip', 'pivoter'], + 'overtop': ['overpot', 'overtop'], + 'overtrade': ['overtrade', 'overtread'], + 'overtread': ['overtrade', 'overtread'], + 'overtrue': ['overtrue', 'overture', 'trouvere'], + 'overture': ['overtrue', 'overture', 'trouvere'], + 'overturn': ['overturn', 'turnover'], + 'overtwine': ['interwove', 'overtwine'], + 'overveil': ['overlive', 'overveil'], + 'overwalk': ['overwalk', 'walkover'], + 'overward': ['overdraw', 'overward'], + 'overwrest': ['overstrew', 'overwrest'], + 'overwroth': ['overthrow', 'overwroth'], + 'ovest': ['ovest', 'stove'], + 'ovidae': ['evodia', 'ovidae'], + 'ovidian': ['ovidian', 'vidonia'], + 'ovile': ['olive', 'ovile', 'voile'], + 'ovillus': ['ovillus', 'villous'], + 'oviparous': ['apivorous', 'oviparous'], + 'ovist': ['ovist', 'visto'], + 'ovistic': ['covisit', 'ovistic'], + 'ovoidal': ['ovaloid', 'ovoidal'], + 'ovular': ['louvar', 'ovular'], + 'ow': ['ow', 'wo'], + 'owd': ['dow', 'owd', 'wod'], + 'owe': ['owe', 'woe'], + 'owen': ['enow', 'owen', 'wone'], + 'owenism': ['owenism', 'winsome'], + 'ower': ['ower', 'wore'], + 'owerby': ['bowery', 'bowyer', 'owerby'], + 'owl': ['low', 'lwo', 'owl'], + 'owler': ['lower', 'owler', 'rowel'], + 'owlery': ['lowery', 'owlery', 'rowley', 'yowler'], + 'owlet': ['owlet', 'towel'], + 'owlish': ['lowish', 'owlish'], + 'owlishly': ['lowishly', 'owlishly', 'sillyhow'], + 'owlishness': ['lowishness', 'owlishness'], + 'owly': ['lowy', 'owly', 'yowl'], + 'own': ['now', 'own', 'won'], + 'owner': ['owner', 'reown', 'rowen'], + 'ownership': ['ownership', 'shipowner'], + 'ownness': ['nowness', 'ownness'], + 'owser': ['owser', 'resow', 'serow', 'sower', 'swore', 'worse'], + 'oxalan': ['axonal', 'oxalan'], + 'oxalite': ['aloxite', 'oxalite'], + 'oxan': ['axon', 'noxa', 'oxan'], + 'oxanic': ['anoxic', 'oxanic'], + 'oxazine': ['azoxine', 'oxazine'], + 'oxen': ['exon', 'oxen'], + 'oxidic': ['ixodic', 'oxidic'], + 'oximate': ['oximate', 'toxemia'], + 'oxy': ['oxy', 'yox'], + 'oxyntic': ['ictonyx', 'oxyntic'], + 'oxyphenol': ['oxyphenol', 'xylophone'], + 'oxyterpene': ['enteropexy', 'oxyterpene'], + 'oyer': ['oyer', 'roey', 'yore'], + 'oyster': ['oyster', 'rosety'], + 'oysterish': ['oysterish', 'thyreosis'], + 'oysterman': ['monastery', 'oysterman'], + 'ozan': ['azon', 'onza', 'ozan'], + 'ozena': ['neoza', 'ozena'], + 'ozonate': ['entozoa', 'ozonate'], + 'ozonic': ['ozonic', 'zoonic'], + 'ozotype': ['ozotype', 'zootype'], + 'paal': ['paal', 'pala'], + 'paar': ['apar', 'paar', 'para'], + 'pablo': ['pablo', 'polab'], + 'pac': ['cap', 'pac'], + 'pacable': ['capable', 'pacable'], + 'pacation': ['copatain', 'pacation'], + 'pacaya': ['cayapa', 'pacaya'], + 'pace': ['cape', 'cepa', 'pace'], + 'paced': ['caped', 'decap', 'paced'], + 'pacer': ['caper', 'crape', 'pacer', 'perca', 'recap'], + 'pachnolite': ['pachnolite', 'phonetical'], + 'pachometer': ['pachometer', 'phacometer'], + 'pacht': ['chapt', 'pacht', 'patch'], + 'pachylosis': ['pachylosis', 'phacolysis'], + 'pacificist': ['pacificist', 'pacifistic'], + 'pacifistic': ['pacificist', 'pacifistic'], + 'packer': ['packer', 'repack'], + 'paco': ['copa', 'paco'], + 'pacolet': ['pacolet', 'polecat'], + 'paction': ['caption', 'paction'], + 'pactional': ['pactional', 'pactolian', 'placation'], + 'pactionally': ['pactionally', 'polyactinal'], + 'pactolian': ['pactional', 'pactolian', 'placation'], + 'pad': ['dap', 'pad'], + 'padda': ['dadap', 'padda'], + 'padder': ['padder', 'parded'], + 'padfoot': ['footpad', 'padfoot'], + 'padle': ['padle', 'paled', 'pedal', 'plead'], + 'padre': ['drape', 'padre'], + 'padtree': ['padtree', 'predate', 'tapered'], + 'paean': ['apnea', 'paean'], + 'paeanism': ['paeanism', 'spanemia'], + 'paegel': ['paegel', 'paegle', 'pelage'], + 'paegle': ['paegel', 'paegle', 'pelage'], + 'paga': ['gapa', 'paga'], + 'page': ['gape', 'page', 'peag', 'pega'], + 'pagedom': ['megapod', 'pagedom'], + 'pager': ['gaper', 'grape', 'pager', 'parge'], + 'pageship': ['pageship', 'shippage'], + 'paginary': ['agrypnia', 'paginary'], + 'paguridae': ['paguridae', 'paguridea'], + 'paguridea': ['paguridae', 'paguridea'], + 'pagurine': ['pagurine', 'perugian'], + 'pah': ['hap', 'pah'], + 'pahari': ['pahari', 'pariah', 'raphia'], + 'pahi': ['hapi', 'pahi'], + 'paho': ['opah', 'paho', 'poha'], + 'paigle': ['paigle', 'pilage'], + 'paik': ['paik', 'pika'], + 'pail': ['lipa', 'pail', 'pali', 'pial'], + 'paillasse': ['paillasse', 'palliasse'], + 'pain': ['nipa', 'pain', 'pani', 'pian', 'pina'], + 'painless': ['painless', 'spinales'], + 'paint': ['inapt', 'paint', 'pinta'], + 'painted': ['depaint', 'inadept', 'painted', 'patined'], + 'painter': ['painter', 'pertain', 'pterian', 'repaint'], + 'painterly': ['interplay', 'painterly'], + 'paintiness': ['antisepsin', 'paintiness'], + 'paip': ['paip', 'pipa'], + 'pair': ['pair', 'pari', 'pria', 'ripa'], + 'paired': ['diaper', 'paired'], + 'pairer': ['pairer', 'rapier', 'repair'], + 'pairment': ['imperant', 'pairment', 'partimen', 'premiant', 'tripeman'], + 'pais': ['apis', 'pais', 'pasi', 'saip'], + 'pajonism': ['japonism', 'pajonism'], + 'pal': ['alp', 'lap', 'pal'], + 'pala': ['paal', 'pala'], + 'palaeechinoid': ['deinocephalia', 'palaeechinoid'], + 'palaemonid': ['anomaliped', 'palaemonid'], + 'palaemonoid': ['adenolipoma', 'palaemonoid'], + 'palaeornis': ['palaeornis', 'personalia'], + 'palaestrics': ['palaestrics', 'paracelsist'], + 'palaic': ['apical', 'palaic'], + 'palaite': ['palaite', 'petalia', 'pileata'], + 'palame': ['palame', 'palmae', 'pamela'], + 'palamite': ['ampliate', 'palamite'], + 'palas': ['palas', 'salpa'], + 'palate': ['aletap', 'palate', 'platea'], + 'palatial': ['palatial', 'palliata'], + 'palatic': ['capital', 'palatic'], + 'palation': ['palation', 'talapoin'], + 'palatonasal': ['nasopalatal', 'palatonasal'], + 'palau': ['palau', 'paula'], + 'palay': ['palay', 'playa'], + 'pale': ['leap', 'lepa', 'pale', 'peal', 'plea'], + 'paled': ['padle', 'paled', 'pedal', 'plead'], + 'paleness': ['paleness', 'paneless'], + 'paleolithy': ['paleolithy', 'polyhalite', 'polythelia'], + 'paler': ['lepra', 'paler', 'parel', 'parle', 'pearl', 'perla', 'relap'], + 'palermitan': ['palermitan', 'parliament'], + 'palermo': ['leproma', 'palermo', 'pleroma', 'polearm'], + 'pales': ['elaps', + 'lapse', + 'lepas', + 'pales', + 'salep', + 'saple', + 'sepal', + 'slape', + 'spale', + 'speal'], + 'palestral': ['alpestral', 'palestral'], + 'palestrian': ['alpestrian', 'palestrian', 'psalterian'], + 'palet': ['leapt', + 'palet', + 'patel', + 'pelta', + 'petal', + 'plate', + 'pleat', + 'tepal'], + 'palette': ['palette', 'peltate'], + 'pali': ['lipa', 'pail', 'pali', 'pial'], + 'palification': ['palification', 'pontificalia'], + 'palinode': ['lapideon', 'palinode', 'pedalion'], + 'palinodist': ['palinodist', 'plastinoid'], + 'palisade': ['palisade', 'salpidae'], + 'palish': ['palish', 'silpha'], + 'pallasite': ['aliseptal', 'pallasite'], + 'pallette': ['pallette', 'platelet'], + 'palliasse': ['paillasse', 'palliasse'], + 'palliata': ['palatial', 'palliata'], + 'pallone': ['pallone', 'pleonal'], + 'palluites': ['palluites', 'pulsatile'], + 'palm': ['lamp', 'palm'], + 'palmad': ['lampad', 'palmad'], + 'palmae': ['palame', 'palmae', 'pamela'], + 'palmary': ['palmary', 'palmyra'], + 'palmatilobed': ['palmatilobed', 'palmilobated'], + 'palmatisect': ['metaplastic', 'palmatisect'], + 'palmer': ['lamper', 'palmer', 'relamp'], + 'palmery': ['lamprey', 'palmery'], + 'palmette': ['palmette', 'template'], + 'palmful': ['lampful', 'palmful'], + 'palmification': ['amplification', 'palmification'], + 'palmilobated': ['palmatilobed', 'palmilobated'], + 'palmipes': ['epiplasm', 'palmipes'], + 'palmist': ['lampist', 'palmist'], + 'palmister': ['palmister', 'prelatism'], + 'palmistry': ['lampistry', 'palmistry'], + 'palmite': ['implate', 'palmite'], + 'palmito': ['optimal', 'palmito'], + 'palmitone': ['emptional', 'palmitone'], + 'palmo': ['mopla', 'palmo'], + 'palmula': ['ampulla', 'palmula'], + 'palmy': ['amply', 'palmy'], + 'palmyra': ['palmary', 'palmyra'], + 'palolo': ['apollo', 'palolo'], + 'palp': ['lapp', 'palp', 'plap'], + 'palpal': ['appall', 'palpal'], + 'palpatory': ['palpatory', 'papolatry'], + 'palped': ['dapple', 'lapped', 'palped'], + 'palpi': ['palpi', 'pipal'], + 'palster': ['palster', 'persalt', 'plaster', 'psalter', 'spartle', 'stapler'], + 'palsy': ['palsy', 'splay'], + 'palt': ['palt', 'plat'], + 'palta': ['aptal', 'palta', 'talpa'], + 'palter': ['palter', 'plater'], + 'palterer': ['palterer', 'platerer'], + 'paltry': ['paltry', 'partly', 'raptly'], + 'paludian': ['paludian', 'paludina'], + 'paludic': ['paludic', 'pudical'], + 'paludina': ['paludian', 'paludina'], + 'palus': ['palus', 'pasul'], + 'palustral': ['palustral', 'plaustral'], + 'palustrine': ['lupinaster', 'palustrine'], + 'paly': ['paly', 'play', 'pyal', 'pyla'], + 'pam': ['map', 'pam'], + 'pamela': ['palame', 'palmae', 'pamela'], + 'pamir': ['impar', 'pamir', 'prima'], + 'pamiri': ['impair', 'pamiri'], + 'pamper': ['mapper', 'pamper', 'pampre'], + 'pampre': ['mapper', 'pamper', 'pampre'], + 'pan': ['nap', 'pan'], + 'panace': ['canape', 'panace'], + 'panaceist': ['antispace', 'panaceist'], + 'panade': ['napead', 'panade'], + 'panak': ['kanap', 'panak'], + 'panamist': ['mainpast', 'mantispa', 'panamist', 'stampian'], + 'panary': ['panary', 'panyar'], + 'panatela': ['panatela', 'plataean'], + 'panatrophy': ['apanthropy', 'panatrophy'], + 'pancreatoduodenectomy': ['duodenopancreatectomy', 'pancreatoduodenectomy'], + 'pandean': ['pandean', 'pannade'], + 'pandemia': ['pandemia', 'pedimana'], + 'pander': ['pander', 'repand'], + 'panderly': ['panderly', 'repandly'], + 'pandermite': ['pandermite', 'pentamerid'], + 'panderous': ['panderous', 'repandous'], + 'pandion': ['dipnoan', 'nonpaid', 'pandion'], + 'pandour': ['pandour', 'poduran'], + 'pane': ['nape', 'neap', 'nepa', 'pane', 'pean'], + 'paned': ['paned', 'penda'], + 'panel': ['alpen', 'nepal', 'panel', 'penal', 'plane'], + 'panela': ['apneal', 'panela'], + 'panelation': ['antelopian', 'neapolitan', 'panelation'], + 'paneler': ['paneler', 'repanel', 'replane'], + 'paneless': ['paleness', 'paneless'], + 'panelist': ['panelist', 'pantelis', 'penalist', 'plastein'], + 'pangamic': ['campaign', 'pangamic'], + 'pangane': ['pangane', 'pannage'], + 'pangen': ['pangen', 'penang'], + 'pangene': ['pangene', 'pennage'], + 'pangi': ['aping', 'ngapi', 'pangi'], + 'pani': ['nipa', 'pain', 'pani', 'pian', 'pina'], + 'panicle': ['calepin', 'capelin', 'panicle', 'pelican', 'pinacle'], + 'paniculitis': ['paniculitis', 'paulinistic'], + 'panisca': ['capsian', 'caspian', 'nascapi', 'panisca'], + 'panisic': ['panisic', 'piscian', 'piscina', 'sinapic'], + 'pank': ['knap', 'pank'], + 'pankin': ['napkin', 'pankin'], + 'panman': ['panman', 'pannam'], + 'panmug': ['panmug', 'pugman'], + 'pannade': ['pandean', 'pannade'], + 'pannage': ['pangane', 'pannage'], + 'pannam': ['panman', 'pannam'], + 'panne': ['panne', 'penna'], + 'pannicle': ['pannicle', 'pinnacle'], + 'pannus': ['pannus', 'sannup', 'unsnap', 'unspan'], + 'panoche': ['copehan', 'panoche', 'phocean'], + 'panoistic': ['panoistic', 'piscation'], + 'panornithic': ['panornithic', 'rhaponticin'], + 'panostitis': ['antiptosis', 'panostitis'], + 'panplegia': ['appealing', 'lagniappe', 'panplegia'], + 'pansciolist': ['costispinal', 'pansciolist'], + 'panse': ['aspen', 'panse', 'snape', 'sneap', 'spane', 'spean'], + 'panside': ['ipseand', 'panside', 'pansied'], + 'pansied': ['ipseand', 'panside', 'pansied'], + 'pansy': ['pansy', 'snapy'], + 'pantaleon': ['pantaleon', 'pantalone'], + 'pantalone': ['pantaleon', 'pantalone'], + 'pantarchy': ['pantarchy', 'pyracanth'], + 'pantelis': ['panelist', 'pantelis', 'penalist', 'plastein'], + 'pantellerite': ['interpellate', 'pantellerite'], + 'panter': ['arpent', + 'enrapt', + 'entrap', + 'panter', + 'parent', + 'pretan', + 'trepan'], + 'pantheic': ['haptenic', 'pantheic', 'pithecan'], + 'pantheonic': ['nonhepatic', 'pantheonic'], + 'pantie': ['pantie', 'patine'], + 'panties': ['panties', 'sapient', 'spinate'], + 'pantile': ['pantile', 'pentail', 'platine', 'talpine'], + 'pantle': ['pantle', 'planet', 'platen'], + 'pantler': ['pantler', 'planter', 'replant'], + 'pantofle': ['felapton', 'pantofle'], + 'pantry': ['pantry', 'trypan'], + 'panyar': ['panary', 'panyar'], + 'papabot': ['papabot', 'papboat'], + 'papal': ['lappa', 'papal'], + 'papalistic': ['papalistic', 'papistical'], + 'papboat': ['papabot', 'papboat'], + 'paper': ['paper', 'rappe'], + 'papered': ['papered', 'pradeep'], + 'paperer': ['paperer', 'perpera', 'prepare', 'repaper'], + 'papern': ['napper', 'papern'], + 'papery': ['papery', 'prepay', 'yapper'], + 'papillote': ['papillote', 'popliteal'], + 'papion': ['oppian', 'papion', 'popian'], + 'papisher': ['papisher', 'sapphire'], + 'papistical': ['papalistic', 'papistical'], + 'papless': ['papless', 'sapples'], + 'papolatry': ['palpatory', 'papolatry'], + 'papule': ['papule', 'upleap'], + 'par': ['par', 'rap'], + 'para': ['apar', 'paar', 'para'], + 'parablepsia': ['appraisable', 'parablepsia'], + 'paracelsist': ['palaestrics', 'paracelsist'], + 'parachor': ['chaparro', 'parachor'], + 'paracolitis': ['paracolitis', 'piscatorial'], + 'paradisaic': ['paradisaic', 'paradisiac'], + 'paradisaically': ['paradisaically', 'paradisiacally'], + 'paradise': ['paradise', 'sparidae'], + 'paradisiac': ['paradisaic', 'paradisiac'], + 'paradisiacally': ['paradisaically', 'paradisiacally'], + 'parado': ['parado', 'pardao'], + 'paraenetic': ['capernaite', 'paraenetic'], + 'paragrapher': ['paragrapher', 'reparagraph'], + 'parah': ['aphra', 'harpa', 'parah'], + 'parale': ['earlap', 'parale'], + 'param': ['param', 'parma', 'praam'], + 'paramine': ['amperian', 'paramine', 'pearmain'], + 'paranephric': ['paranephric', 'paraphrenic'], + 'paranephritis': ['paranephritis', 'paraphrenitis'], + 'paranosic': ['caparison', 'paranosic'], + 'paraphrenic': ['paranephric', 'paraphrenic'], + 'paraphrenitis': ['paranephritis', 'paraphrenitis'], + 'parasita': ['aspirata', 'parasita'], + 'parasite': ['aspirate', 'parasite'], + 'parasol': ['asaprol', 'parasol'], + 'parasuchian': ['parasuchian', 'unpharasaic'], + 'parasyntheton': ['parasyntheton', 'thysanopteran'], + 'parate': ['aptera', 'parate', 'patera'], + 'parathion': ['parathion', 'phanariot'], + 'parazoan': ['parazoan', 'zaparoan'], + 'parboil': ['bipolar', 'parboil'], + 'parcel': ['carpel', 'parcel', 'placer'], + 'parcellary': ['carpellary', 'parcellary'], + 'parcellate': ['carpellate', 'parcellate', 'prelacteal'], + 'parchesi': ['parchesi', 'seraphic'], + 'pard': ['pard', 'prad'], + 'pardao': ['parado', 'pardao'], + 'parded': ['padder', 'parded'], + 'pardesi': ['despair', 'pardesi'], + 'pardo': ['adrop', 'pardo'], + 'pardoner': ['pardoner', 'preadorn'], + 'pare': ['aper', 'pare', 'pear', 'rape', 'reap'], + 'parel': ['lepra', 'paler', 'parel', 'parle', 'pearl', 'perla', 'relap'], + 'paren': ['arpen', 'paren'], + 'parent': ['arpent', + 'enrapt', + 'entrap', + 'panter', + 'parent', + 'pretan', + 'trepan'], + 'parental': ['parental', 'paternal', 'prenatal'], + 'parentalia': ['parentalia', 'planetaria'], + 'parentalism': ['parentalism', 'paternalism'], + 'parentality': ['parentality', 'paternality'], + 'parentally': ['parentally', 'paternally', 'prenatally'], + 'parentelic': ['epicentral', 'parentelic'], + 'parenticide': ['parenticide', 'preindicate'], + 'parer': ['parer', 'raper'], + 'paresis': ['paresis', 'serapis'], + 'paretic': ['paretic', 'patrice', 'picrate'], + 'parge': ['gaper', 'grape', 'pager', 'parge'], + 'pari': ['pair', 'pari', 'pria', 'ripa'], + 'pariah': ['pahari', 'pariah', 'raphia'], + 'paridae': ['deipara', 'paridae'], + 'paries': ['aspire', 'paries', 'praise', 'sirpea', 'spirea'], + 'parietal': ['apterial', 'parietal'], + 'parietes': ['asperite', 'parietes'], + 'parietofrontal': ['frontoparietal', 'parietofrontal'], + 'parietosquamosal': ['parietosquamosal', 'squamosoparietal'], + 'parietotemporal': ['parietotemporal', 'temporoparietal'], + 'parietovisceral': ['parietovisceral', 'visceroparietal'], + 'parine': ['parine', 'rapine'], + 'paring': ['paring', 'raping'], + 'paris': ['paris', 'parsi', 'sarip'], + 'parish': ['parish', 'raphis', 'rhapis'], + 'parished': ['diphaser', 'parished', 'raphides', 'sephardi'], + 'parison': ['parison', 'soprani'], + 'parity': ['parity', 'piraty'], + 'parkee': ['parkee', 'peaker'], + 'parker': ['parker', 'repark'], + 'parlatory': ['parlatory', 'portrayal'], + 'parle': ['lepra', 'paler', 'parel', 'parle', 'pearl', 'perla', 'relap'], + 'parley': ['parley', 'pearly', 'player', 'replay'], + 'parliament': ['palermitan', 'parliament'], + 'parly': ['parly', 'pylar', 'pyral'], + 'parma': ['param', 'parma', 'praam'], + 'parmesan': ['parmesan', 'spearman'], + 'parnel': ['parnel', 'planer', 'replan'], + 'paroch': ['carhop', 'paroch'], + 'parochialism': ['aphorismical', 'parochialism'], + 'parochine': ['canephroi', 'parochine'], + 'parodic': ['parodic', 'picador'], + 'paroecism': ['paroecism', 'premosaic'], + 'parol': ['parol', 'polar', 'poral', 'proal'], + 'parosela': ['parosela', 'psoralea'], + 'parosteal': ['parosteal', 'pastorale'], + 'parostotic': ['parostotic', 'postaortic'], + 'parotia': ['apiator', 'atropia', 'parotia'], + 'parotic': ['apricot', 'atropic', 'parotic', 'patrico'], + 'parotid': ['dioptra', 'parotid'], + 'parotitic': ['parotitic', 'patriotic'], + 'parotitis': ['parotitis', 'topiarist'], + 'parous': ['parous', 'upsoar'], + 'parovarium': ['parovarium', 'vaporarium'], + 'parrot': ['parrot', 'raptor'], + 'parroty': ['parroty', 'portray', 'tropary'], + 'parsable': ['parsable', 'prebasal', 'sparable'], + 'parse': ['asper', 'parse', 'prase', 'spaer', 'spare', 'spear'], + 'parsec': ['casper', 'escarp', 'parsec', 'scrape', 'secpar', 'spacer'], + 'parsee': ['parsee', 'persae', 'persea', 'serape'], + 'parser': ['parser', 'rasper', 'sparer'], + 'parsi': ['paris', 'parsi', 'sarip'], + 'parsley': ['parsley', 'pyrales', 'sparely', 'splayer'], + 'parsoned': ['parsoned', 'spadrone'], + 'parsonese': ['parsonese', 'preseason'], + 'parsonic': ['parsonic', 'scoparin'], + 'part': ['part', 'prat', 'rapt', 'tarp', 'trap'], + 'partan': ['partan', 'tarpan'], + 'parted': ['depart', 'parted', 'petard'], + 'partedness': ['depressant', 'partedness'], + 'parter': ['parter', 'prater'], + 'parthian': ['parthian', 'taphrina'], + 'partial': ['partial', 'patrial'], + 'partialistic': ['iatraliptics', 'partialistic'], + 'particle': ['particle', 'plicater', 'prelatic'], + 'particulate': ['catapultier', 'particulate'], + 'partigen': ['partigen', 'tapering'], + 'partile': ['partile', 'plaiter', 'replait'], + 'partimen': ['imperant', 'pairment', 'partimen', 'premiant', 'tripeman'], + 'partinium': ['impuritan', 'partinium'], + 'partisan': ['aspirant', 'partisan', 'spartina'], + 'partite': ['partite', 'tearpit'], + 'partitioned': ['departition', 'partitioned', 'trepidation'], + 'partitioner': ['partitioner', 'repartition'], + 'partlet': ['partlet', 'platter', 'prattle'], + 'partly': ['paltry', 'partly', 'raptly'], + 'parto': ['aport', 'parto', 'porta'], + 'parture': ['parture', 'rapture'], + 'party': ['party', 'trypa'], + 'parulis': ['parulis', 'spirula', 'uprisal'], + 'parure': ['parure', 'uprear'], + 'parvoline': ['overplain', 'parvoline'], + 'pasan': ['pasan', 'sapan'], + 'pasch': ['chaps', 'pasch'], + 'pascha': ['pascha', 'scapha'], + 'paschite': ['paschite', 'pastiche', 'pistache', 'scaphite'], + 'pascual': ['capsula', 'pascual', 'scapula'], + 'pash': ['hasp', 'pash', 'psha', 'shap'], + 'pasha': ['asaph', 'pasha'], + 'pashm': ['pashm', 'phasm'], + 'pashto': ['pashto', 'pathos', 'potash'], + 'pasi': ['apis', 'pais', 'pasi', 'saip'], + 'passer': ['passer', 'repass', 'sparse'], + 'passional': ['passional', 'sponsalia'], + 'passo': ['passo', 'psoas'], + 'passout': ['outpass', 'passout'], + 'passover': ['overpass', 'passover'], + 'past': ['past', 'spat', 'stap', 'taps'], + 'paste': ['paste', 'septa', 'spate'], + 'pastel': ['pastel', 'septal', 'staple'], + 'paster': ['paster', 'repast', 'trapes'], + 'pasterer': ['pasterer', 'strepera'], + 'pasteur': ['pasteur', 'pasture', 'upstare'], + 'pastiche': ['paschite', 'pastiche', 'pistache', 'scaphite'], + 'pasticheur': ['curateship', 'pasticheur'], + 'pastil': ['alpist', 'pastil', 'spital'], + 'pastile': ['aliptes', 'pastile', 'talipes'], + 'pastime': ['impaste', 'pastime'], + 'pastimer': ['maspiter', 'pastimer', 'primates'], + 'pastophorium': ['amphitropous', 'pastophorium'], + 'pastophorus': ['apostrophus', 'pastophorus'], + 'pastor': ['asport', 'pastor', 'sproat'], + 'pastoral': ['pastoral', 'proatlas'], + 'pastorale': ['parosteal', 'pastorale'], + 'pastose': ['pastose', 'petasos'], + 'pastural': ['pastural', 'spatular'], + 'pasture': ['pasteur', 'pasture', 'upstare'], + 'pasty': ['pasty', 'patsy'], + 'pasul': ['palus', 'pasul'], + 'pat': ['apt', 'pat', 'tap'], + 'pata': ['atap', 'pata', 'tapa'], + 'patao': ['opata', 'patao', 'tapoa'], + 'patarin': ['patarin', 'tarapin'], + 'patarine': ['patarine', 'tarpeian'], + 'patas': ['patas', 'tapas'], + 'patch': ['chapt', 'pacht', 'patch'], + 'patcher': ['chapter', 'patcher', 'repatch'], + 'patchery': ['patchery', 'petchary'], + 'pate': ['pate', 'peat', 'tape', 'teap'], + 'patel': ['leapt', + 'palet', + 'patel', + 'pelta', + 'petal', + 'plate', + 'pleat', + 'tepal'], + 'paten': ['enapt', 'paten', 'penta', 'tapen'], + 'patener': ['patener', 'pearten', 'petrean', 'terpane'], + 'patent': ['patent', 'patten', 'tapnet'], + 'pater': ['apert', 'pater', 'peart', 'prate', 'taper', 'terap'], + 'patera': ['aptera', 'parate', 'patera'], + 'paternal': ['parental', 'paternal', 'prenatal'], + 'paternalism': ['parentalism', 'paternalism'], + 'paternalist': ['intraseptal', 'paternalist', 'prenatalist'], + 'paternality': ['parentality', 'paternality'], + 'paternally': ['parentally', 'paternally', 'prenatally'], + 'paternoster': ['paternoster', 'prosternate', 'transportee'], + 'patesi': ['patesi', 'pietas'], + 'pathed': ['heptad', 'pathed'], + 'pathic': ['haptic', 'pathic'], + 'pathlet': ['pathlet', 'telpath'], + 'pathogen': ['heptagon', 'pathogen'], + 'pathologicoanatomic': ['anatomicopathologic', 'pathologicoanatomic'], + 'pathologicoanatomical': ['anatomicopathological', 'pathologicoanatomical'], + 'pathologicoclinical': ['clinicopathological', 'pathologicoclinical'], + 'pathonomy': ['monopathy', 'pathonomy'], + 'pathophoric': ['haptophoric', 'pathophoric'], + 'pathophorous': ['haptophorous', 'pathophorous'], + 'pathos': ['pashto', 'pathos', 'potash'], + 'pathy': ['pathy', 'typha'], + 'patiently': ['patiently', 'platynite'], + 'patina': ['aptian', 'patina', 'taipan'], + 'patine': ['pantie', 'patine'], + 'patined': ['depaint', 'inadept', 'painted', 'patined'], + 'patio': ['patio', 'taipo', 'topia'], + 'patly': ['aptly', 'patly', 'platy', 'typal'], + 'patness': ['aptness', 'patness'], + 'pato': ['atop', 'pato'], + 'patola': ['patola', 'tapalo'], + 'patrial': ['partial', 'patrial'], + 'patriarch': ['patriarch', 'phratriac'], + 'patrice': ['paretic', 'patrice', 'picrate'], + 'patricide': ['dipicrate', 'patricide', 'pediatric'], + 'patrico': ['apricot', 'atropic', 'parotic', 'patrico'], + 'patrilocal': ['allopatric', 'patrilocal'], + 'patriotic': ['parotitic', 'patriotic'], + 'patroclinous': ['patroclinous', 'pratincolous'], + 'patrol': ['patrol', 'portal', 'tropal'], + 'patron': ['patron', 'tarpon'], + 'patroness': ['patroness', 'transpose'], + 'patronite': ['antitrope', 'patronite', 'tritanope'], + 'patronymic': ['importancy', 'patronymic', 'pyromantic'], + 'patsy': ['pasty', 'patsy'], + 'patte': ['patte', 'tapet'], + 'pattee': ['pattee', 'tapete'], + 'patten': ['patent', 'patten', 'tapnet'], + 'pattener': ['pattener', 'repatent'], + 'patterer': ['patterer', 'pretreat'], + 'pattern': ['pattern', 'reptant'], + 'patterner': ['patterner', 'repattern'], + 'patu': ['patu', 'paut', 'tapu'], + 'patulent': ['patulent', 'petulant'], + 'pau': ['pau', 'pua'], + 'paul': ['paul', 'upla'], + 'paula': ['palau', 'paula'], + 'paulian': ['apulian', 'paulian', 'paulina'], + 'paulie': ['alpieu', 'paulie'], + 'paulin': ['paulin', 'pulian'], + 'paulina': ['apulian', 'paulian', 'paulina'], + 'paulinistic': ['paniculitis', 'paulinistic'], + 'paulinus': ['nauplius', 'paulinus'], + 'paulist': ['paulist', 'stipula'], + 'paup': ['paup', 'pupa'], + 'paut': ['patu', 'paut', 'tapu'], + 'paver': ['paver', 'verpa'], + 'pavid': ['pavid', 'vapid'], + 'pavidity': ['pavidity', 'vapidity'], + 'pavier': ['pavier', 'vipera'], + 'pavisor': ['pavisor', 'proavis'], + 'paw': ['paw', 'wap'], + 'pawner': ['enwrap', 'pawner', 'repawn'], + 'pay': ['pay', 'pya', 'yap'], + 'payer': ['apery', 'payer', 'repay'], + 'payroll': ['payroll', 'polarly'], + 'pea': ['ape', 'pea'], + 'peach': ['chape', 'cheap', 'peach'], + 'peachen': ['cheapen', 'peachen'], + 'peachery': ['cheapery', 'peachery'], + 'peachlet': ['chapelet', 'peachlet'], + 'peacoat': ['opacate', 'peacoat'], + 'peag': ['gape', 'page', 'peag', 'pega'], + 'peaker': ['parkee', 'peaker'], + 'peal': ['leap', 'lepa', 'pale', 'peal', 'plea'], + 'pealike': ['apelike', 'pealike'], + 'pean': ['nape', 'neap', 'nepa', 'pane', 'pean'], + 'pear': ['aper', 'pare', 'pear', 'rape', 'reap'], + 'pearl': ['lepra', 'paler', 'parel', 'parle', 'pearl', 'perla', 'relap'], + 'pearled': ['pearled', 'pedaler', 'pleader', 'replead'], + 'pearlet': ['pearlet', 'pleater', 'prelate', 'ptereal', 'replate', 'repleat'], + 'pearlin': ['pearlin', 'plainer', 'praline'], + 'pearlish': ['earlship', 'pearlish'], + 'pearlsides': ['displeaser', 'pearlsides'], + 'pearly': ['parley', 'pearly', 'player', 'replay'], + 'pearmain': ['amperian', 'paramine', 'pearmain'], + 'peart': ['apert', 'pater', 'peart', 'prate', 'taper', 'terap'], + 'pearten': ['patener', 'pearten', 'petrean', 'terpane'], + 'peartly': ['apertly', 'peartly', 'platery', 'pteryla', 'taperly'], + 'peartness': ['apertness', 'peartness', 'taperness'], + 'peasantry': ['peasantry', 'synaptera'], + 'peat': ['pate', 'peat', 'tape', 'teap'], + 'peatman': ['peatman', 'tapeman'], + 'peatship': ['happiest', 'peatship'], + 'peccation': ['acception', 'peccation'], + 'peckerwood': ['peckerwood', 'woodpecker'], + 'pecos': ['copse', 'pecos', 'scope'], + 'pectin': ['incept', 'pectin'], + 'pectinate': ['pectinate', 'pencatite'], + 'pectination': ['antinepotic', 'pectination'], + 'pectinatopinnate': ['pectinatopinnate', 'pinnatopectinate'], + 'pectinoid': ['depiction', 'pectinoid'], + 'pectora': ['coperta', 'pectora', 'porcate'], + 'pecunious': ['pecunious', 'puniceous'], + 'peda': ['depa', 'peda'], + 'pedal': ['padle', 'paled', 'pedal', 'plead'], + 'pedaler': ['pearled', 'pedaler', 'pleader', 'replead'], + 'pedalier': ['pedalier', 'perlidae'], + 'pedalion': ['lapideon', 'palinode', 'pedalion'], + 'pedalism': ['misplead', 'pedalism'], + 'pedalist': ['dispetal', 'pedalist'], + 'pedaliter': ['pedaliter', 'predetail'], + 'pedant': ['pedant', 'pentad'], + 'pedantess': ['adeptness', 'pedantess'], + 'pedantic': ['pedantic', 'pentacid'], + 'pedary': ['pedary', 'preday'], + 'pederastic': ['discrepate', 'pederastic'], + 'pedes': ['pedes', 'speed'], + 'pedesis': ['despise', 'pedesis'], + 'pedestrial': ['pedestrial', 'pilastered'], + 'pediatric': ['dipicrate', 'patricide', 'pediatric'], + 'pedicel': ['pedicel', 'pedicle'], + 'pedicle': ['pedicel', 'pedicle'], + 'pedicular': ['crepidula', 'pedicular'], + 'pediculi': ['lupicide', 'pediculi', 'pulicide'], + 'pedimana': ['pandemia', 'pedimana'], + 'pedocal': ['lacepod', 'pedocal', 'placode'], + 'pedometrician': ['pedometrician', 'premedication'], + 'pedrail': ['pedrail', 'predial'], + 'pedro': ['doper', 'pedro', 'pored'], + 'peed': ['deep', 'peed'], + 'peek': ['keep', 'peek'], + 'peel': ['leep', 'peel', 'pele'], + 'peelman': ['empanel', 'emplane', 'peelman'], + 'peen': ['neep', 'peen'], + 'peerly': ['peerly', 'yelper'], + 'pega': ['gape', 'page', 'peag', 'pega'], + 'peho': ['hope', 'peho'], + 'peiser': ['espier', 'peiser'], + 'peitho': ['ethiop', 'ophite', 'peitho'], + 'peixere': ['expiree', 'peixere'], + 'pekan': ['knape', 'pekan'], + 'pelage': ['paegel', 'paegle', 'pelage'], + 'pelasgoi': ['pelasgoi', 'spoilage'], + 'pele': ['leep', 'peel', 'pele'], + 'pelean': ['alpeen', 'lenape', 'pelean'], + 'pelecani': ['capeline', 'pelecani'], + 'pelecanus': ['encapsule', 'pelecanus'], + 'pelias': ['espial', 'lipase', 'pelias'], + 'pelican': ['calepin', 'capelin', 'panicle', 'pelican', 'pinacle'], + 'pelick': ['pelick', 'pickle'], + 'pelides': ['pelides', 'seedlip'], + 'pelidnota': ['pelidnota', 'planetoid'], + 'pelike': ['kelpie', 'pelike'], + 'pelisse': ['pelisse', 'pieless'], + 'pelite': ['leepit', 'pelite', 'pielet'], + 'pellation': ['pellation', 'pollinate'], + 'pellotine': ['pellotine', 'pollenite'], + 'pelmet': ['pelmet', 'temple'], + 'pelon': ['pelon', 'pleon'], + 'pelops': ['pelops', 'peplos'], + 'pelorian': ['pelorian', 'peronial', 'proalien'], + 'peloric': ['peloric', 'precoil'], + 'pelorus': ['leprous', 'pelorus', 'sporule'], + 'pelota': ['alepot', 'pelota'], + 'pelta': ['leapt', + 'palet', + 'patel', + 'pelta', + 'petal', + 'plate', + 'pleat', + 'tepal'], + 'peltandra': ['leptandra', 'peltandra'], + 'peltast': ['peltast', 'spattle'], + 'peltate': ['palette', 'peltate'], + 'peltation': ['peltation', 'potential'], + 'pelter': ['pelter', 'petrel'], + 'peltiform': ['leptiform', 'peltiform'], + 'pelting': ['pelting', 'petling'], + 'peltry': ['peltry', 'pertly'], + 'pelu': ['lupe', 'pelu', 'peul', 'pule'], + 'pelusios': ['epulosis', 'pelusios'], + 'pelycography': ['pelycography', 'pyrgocephaly'], + 'pemican': ['campine', 'pemican'], + 'pen': ['nep', 'pen'], + 'penal': ['alpen', 'nepal', 'panel', 'penal', 'plane'], + 'penalist': ['panelist', 'pantelis', 'penalist', 'plastein'], + 'penalty': ['aplenty', 'penalty'], + 'penang': ['pangen', 'penang'], + 'penates': ['penates', 'septane'], + 'pencatite': ['pectinate', 'pencatite'], + 'penciled': ['depencil', 'penciled', 'pendicle'], + 'pencilry': ['pencilry', 'princely'], + 'penda': ['paned', 'penda'], + 'pendicle': ['depencil', 'penciled', 'pendicle'], + 'pendulant': ['pendulant', 'unplanted'], + 'pendular': ['pendular', 'underlap', 'uplander'], + 'pendulate': ['pendulate', 'unpleated'], + 'pendulation': ['pendulation', 'pennatuloid'], + 'pendulum': ['pendulum', 'unlumped', 'unplumed'], + 'penetrable': ['penetrable', 'repentable'], + 'penetrance': ['penetrance', 'repentance'], + 'penetrant': ['penetrant', 'repentant'], + 'penial': ['alpine', 'nepali', 'penial', 'pineal'], + 'penis': ['penis', 'snipe', 'spine'], + 'penitencer': ['penitencer', 'pertinence'], + 'penman': ['nepman', 'penman'], + 'penna': ['panne', 'penna'], + 'pennage': ['pangene', 'pennage'], + 'pennate': ['pennate', 'pentane'], + 'pennatulid': ['pennatulid', 'pinnulated'], + 'pennatuloid': ['pendulation', 'pennatuloid'], + 'pennia': ['nanpie', 'pennia', 'pinnae'], + 'pennisetum': ['pennisetum', 'septennium'], + 'pensioner': ['pensioner', 'repension'], + 'pensive': ['pensive', 'vespine'], + 'penster': ['penster', 'present', 'serpent', 'strepen'], + 'penta': ['enapt', 'paten', 'penta', 'tapen'], + 'pentace': ['pentace', 'tepanec'], + 'pentacid': ['pedantic', 'pentacid'], + 'pentad': ['pedant', 'pentad'], + 'pentadecoic': ['adenectopic', 'pentadecoic'], + 'pentail': ['pantile', 'pentail', 'platine', 'talpine'], + 'pentamerid': ['pandermite', 'pentamerid'], + 'pentameroid': ['pentameroid', 'predominate'], + 'pentane': ['pennate', 'pentane'], + 'pentaploid': ['deoppilant', 'pentaploid'], + 'pentathionic': ['antiphonetic', 'pentathionic'], + 'pentatomic': ['camptonite', 'pentatomic'], + 'pentitol': ['pentitol', 'pointlet'], + 'pentoic': ['entopic', 'nepotic', 'pentoic'], + 'pentol': ['lepton', 'pentol'], + 'pentose': ['pentose', 'posteen'], + 'pentyl': ['pentyl', 'plenty'], + 'penult': ['penult', 'punlet', 'puntel'], + 'peon': ['nope', 'open', 'peon', 'pone'], + 'peony': ['peony', 'poney'], + 'peopler': ['peopler', 'popeler'], + 'peorian': ['apeiron', 'peorian'], + 'peplos': ['pelops', 'peplos'], + 'peplum': ['peplum', 'pumple'], + 'peplus': ['peplus', 'supple'], + 'pepo': ['pepo', 'pope'], + 'per': ['per', 'rep'], + 'peracid': ['epacrid', 'peracid', 'preacid'], + 'peract': ['carpet', 'peract', 'preact'], + 'peracute': ['peracute', 'preacute'], + 'peradventure': ['peradventure', 'preadventure'], + 'perakim': ['perakim', 'permiak', 'rampike'], + 'peramble': ['peramble', 'preamble'], + 'perambulate': ['perambulate', 'preambulate'], + 'perambulation': ['perambulation', 'preambulation'], + 'perambulatory': ['perambulatory', 'preambulatory'], + 'perates': ['perates', 'repaste', 'sperate'], + 'perbend': ['perbend', 'prebend'], + 'perborate': ['perborate', 'prorebate', 'reprobate'], + 'perca': ['caper', 'crape', 'pacer', 'perca', 'recap'], + 'percale': ['percale', 'replace'], + 'percaline': ['percaline', 'periclean'], + 'percent': ['percent', 'precent'], + 'percept': ['percept', 'precept'], + 'perception': ['perception', 'preception'], + 'perceptionism': ['misperception', 'perceptionism'], + 'perceptive': ['perceptive', 'preceptive'], + 'perceptively': ['perceptively', 'preceptively'], + 'perceptual': ['perceptual', 'preceptual'], + 'perceptually': ['perceptually', 'preceptually'], + 'percha': ['aperch', 'eparch', 'percha', 'preach'], + 'perchloric': ['perchloric', 'prechloric'], + 'percid': ['percid', 'priced'], + 'perclose': ['perclose', 'preclose'], + 'percoidea': ['adipocere', 'percoidea'], + 'percolate': ['percolate', 'prelocate'], + 'percolation': ['neotropical', 'percolation'], + 'percompound': ['percompound', 'precompound'], + 'percontation': ['percontation', 'pernoctation'], + 'perculsion': ['perculsion', 'preclusion'], + 'perculsive': ['perculsive', 'preclusive'], + 'percurrent': ['percurrent', 'precurrent'], + 'percursory': ['percursory', 'precursory'], + 'percussion': ['croupiness', 'percussion', 'supersonic'], + 'percussioner': ['percussioner', 'repercussion'], + 'percussor': ['percussor', 'procuress'], + 'percy': ['crepy', 'cypre', 'percy'], + 'perdicine': ['perdicine', 'recipiend'], + 'perdition': ['direption', 'perdition', 'tropidine'], + 'perdu': ['drupe', 'duper', 'perdu', 'prude', 'pured'], + 'peregrina': ['peregrina', 'pregainer'], + 'pereion': ['pereion', 'pioneer'], + 'perendure': ['perendure', 'underpeer'], + 'peres': ['peres', 'perse', 'speer', 'spree'], + 'perfect': ['perfect', 'prefect'], + 'perfected': ['perfected', 'predefect'], + 'perfection': ['frontpiece', 'perfection'], + 'perfectly': ['perfectly', 'prefectly'], + 'perfervid': ['perfervid', 'prefervid'], + 'perfoliation': ['perfoliation', 'prefoliation'], + 'perforative': ['perforative', 'prefavorite'], + 'perform': ['perform', 'preform'], + 'performant': ['performant', 'preformant'], + 'performative': ['performative', 'preformative'], + 'performer': ['performer', 'prereform', 'reperform'], + 'pergamic': ['crimpage', 'pergamic'], + 'perhaps': ['perhaps', 'prehaps'], + 'perhazard': ['perhazard', 'prehazard'], + 'peri': ['peri', 'pier', 'ripe'], + 'periacinal': ['epicranial', 'periacinal'], + 'perianal': ['airplane', 'perianal'], + 'perianth': ['perianth', 'triphane'], + 'periapt': ['periapt', 'rappite'], + 'periaster': ['periaster', 'sparterie'], + 'pericardiacophrenic': ['pericardiacophrenic', 'phrenicopericardiac'], + 'pericardiopleural': ['pericardiopleural', 'pleuropericardial'], + 'perichete': ['perichete', 'perithece'], + 'periclase': ['episclera', 'periclase'], + 'periclean': ['percaline', 'periclean'], + 'pericles': ['eclipser', 'pericles', 'resplice'], + 'pericopal': ['pericopal', 'periploca'], + 'periculant': ['periculant', 'unprelatic'], + 'peridental': ['interplead', 'peridental'], + 'peridiastolic': ['peridiastolic', 'periodicalist', 'proidealistic'], + 'peridot': ['diopter', 'peridot', 'proetid', 'protide', 'pteroid'], + 'perigone': ['perigone', 'pigeoner'], + 'peril': ['peril', 'piler', 'plier'], + 'perilous': ['perilous', 'uropsile'], + 'perimeter': ['perimeter', 'peritreme'], + 'perine': ['neiper', 'perine', 'pirene', 'repine'], + 'perineovaginal': ['perineovaginal', 'vaginoperineal'], + 'periodate': ['periodate', 'proetidae', 'proteidae'], + 'periodicalist': ['peridiastolic', 'periodicalist', 'proidealistic'], + 'periodontal': ['deploration', 'periodontal'], + 'periost': ['periost', 'porites', 'reposit', 'riposte'], + 'periosteal': ['periosteal', 'praseolite'], + 'periotic': ['epirotic', 'periotic'], + 'peripatetic': ['peripatetic', 'precipitate'], + 'peripatidae': ['peripatidae', 'peripatidea'], + 'peripatidea': ['peripatidae', 'peripatidea'], + 'periplaneta': ['periplaneta', 'prepalatine'], + 'periploca': ['pericopal', 'periploca'], + 'periplus': ['periplus', 'supplier'], + 'periportal': ['periportal', 'peritropal'], + 'periproct': ['cotripper', 'periproct'], + 'peripterous': ['peripterous', 'prepositure'], + 'perique': ['perique', 'repique'], + 'perirectal': ['perirectal', 'prerecital'], + 'periscian': ['periscian', 'precisian'], + 'periscopal': ['periscopal', 'sapropelic'], + 'perish': ['perish', 'reship'], + 'perished': ['hesperid', 'perished'], + 'perishment': ['perishment', 'reshipment'], + 'perisomal': ['perisomal', 'semipolar'], + 'perisome': ['perisome', 'promisee', 'reimpose'], + 'perispome': ['perispome', 'preimpose'], + 'peristole': ['epistoler', 'peristole', 'perseitol', 'pistoleer'], + 'peristoma': ['epistroma', 'peristoma'], + 'peristomal': ['peristomal', 'prestomial'], + 'peristylos': ['peristylos', 'pterylosis'], + 'perit': ['perit', 'retip', 'tripe'], + 'perite': ['perite', 'petrie', 'pieter'], + 'peritenon': ['interpone', 'peritenon', 'pinnotere', 'preintone'], + 'perithece': ['perichete', 'perithece'], + 'peritomize': ['epitomizer', 'peritomize'], + 'peritomous': ['outpromise', 'peritomous'], + 'peritreme': ['perimeter', 'peritreme'], + 'peritrichous': ['courtiership', 'peritrichous'], + 'peritroch': ['chiropter', 'peritroch'], + 'peritropal': ['periportal', 'peritropal'], + 'peritropous': ['peritropous', 'proprietous'], + 'perkin': ['perkin', 'pinker'], + 'perknite': ['perknite', 'peterkin'], + 'perla': ['lepra', 'paler', 'parel', 'parle', 'pearl', 'perla', 'relap'], + 'perle': ['leper', 'perle', 'repel'], + 'perlection': ['perlection', 'prelection'], + 'perlidae': ['pedalier', 'perlidae'], + 'perlingual': ['perlingual', 'prelingual'], + 'perlite': ['perlite', 'reptile'], + 'perlitic': ['perlitic', 'triplice'], + 'permeameter': ['amperemeter', 'permeameter'], + 'permeance': ['permeance', 'premenace'], + 'permeant': ['permeant', 'peterman'], + 'permeation': ['permeation', 'preominate'], + 'permiak': ['perakim', 'permiak', 'rampike'], + 'permissibility': ['impressibility', 'permissibility'], + 'permissible': ['impressible', 'permissible'], + 'permissibleness': ['impressibleness', 'permissibleness'], + 'permissibly': ['impressibly', 'permissibly'], + 'permission': ['impression', 'permission'], + 'permissive': ['impressive', 'permissive'], + 'permissively': ['impressively', 'permissively'], + 'permissiveness': ['impressiveness', 'permissiveness'], + 'permitter': ['permitter', 'pretermit'], + 'permixture': ['permixture', 'premixture'], + 'permonosulphuric': ['monopersulphuric', 'permonosulphuric'], + 'permutation': ['importunate', 'permutation'], + 'pernasal': ['pernasal', 'prenasal'], + 'pernis': ['pernis', 'respin', 'sniper'], + 'pernoctation': ['percontation', 'pernoctation'], + 'pernor': ['pernor', 'perron'], + 'pernyi': ['pernyi', 'pinery'], + 'peronial': ['pelorian', 'peronial', 'proalien'], + 'peropus': ['peropus', 'purpose'], + 'peroral': ['peroral', 'preoral'], + 'perorally': ['perorally', 'preorally'], + 'perorate': ['perorate', 'retepora'], + 'perosmate': ['perosmate', 'sematrope'], + 'perosmic': ['comprise', 'perosmic'], + 'perotic': ['perotic', 'proteic', 'tropeic'], + 'perpera': ['paperer', 'perpera', 'prepare', 'repaper'], + 'perpetualist': ['perpetualist', 'pluriseptate'], + 'perplexer': ['perplexer', 'reperplex'], + 'perron': ['pernor', 'perron'], + 'perry': ['perry', 'pryer'], + 'persae': ['parsee', 'persae', 'persea', 'serape'], + 'persalt': ['palster', 'persalt', 'plaster', 'psalter', 'spartle', 'stapler'], + 'perscribe': ['perscribe', 'prescribe'], + 'perse': ['peres', 'perse', 'speer', 'spree'], + 'persea': ['parsee', 'persae', 'persea', 'serape'], + 'perseid': ['perseid', 'preside'], + 'perseitol': ['epistoler', 'peristole', 'perseitol', 'pistoleer'], + 'perseity': ['perseity', 'speerity'], + 'persian': ['persian', 'prasine', 'saprine'], + 'persic': ['crepis', 'cripes', 'persic', 'precis', 'spicer'], + 'persico': ['ceriops', 'persico'], + 'persism': ['impress', 'persism', 'premiss'], + 'persist': ['persist', 'spriest'], + 'persistent': ['persistent', 'presentist', 'prettiness'], + 'personalia': ['palaeornis', 'personalia'], + 'personalistic': ['personalistic', 'pictorialness'], + 'personate': ['esperanto', 'personate'], + 'personed': ['personed', 'responde'], + 'pert': ['pert', 'petr', 'terp'], + 'pertain': ['painter', 'pertain', 'pterian', 'repaint'], + 'perten': ['perten', 'repent'], + 'perthite': ['perthite', 'tephrite'], + 'perthitic': ['perthitic', 'tephritic'], + 'pertinacity': ['antipyretic', 'pertinacity'], + 'pertinence': ['penitencer', 'pertinence'], + 'pertly': ['peltry', 'pertly'], + 'perturbational': ['perturbational', 'protuberantial'], + 'pertussal': ['pertussal', 'supersalt'], + 'perty': ['perty', 'typer'], + 'peru': ['peru', 'prue', 'pure'], + 'perugian': ['pagurine', 'perugian'], + 'peruke': ['keuper', 'peruke'], + 'perula': ['epural', 'perula', 'pleura'], + 'perun': ['perun', 'prune'], + 'perusable': ['perusable', 'superable'], + 'perusal': ['perusal', 'serpula'], + 'peruse': ['peruse', 'respue'], + 'pervade': ['deprave', 'pervade'], + 'pervader': ['depraver', 'pervader'], + 'pervadingly': ['depravingly', 'pervadingly'], + 'perverse': ['perverse', 'preserve'], + 'perversion': ['perversion', 'preversion'], + 'pervious': ['pervious', 'previous', 'viperous'], + 'perviously': ['perviously', 'previously', 'viperously'], + 'perviousness': ['perviousness', 'previousness', 'viperousness'], + 'pesa': ['apse', 'pesa', 'spae'], + 'pesach': ['cephas', 'pesach'], + 'pesah': ['heaps', 'pesah', 'phase', 'shape'], + 'peseta': ['asteep', 'peseta'], + 'peso': ['epos', 'peso', 'pose', 'sope'], + 'pess': ['pess', 'seps'], + 'pessoner': ['pessoner', 'response'], + 'pest': ['pest', 'sept', 'spet', 'step'], + 'peste': ['peste', 'steep'], + 'pester': ['pester', 'preset', 'restep', 'streep'], + 'pesthole': ['heelpost', 'pesthole'], + 'pesticidal': ['pesticidal', 'septicidal'], + 'pestiferous': ['pestiferous', 'septiferous'], + 'pestle': ['pestle', 'spleet'], + 'petal': ['leapt', + 'palet', + 'patel', + 'pelta', + 'petal', + 'plate', + 'pleat', + 'tepal'], + 'petalia': ['palaite', 'petalia', 'pileata'], + 'petaline': ['petaline', 'tapeline'], + 'petalism': ['petalism', 'septimal'], + 'petalless': ['petalless', 'plateless', 'pleatless'], + 'petallike': ['petallike', 'platelike'], + 'petaloid': ['opdalite', 'petaloid'], + 'petalon': ['lepanto', 'nepotal', 'petalon', 'polenta'], + 'petard': ['depart', 'parted', 'petard'], + 'petary': ['petary', 'pratey'], + 'petasos': ['pastose', 'petasos'], + 'petchary': ['patchery', 'petchary'], + 'petechial': ['epithecal', 'petechial', 'phacelite'], + 'petechiate': ['epithecate', 'petechiate'], + 'peteman': ['peteman', 'tempean'], + 'peter': ['erept', 'peter', 'petre'], + 'peterkin': ['perknite', 'peterkin'], + 'peterman': ['permeant', 'peterman'], + 'petiolary': ['epilatory', 'petiolary'], + 'petiole': ['petiole', 'pilotee'], + 'petioled': ['lepidote', 'petioled'], + 'petitionary': ['opiniatrety', 'petitionary'], + 'petitioner': ['petitioner', 'repetition'], + 'petiveria': ['aperitive', 'petiveria'], + 'petling': ['pelting', 'petling'], + 'peto': ['peto', 'poet', 'pote', 'tope'], + 'petr': ['pert', 'petr', 'terp'], + 'petre': ['erept', 'peter', 'petre'], + 'petrea': ['petrea', 'repeat', 'retape'], + 'petrean': ['patener', 'pearten', 'petrean', 'terpane'], + 'petrel': ['pelter', 'petrel'], + 'petricola': ['carpolite', 'petricola'], + 'petrie': ['perite', 'petrie', 'pieter'], + 'petrine': ['petrine', 'terpine'], + 'petrochemical': ['cephalometric', 'petrochemical'], + 'petrogale': ['petrogale', 'petrolage', 'prolegate'], + 'petrographer': ['petrographer', 'pterographer'], + 'petrographic': ['petrographic', 'pterographic'], + 'petrographical': ['petrographical', 'pterographical'], + 'petrographically': ['petrographically', 'pterylographical'], + 'petrography': ['petrography', 'pterography', 'typographer'], + 'petrol': ['petrol', 'replot'], + 'petrolage': ['petrogale', 'petrolage', 'prolegate'], + 'petrolean': ['petrolean', 'rantepole'], + 'petrolic': ['petrolic', 'plerotic'], + 'petrologically': ['petrologically', 'pterylological'], + 'petrosa': ['esparto', 'petrosa', 'seaport'], + 'petrosal': ['petrosal', 'polestar'], + 'petrosquamosal': ['petrosquamosal', 'squamopetrosal'], + 'petrous': ['petrous', 'posture', 'proetus', 'proteus', 'septuor', 'spouter'], + 'petticoated': ['depetticoat', 'petticoated'], + 'petulant': ['patulent', 'petulant'], + 'petune': ['neetup', 'petune'], + 'peul': ['lupe', 'pelu', 'peul', 'pule'], + 'pewy': ['pewy', 'wype'], + 'peyote': ['peyote', 'poteye'], + 'peyotl': ['peyotl', 'poetly'], + 'phacelia': ['acephali', 'phacelia'], + 'phacelite': ['epithecal', 'petechial', 'phacelite'], + 'phacoid': ['dapicho', 'phacoid'], + 'phacolite': ['hopcalite', 'phacolite'], + 'phacolysis': ['pachylosis', 'phacolysis'], + 'phacometer': ['pachometer', 'phacometer'], + 'phaethonic': ['phaethonic', 'theophanic'], + 'phaeton': ['phaeton', 'phonate'], + 'phagocytism': ['mycophagist', 'phagocytism'], + 'phalaecian': ['acephalina', 'phalaecian'], + 'phalangium': ['gnaphalium', 'phalangium'], + 'phalera': ['phalera', 'raphael'], + 'phanariot': ['parathion', 'phanariot'], + 'phanerogam': ['anemograph', 'phanerogam'], + 'phanerogamic': ['anemographic', 'phanerogamic'], + 'phanerogamy': ['anemography', 'phanerogamy'], + 'phanic': ['apinch', 'chapin', 'phanic'], + 'phano': ['phano', 'pohna'], + 'pharaonic': ['anaphoric', 'pharaonic'], + 'pharaonical': ['anaphorical', 'pharaonical'], + 'phare': ['hepar', 'phare', 'raphe'], + 'pharian': ['pharian', 'piranha'], + 'pharisaic': ['chirapsia', 'pharisaic'], + 'pharisean': ['pharisean', 'seraphina'], + 'pharisee': ['hesperia', 'pharisee'], + 'phariseeism': ['hemiparesis', 'phariseeism'], + 'pharmacolite': ['metaphorical', 'pharmacolite'], + 'pharyngolaryngeal': ['laryngopharyngeal', 'pharyngolaryngeal'], + 'pharyngolaryngitis': ['laryngopharyngitis', 'pharyngolaryngitis'], + 'pharyngorhinitis': ['pharyngorhinitis', 'rhinopharyngitis'], + 'phase': ['heaps', 'pesah', 'phase', 'shape'], + 'phaseless': ['phaseless', 'shapeless'], + 'phaseolin': ['esiphonal', 'phaseolin'], + 'phasis': ['aspish', 'phasis'], + 'phasm': ['pashm', 'phasm'], + 'phasmid': ['dampish', 'madship', 'phasmid'], + 'phasmoid': ['phasmoid', 'shopmaid'], + 'pheal': ['aleph', 'pheal'], + 'pheasant': ['pheasant', 'stephana'], + 'phecda': ['chaped', 'phecda'], + 'phemie': ['imphee', 'phemie'], + 'phenacite': ['phenacite', 'phenicate'], + 'phenate': ['haptene', 'heptane', 'phenate'], + 'phenetole': ['phenetole', 'telephone'], + 'phenic': ['phenic', 'pinche'], + 'phenicate': ['phenacite', 'phenicate'], + 'phenolic': ['phenolic', 'pinochle'], + 'phenological': ['nephological', 'phenological'], + 'phenologist': ['nephologist', 'phenologist'], + 'phenology': ['nephology', 'phenology'], + 'phenosal': ['alphonse', 'phenosal'], + 'pheon': ['pheon', 'phone'], + 'phi': ['hip', 'phi'], + 'phialide': ['hepialid', 'phialide'], + 'philobotanist': ['botanophilist', 'philobotanist'], + 'philocynic': ['cynophilic', 'philocynic'], + 'philohela': ['halophile', 'philohela'], + 'philoneism': ['neophilism', 'philoneism'], + 'philopoet': ['philopoet', 'photopile'], + 'philotheist': ['philotheist', 'theophilist'], + 'philotherian': ['lithonephria', 'philotherian'], + 'philozoic': ['philozoic', 'zoophilic'], + 'philozoist': ['philozoist', 'zoophilist'], + 'philter': ['philter', 'thripel'], + 'phineas': ['inphase', 'phineas'], + 'phiroze': ['orphize', 'phiroze'], + 'phit': ['phit', 'pith'], + 'phlebometritis': ['metrophlebitis', 'phlebometritis'], + 'phleum': ['phleum', 'uphelm'], + 'phloretic': ['phloretic', 'plethoric'], + 'pho': ['hop', 'pho', 'poh'], + 'phobism': ['mobship', 'phobism'], + 'phoca': ['chopa', 'phoca', 'poach'], + 'phocaean': ['phocaean', 'phocaena'], + 'phocaena': ['phocaean', 'phocaena'], + 'phocaenine': ['phocaenine', 'phoenicean'], + 'phocean': ['copehan', 'panoche', 'phocean'], + 'phocian': ['aphonic', 'phocian'], + 'phocine': ['chopine', 'phocine'], + 'phoenicean': ['phocaenine', 'phoenicean'], + 'pholad': ['adolph', 'pholad'], + 'pholas': ['alphos', 'pholas'], + 'pholcidae': ['cephaloid', 'pholcidae'], + 'pholcoid': ['chilopod', 'pholcoid'], + 'phonate': ['phaeton', 'phonate'], + 'phone': ['pheon', 'phone'], + 'phonelescope': ['nepheloscope', 'phonelescope'], + 'phonetical': ['pachnolite', 'phonetical'], + 'phonetics': ['phonetics', 'sphenotic'], + 'phoniatry': ['phoniatry', 'thiopyran'], + 'phonic': ['chopin', 'phonic'], + 'phonogram': ['monograph', 'nomograph', 'phonogram'], + 'phonogramic': ['gramophonic', 'monographic', 'nomographic', 'phonogramic'], + 'phonogramically': ['gramophonically', + 'monographically', + 'nomographically', + 'phonogramically'], + 'phonographic': ['graphophonic', 'phonographic'], + 'phonolite': ['lithopone', 'phonolite'], + 'phonometer': ['nephrotome', 'phonometer'], + 'phonometry': ['nephrotomy', 'phonometry'], + 'phonophote': ['phonophote', 'photophone'], + 'phonotyper': ['hypopteron', 'phonotyper'], + 'phoo': ['hoop', 'phoo', 'pooh'], + 'phorone': ['orpheon', 'phorone'], + 'phoronidea': ['phoronidea', 'radiophone'], + 'phos': ['phos', 'posh', 'shop', 'soph'], + 'phosphatide': ['diphosphate', 'phosphatide'], + 'phosphoglycerate': ['glycerophosphate', 'phosphoglycerate'], + 'phossy': ['hyssop', 'phossy', 'sposhy'], + 'phot': ['phot', 'toph'], + 'photechy': ['hypothec', 'photechy'], + 'photochromography': ['chromophotography', 'photochromography'], + 'photochromolithograph': ['chromophotolithograph', 'photochromolithograph'], + 'photochronograph': ['chronophotograph', 'photochronograph'], + 'photochronographic': ['chronophotographic', 'photochronographic'], + 'photochronography': ['chronophotography', 'photochronography'], + 'photogram': ['motograph', 'photogram'], + 'photographer': ['photographer', 'rephotograph'], + 'photoheliography': ['heliophotography', 'photoheliography'], + 'photolithography': ['lithophotography', 'photolithography'], + 'photomacrograph': ['macrophotograph', 'photomacrograph'], + 'photometer': ['photometer', 'prototheme'], + 'photomicrograph': ['microphotograph', 'photomicrograph'], + 'photomicrographic': ['microphotographic', 'photomicrographic'], + 'photomicrography': ['microphotography', 'photomicrography'], + 'photomicroscope': ['microphotoscope', 'photomicroscope'], + 'photophone': ['phonophote', 'photophone'], + 'photopile': ['philopoet', 'photopile'], + 'photostereograph': ['photostereograph', 'stereophotograph'], + 'phototelegraph': ['phototelegraph', 'telephotograph'], + 'phototelegraphic': ['phototelegraphic', 'telephotographic'], + 'phototelegraphy': ['phototelegraphy', 'telephotography'], + 'phototypography': ['phototypography', 'phytotopography'], + 'phrase': ['phrase', 'seraph', 'shaper', 'sherpa'], + 'phraser': ['phraser', 'sharper'], + 'phrasing': ['harpings', 'phrasing'], + 'phrasy': ['phrasy', 'sharpy'], + 'phratriac': ['patriarch', 'phratriac'], + 'phreatic': ['chapiter', 'phreatic'], + 'phrenesia': ['hesperian', 'phrenesia', 'seraphine'], + 'phrenic': ['nephric', 'phrenic', 'pincher'], + 'phrenicopericardiac': ['pericardiacophrenic', 'phrenicopericardiac'], + 'phrenics': ['phrenics', 'pinscher'], + 'phrenitic': ['nephritic', 'phrenitic', 'prehnitic'], + 'phrenitis': ['inspreith', 'nephritis', 'phrenitis'], + 'phrenocardiac': ['nephrocardiac', 'phrenocardiac'], + 'phrenocolic': ['nephrocolic', 'phrenocolic'], + 'phrenocostal': ['phrenocostal', 'plastochrone'], + 'phrenogastric': ['gastrophrenic', 'nephrogastric', 'phrenogastric'], + 'phrenohepatic': ['hepatonephric', 'phrenohepatic'], + 'phrenologist': ['nephrologist', 'phrenologist'], + 'phrenology': ['nephrology', 'phrenology'], + 'phrenopathic': ['nephropathic', 'phrenopathic'], + 'phrenopathy': ['nephropathy', 'phrenopathy'], + 'phrenosplenic': ['phrenosplenic', 'splenonephric', 'splenophrenic'], + 'phronesis': ['nephrosis', 'phronesis'], + 'phronimidae': ['diamorphine', 'phronimidae'], + 'phthalazine': ['naphthalize', 'phthalazine'], + 'phu': ['hup', 'phu'], + 'phycitol': ['cytophil', 'phycitol'], + 'phycocyanin': ['cyanophycin', 'phycocyanin'], + 'phyla': ['haply', 'phyla'], + 'phyletic': ['heptylic', 'phyletic'], + 'phylloceras': ['hyposcleral', 'phylloceras'], + 'phylloclad': ['cladophyll', 'phylloclad'], + 'phyllodial': ['phyllodial', 'phylloidal'], + 'phylloerythrin': ['erythrophyllin', 'phylloerythrin'], + 'phylloidal': ['phyllodial', 'phylloidal'], + 'phyllopodous': ['phyllopodous', 'podophyllous'], + 'phyma': ['phyma', 'yamph'], + 'phymatodes': ['desmopathy', 'phymatodes'], + 'phymosia': ['hyposmia', 'phymosia'], + 'physa': ['physa', 'shapy'], + 'physalite': ['physalite', 'styphelia'], + 'physic': ['physic', 'scyphi'], + 'physicochemical': ['chemicophysical', 'physicochemical'], + 'physicomedical': ['medicophysical', 'physicomedical'], + 'physiocrat': ['physiocrat', 'psychotria'], + 'physiologicoanatomic': ['anatomicophysiologic', 'physiologicoanatomic'], + 'physiopsychological': ['physiopsychological', 'psychophysiological'], + 'physiopsychology': ['physiopsychology', 'psychophysiology'], + 'phytic': ['phytic', 'pitchy', 'pythic', 'typhic'], + 'phytogenesis': ['phytogenesis', 'pythogenesis'], + 'phytogenetic': ['phytogenetic', 'pythogenetic'], + 'phytogenic': ['phytogenic', 'pythogenic', 'typhogenic'], + 'phytogenous': ['phytogenous', 'pythogenous'], + 'phytoid': ['phytoid', 'typhoid'], + 'phytologist': ['hypoglottis', 'phytologist'], + 'phytometer': ['phytometer', 'thermotype'], + 'phytometric': ['phytometric', 'thermotypic'], + 'phytometry': ['phytometry', 'thermotypy'], + 'phytomonas': ['phytomonas', 'somnopathy'], + 'phyton': ['phyton', 'python'], + 'phytonic': ['hypnotic', 'phytonic', 'pythonic', 'typhonic'], + 'phytosis': ['phytosis', 'typhosis'], + 'phytotopography': ['phototypography', 'phytotopography'], + 'phytozoa': ['phytozoa', 'zoopathy', 'zoophyta'], + 'piacle': ['epical', 'piacle', 'plaice'], + 'piacular': ['apicular', 'piacular'], + 'pial': ['lipa', 'pail', 'pali', 'pial'], + 'pialyn': ['alypin', 'pialyn'], + 'pian': ['nipa', 'pain', 'pani', 'pian', 'pina'], + 'pianiste': ['pianiste', 'pisanite'], + 'piannet': ['piannet', 'pinnate'], + 'pianola': ['opalina', 'pianola'], + 'piaroa': ['aporia', 'piaroa'], + 'piast': ['piast', 'stipa', 'tapis'], + 'piaster': ['piaster', 'piastre', 'raspite', 'spirate', 'traipse'], + 'piastre': ['piaster', 'piastre', 'raspite', 'spirate', 'traipse'], + 'picador': ['parodic', 'picador'], + 'picae': ['picae', 'picea'], + 'pical': ['pical', 'plica'], + 'picard': ['caprid', 'carpid', 'picard'], + 'picarel': ['caliper', 'picarel', 'replica'], + 'picary': ['cypria', 'picary', 'piracy'], + 'pice': ['epic', 'pice'], + 'picea': ['picae', 'picea'], + 'picene': ['picene', 'piecen'], + 'picker': ['picker', 'repick'], + 'pickle': ['pelick', 'pickle'], + 'pickler': ['pickler', 'prickle'], + 'pickover': ['overpick', 'pickover'], + 'picktooth': ['picktooth', 'toothpick'], + 'pico': ['cipo', 'pico'], + 'picot': ['optic', 'picot', 'topic'], + 'picotah': ['aphotic', 'picotah'], + 'picra': ['capri', 'picra', 'rapic'], + 'picrate': ['paretic', 'patrice', 'picrate'], + 'pictography': ['graphotypic', 'pictography', 'typographic'], + 'pictorialness': ['personalistic', 'pictorialness'], + 'picture': ['cuprite', 'picture'], + 'picudilla': ['picudilla', 'pulicidal'], + 'pidan': ['pidan', 'pinda'], + 'piebald': ['bipedal', 'piebald'], + 'piebaldness': ['dispensable', 'piebaldness'], + 'piecen': ['picene', 'piecen'], + 'piecer': ['piecer', 'pierce', 'recipe'], + 'piecework': ['piecework', 'workpiece'], + 'piecrust': ['crepitus', 'piecrust'], + 'piedness': ['dispense', 'piedness'], + 'piegan': ['genipa', 'piegan'], + 'pieless': ['pelisse', 'pieless'], + 'pielet': ['leepit', 'pelite', 'pielet'], + 'piemag': ['magpie', 'piemag'], + 'pieman': ['impane', 'pieman'], + 'pien': ['pien', 'pine'], + 'piend': ['piend', 'pined'], + 'pier': ['peri', 'pier', 'ripe'], + 'pierce': ['piecer', 'pierce', 'recipe'], + 'piercent': ['piercent', 'prentice'], + 'piercer': ['piercer', 'reprice'], + 'pierlike': ['pierlike', 'ripelike'], + 'piet': ['piet', 'tipe'], + 'pietas': ['patesi', 'pietas'], + 'pieter': ['perite', 'petrie', 'pieter'], + 'pig': ['gip', 'pig'], + 'pigeoner': ['perigone', 'pigeoner'], + 'pigeontail': ['pigeontail', 'plagionite'], + 'pigly': ['gilpy', 'pigly'], + 'pignon': ['ningpo', 'pignon'], + 'pignorate': ['operating', 'pignorate'], + 'pigskin': ['pigskin', 'spiking'], + 'pigsney': ['gypsine', 'pigsney'], + 'pik': ['kip', 'pik'], + 'pika': ['paik', 'pika'], + 'pike': ['kepi', 'kipe', 'pike'], + 'pikel': ['pikel', 'pikle'], + 'piker': ['krepi', 'piker'], + 'pikle': ['pikel', 'pikle'], + 'pilage': ['paigle', 'pilage'], + 'pilar': ['april', 'pilar', 'ripal'], + 'pilaster': ['epistlar', 'pilaster', 'plaister', 'priestal'], + 'pilastered': ['pedestrial', 'pilastered'], + 'pilastric': ['pilastric', 'triplasic'], + 'pilate': ['aplite', 'pilate'], + 'pileata': ['palaite', 'petalia', 'pileata'], + 'pileate': ['epilate', 'epitela', 'pileate'], + 'pileated': ['depilate', 'leptidae', 'pileated'], + 'piled': ['piled', 'plied'], + 'piler': ['peril', 'piler', 'plier'], + 'piles': ['piles', 'plies', 'slipe', 'spiel', 'spile'], + 'pileus': ['epulis', 'pileus'], + 'pili': ['ipil', 'pili'], + 'pilin': ['lipin', 'pilin'], + 'pillarist': ['pillarist', 'pistillar'], + 'pillet': ['liplet', 'pillet'], + 'pilm': ['limp', 'pilm', 'plim'], + 'pilmy': ['imply', 'limpy', 'pilmy'], + 'pilosis': ['liposis', 'pilosis'], + 'pilotee': ['petiole', 'pilotee'], + 'pilpai': ['lippia', 'pilpai'], + 'pilus': ['lupis', 'pilus'], + 'pim': ['imp', 'pim'], + 'pimelate': ['ampelite', 'pimelate'], + 'pimento': ['emption', 'pimento'], + 'pimenton': ['imponent', 'pimenton'], + 'pimola': ['lipoma', 'pimola', 'ploima'], + 'pimpish': ['impship', 'pimpish'], + 'pimplous': ['pimplous', 'pompilus', 'populism'], + 'pin': ['nip', 'pin'], + 'pina': ['nipa', 'pain', 'pani', 'pian', 'pina'], + 'pinaces': ['pinaces', 'pincase'], + 'pinachrome': ['epharmonic', 'pinachrome'], + 'pinacle': ['calepin', 'capelin', 'panicle', 'pelican', 'pinacle'], + 'pinacoid': ['diapnoic', 'pinacoid'], + 'pinal': ['lipan', 'pinal', 'plain'], + 'pinales': ['espinal', 'pinales', 'spaniel'], + 'pinaster': ['pinaster', 'pristane'], + 'pincase': ['pinaces', 'pincase'], + 'pincer': ['pincer', 'prince'], + 'pincerlike': ['pincerlike', 'princelike'], + 'pincers': ['encrisp', 'pincers'], + 'pinchbelly': ['bellypinch', 'pinchbelly'], + 'pinche': ['phenic', 'pinche'], + 'pincher': ['nephric', 'phrenic', 'pincher'], + 'pincushion': ['nuncioship', 'pincushion'], + 'pinda': ['pidan', 'pinda'], + 'pindari': ['pindari', 'pridian'], + 'pine': ['pien', 'pine'], + 'pineal': ['alpine', 'nepali', 'penial', 'pineal'], + 'pined': ['piend', 'pined'], + 'piner': ['piner', 'prine', 'repin', 'ripen'], + 'pinery': ['pernyi', 'pinery'], + 'pingler': ['pingler', 'pringle'], + 'pinhold': ['dolphin', 'pinhold'], + 'pinhole': ['lophine', 'pinhole'], + 'pinite': ['pinite', 'tiepin'], + 'pinker': ['perkin', 'pinker'], + 'pinking': ['kingpin', 'pinking'], + 'pinkish': ['kinship', 'pinkish'], + 'pinlock': ['lockpin', 'pinlock'], + 'pinnacle': ['pannicle', 'pinnacle'], + 'pinnae': ['nanpie', 'pennia', 'pinnae'], + 'pinnate': ['piannet', 'pinnate'], + 'pinnatopectinate': ['pectinatopinnate', 'pinnatopectinate'], + 'pinnet': ['pinnet', 'tenpin'], + 'pinnitarsal': ['intraspinal', 'pinnitarsal'], + 'pinnotere': ['interpone', 'peritenon', 'pinnotere', 'preintone'], + 'pinnothere': ['interphone', 'pinnothere'], + 'pinnula': ['pinnula', 'unplain'], + 'pinnulated': ['pennatulid', 'pinnulated'], + 'pinochle': ['phenolic', 'pinochle'], + 'pinole': ['pinole', 'pleion'], + 'pinolia': ['apiolin', 'pinolia'], + 'pinscher': ['phrenics', 'pinscher'], + 'pinta': ['inapt', 'paint', 'pinta'], + 'pintail': ['pintail', 'tailpin'], + 'pintano': ['opinant', 'pintano'], + 'pinte': ['inept', 'pinte'], + 'pinto': ['pinto', 'point'], + 'pintura': ['pintura', 'puritan', 'uptrain'], + 'pinulus': ['lupinus', 'pinulus'], + 'piny': ['piny', 'pyin'], + 'pinyl': ['pinyl', 'pliny'], + 'pioneer': ['pereion', 'pioneer'], + 'pioted': ['pioted', 'podite'], + 'pipa': ['paip', 'pipa'], + 'pipal': ['palpi', 'pipal'], + 'piperno': ['piperno', 'propine'], + 'pique': ['equip', 'pique'], + 'pir': ['pir', 'rip'], + 'piracy': ['cypria', 'picary', 'piracy'], + 'piranha': ['pharian', 'piranha'], + 'piratess': ['piratess', 'serapist', 'tarsipes'], + 'piratically': ['capillarity', 'piratically'], + 'piraty': ['parity', 'piraty'], + 'pirene': ['neiper', 'perine', 'pirene', 'repine'], + 'pirssonite': ['pirssonite', 'trispinose'], + 'pisaca': ['capias', 'pisaca'], + 'pisan': ['pisan', 'sapin', 'spina'], + 'pisanite': ['pianiste', 'pisanite'], + 'piscation': ['panoistic', 'piscation'], + 'piscatorial': ['paracolitis', 'piscatorial'], + 'piscian': ['panisic', 'piscian', 'piscina', 'sinapic'], + 'pisciferous': ['pisciferous', 'spiciferous'], + 'pisciform': ['pisciform', 'spiciform'], + 'piscina': ['panisic', 'piscian', 'piscina', 'sinapic'], + 'pisco': ['copis', 'pisco'], + 'pise': ['pise', 'sipe'], + 'pish': ['pish', 'ship'], + 'pisk': ['pisk', 'skip'], + 'pisky': ['pisky', 'spiky'], + 'pismire': ['pismire', 'primsie'], + 'pisonia': ['pisonia', 'sinopia'], + 'pist': ['pist', 'spit'], + 'pistache': ['paschite', 'pastiche', 'pistache', 'scaphite'], + 'pistacite': ['epistatic', 'pistacite'], + 'pistareen': ['pistareen', 'sparteine'], + 'pistillar': ['pillarist', 'pistillar'], + 'pistillary': ['pistillary', 'spiritally'], + 'pistle': ['pistle', 'stipel'], + 'pistol': ['pistol', 'postil', 'spoilt'], + 'pistoleer': ['epistoler', 'peristole', 'perseitol', 'pistoleer'], + 'pit': ['pit', 'tip'], + 'pita': ['atip', 'pita'], + 'pitapat': ['apitpat', 'pitapat'], + 'pitarah': ['pitarah', 'taphria'], + 'pitcher': ['pitcher', 'repitch'], + 'pitchout': ['outpitch', 'pitchout'], + 'pitchy': ['phytic', 'pitchy', 'pythic', 'typhic'], + 'pith': ['phit', 'pith'], + 'pithecan': ['haptenic', 'pantheic', 'pithecan'], + 'pithole': ['hoplite', 'pithole'], + 'pithsome': ['mephisto', 'pithsome'], + 'pitless': ['pitless', 'tipless'], + 'pitman': ['pitman', 'tampin', 'tipman'], + 'pittancer': ['crepitant', 'pittancer'], + 'pittoid': ['pittoid', 'poditti'], + 'pityroid': ['pityroid', 'pyritoid'], + 'pivoter': ['overtip', 'pivoter'], + 'placate': ['epactal', 'placate'], + 'placation': ['pactional', 'pactolian', 'placation'], + 'place': ['capel', 'place'], + 'placebo': ['copable', 'placebo'], + 'placentalia': ['analeptical', 'placentalia'], + 'placentoma': ['complanate', 'placentoma'], + 'placer': ['carpel', 'parcel', 'placer'], + 'placode': ['lacepod', 'pedocal', 'placode'], + 'placoid': ['placoid', 'podalic', 'podical'], + 'placus': ['cuspal', 'placus'], + 'plagionite': ['pigeontail', 'plagionite'], + 'plague': ['plague', 'upgale'], + 'plaguer': ['earplug', 'graupel', 'plaguer'], + 'plaice': ['epical', 'piacle', 'plaice'], + 'plaid': ['alpid', 'plaid'], + 'plaidy': ['adipyl', 'plaidy'], + 'plain': ['lipan', 'pinal', 'plain'], + 'plainer': ['pearlin', 'plainer', 'praline'], + 'plaint': ['plaint', 'pliant'], + 'plaister': ['epistlar', 'pilaster', 'plaister', 'priestal'], + 'plaited': ['plaited', 'taliped'], + 'plaiter': ['partile', 'plaiter', 'replait'], + 'planate': ['planate', 'planeta', 'plantae', 'platane'], + 'planation': ['planation', 'platonian'], + 'plancheite': ['elephantic', 'plancheite'], + 'plane': ['alpen', 'nepal', 'panel', 'penal', 'plane'], + 'planer': ['parnel', 'planer', 'replan'], + 'planera': ['planera', 'preanal'], + 'planet': ['pantle', 'planet', 'platen'], + 'planeta': ['planate', 'planeta', 'plantae', 'platane'], + 'planetabler': ['planetabler', 'replantable'], + 'planetaria': ['parentalia', 'planetaria'], + 'planetoid': ['pelidnota', 'planetoid'], + 'planity': ['inaptly', 'planity', 'ptyalin'], + 'planker': ['planker', 'prankle'], + 'planta': ['planta', 'platan'], + 'plantae': ['planate', 'planeta', 'plantae', 'platane'], + 'planter': ['pantler', 'planter', 'replant'], + 'plap': ['lapp', 'palp', 'plap'], + 'plasher': ['plasher', 'spheral'], + 'plasm': ['plasm', 'psalm', 'slamp'], + 'plasma': ['lampas', 'plasma'], + 'plasmation': ['aminoplast', 'plasmation'], + 'plasmic': ['plasmic', 'psalmic'], + 'plasmode': ['malposed', 'plasmode'], + 'plasmodial': ['plasmodial', 'psalmodial'], + 'plasmodic': ['plasmodic', 'psalmodic'], + 'plasson': ['plasson', 'sponsal'], + 'plastein': ['panelist', 'pantelis', 'penalist', 'plastein'], + 'plaster': ['palster', 'persalt', 'plaster', 'psalter', 'spartle', 'stapler'], + 'plasterer': ['plasterer', 'replaster'], + 'plastery': ['plastery', 'psaltery'], + 'plasticine': ['cisplatine', 'plasticine'], + 'plastidome': ['plastidome', 'postmedial'], + 'plastinoid': ['palinodist', 'plastinoid'], + 'plastochrone': ['phrenocostal', 'plastochrone'], + 'plat': ['palt', 'plat'], + 'plataean': ['panatela', 'plataean'], + 'platan': ['planta', 'platan'], + 'platane': ['planate', 'planeta', 'plantae', 'platane'], + 'plate': ['leapt', + 'palet', + 'patel', + 'pelta', + 'petal', + 'plate', + 'pleat', + 'tepal'], + 'platea': ['aletap', 'palate', 'platea'], + 'plateless': ['petalless', 'plateless', 'pleatless'], + 'platelet': ['pallette', 'platelet'], + 'platelike': ['petallike', 'platelike'], + 'platen': ['pantle', 'planet', 'platen'], + 'plater': ['palter', 'plater'], + 'platerer': ['palterer', 'platerer'], + 'platery': ['apertly', 'peartly', 'platery', 'pteryla', 'taperly'], + 'platine': ['pantile', 'pentail', 'platine', 'talpine'], + 'platinochloric': ['chloroplatinic', 'platinochloric'], + 'platinous': ['platinous', 'pulsation'], + 'platode': ['platode', 'tadpole'], + 'platoid': ['platoid', 'talpoid'], + 'platonian': ['planation', 'platonian'], + 'platter': ['partlet', 'platter', 'prattle'], + 'platy': ['aptly', 'patly', 'platy', 'typal'], + 'platynite': ['patiently', 'platynite'], + 'platysternal': ['platysternal', 'transeptally'], + 'plaud': ['dupla', 'plaud'], + 'plaustral': ['palustral', 'plaustral'], + 'play': ['paly', 'play', 'pyal', 'pyla'], + 'playa': ['palay', 'playa'], + 'player': ['parley', 'pearly', 'player', 'replay'], + 'playgoer': ['playgoer', 'pylagore'], + 'playroom': ['myopolar', 'playroom'], + 'plea': ['leap', 'lepa', 'pale', 'peal', 'plea'], + 'pleach': ['chapel', 'lepcha', 'pleach'], + 'plead': ['padle', 'paled', 'pedal', 'plead'], + 'pleader': ['pearled', 'pedaler', 'pleader', 'replead'], + 'please': ['asleep', 'elapse', 'please'], + 'pleaser': ['pleaser', 'preseal', 'relapse'], + 'pleasure': ['pleasure', 'serpulae'], + 'pleasurer': ['pleasurer', 'reperusal'], + 'pleasurous': ['asperulous', 'pleasurous'], + 'pleat': ['leapt', + 'palet', + 'patel', + 'pelta', + 'petal', + 'plate', + 'pleat', + 'tepal'], + 'pleater': ['pearlet', 'pleater', 'prelate', 'ptereal', 'replate', 'repleat'], + 'pleatless': ['petalless', 'plateless', 'pleatless'], + 'plectre': ['plectre', 'prelect'], + 'pleion': ['pinole', 'pleion'], + 'pleionian': ['opalinine', 'pleionian'], + 'plenilunar': ['plenilunar', 'plurennial'], + 'plenty': ['pentyl', 'plenty'], + 'pleomorph': ['pleomorph', 'prophloem'], + 'pleon': ['pelon', 'pleon'], + 'pleonal': ['pallone', 'pleonal'], + 'pleonasm': ['neoplasm', 'pleonasm', 'polesman', 'splenoma'], + 'pleonast': ['lapstone', 'pleonast'], + 'pleonastic': ['neoplastic', 'pleonastic'], + 'pleroma': ['leproma', 'palermo', 'pleroma', 'polearm'], + 'plerosis': ['leprosis', 'plerosis'], + 'plerotic': ['petrolic', 'plerotic'], + 'plessor': ['plessor', 'preloss'], + 'plethora': ['plethora', 'traphole'], + 'plethoric': ['phloretic', 'plethoric'], + 'pleura': ['epural', 'perula', 'pleura'], + 'pleuric': ['luperci', 'pleuric'], + 'pleuropericardial': ['pericardiopleural', 'pleuropericardial'], + 'pleurotoma': ['pleurotoma', 'tropaeolum'], + 'pleurovisceral': ['pleurovisceral', 'visceropleural'], + 'pliancy': ['pliancy', 'pycnial'], + 'pliant': ['plaint', 'pliant'], + 'plica': ['pical', 'plica'], + 'plicately': ['callitype', 'plicately'], + 'plicater': ['particle', 'plicater', 'prelatic'], + 'plicator': ['plicator', 'tropical'], + 'plied': ['piled', 'plied'], + 'plier': ['peril', 'piler', 'plier'], + 'pliers': ['lisper', 'pliers', 'sirple', 'spiler'], + 'plies': ['piles', 'plies', 'slipe', 'spiel', 'spile'], + 'plighter': ['plighter', 'replight'], + 'plim': ['limp', 'pilm', 'plim'], + 'pliny': ['pinyl', 'pliny'], + 'pliosaur': ['liparous', 'pliosaur'], + 'pliosauridae': ['lepidosauria', 'pliosauridae'], + 'ploceidae': ['adipocele', 'cepolidae', 'ploceidae'], + 'ploceus': ['culpose', 'ploceus', 'upclose'], + 'plodder': ['plodder', 'proddle'], + 'ploima': ['lipoma', 'pimola', 'ploima'], + 'ploration': ['ploration', 'portional', 'prolation'], + 'plot': ['plot', 'polt'], + 'plotful': ['plotful', 'topfull'], + 'plotted': ['plotted', 'pottled'], + 'plotter': ['plotter', 'portlet'], + 'plousiocracy': ['plousiocracy', 'procaciously'], + 'plout': ['plout', 'pluto', 'poult'], + 'plouter': ['plouter', 'poulter'], + 'plovery': ['overply', 'plovery'], + 'plower': ['plower', 'replow'], + 'ploy': ['ploy', 'poly'], + 'plucker': ['plucker', 'puckrel'], + 'plug': ['gulp', 'plug'], + 'plum': ['lump', 'plum'], + 'pluma': ['ampul', 'pluma'], + 'plumbagine': ['impugnable', 'plumbagine'], + 'plumbic': ['plumbic', 'upclimb'], + 'plumed': ['dumple', 'plumed'], + 'plumeous': ['eumolpus', 'plumeous'], + 'plumer': ['lumper', 'plumer', 'replum', 'rumple'], + 'plumet': ['lumpet', 'plumet'], + 'pluminess': ['lumpiness', 'pluminess'], + 'plumy': ['lumpy', 'plumy'], + 'plunderer': ['plunderer', 'replunder'], + 'plunge': ['plunge', 'pungle'], + 'plup': ['plup', 'pulp'], + 'plurennial': ['plenilunar', 'plurennial'], + 'pluriseptate': ['perpetualist', 'pluriseptate'], + 'plutean': ['plutean', 'unpetal', 'unpleat'], + 'pluteus': ['pluteus', 'pustule'], + 'pluto': ['plout', 'pluto', 'poult'], + 'pluvine': ['pluvine', 'vulpine'], + 'plyer': ['plyer', 'reply'], + 'pneumatophony': ['pneumatophony', 'pneumonopathy'], + 'pneumohemothorax': ['hemopneumothorax', 'pneumohemothorax'], + 'pneumohydropericardium': ['hydropneumopericardium', 'pneumohydropericardium'], + 'pneumohydrothorax': ['hydropneumothorax', 'pneumohydrothorax'], + 'pneumonopathy': ['pneumatophony', 'pneumonopathy'], + 'pneumopyothorax': ['pneumopyothorax', 'pyopneumothorax'], + 'poach': ['chopa', 'phoca', 'poach'], + 'poachy': ['poachy', 'pochay'], + 'poales': ['aslope', 'poales'], + 'pob': ['bop', 'pob'], + 'pochay': ['poachy', 'pochay'], + 'poche': ['epoch', 'poche'], + 'pocketer': ['pocketer', 'repocket'], + 'poco': ['coop', 'poco'], + 'pocosin': ['opsonic', 'pocosin'], + 'poculation': ['copulation', 'poculation'], + 'pod': ['dop', 'pod'], + 'podalic': ['placoid', 'podalic', 'podical'], + 'podarthritis': ['podarthritis', 'traditorship'], + 'podial': ['podial', 'poliad'], + 'podical': ['placoid', 'podalic', 'podical'], + 'podiceps': ['podiceps', 'scopiped'], + 'podite': ['pioted', 'podite'], + 'poditti': ['pittoid', 'poditti'], + 'podler': ['podler', 'polder', 'replod'], + 'podley': ['deploy', 'podley'], + 'podobranchia': ['branchiopoda', 'podobranchia'], + 'podocephalous': ['cephalopodous', 'podocephalous'], + 'podophyllous': ['phyllopodous', 'podophyllous'], + 'podoscaph': ['podoscaph', 'scaphopod'], + 'podostomata': ['podostomata', 'stomatopoda'], + 'podostomatous': ['podostomatous', 'stomatopodous'], + 'podotheca': ['chaetopod', 'podotheca'], + 'podura': ['podura', 'uproad'], + 'poduran': ['pandour', 'poduran'], + 'poe': ['ope', 'poe'], + 'poem': ['mope', 'poem', 'pome'], + 'poemet': ['metope', 'poemet'], + 'poemlet': ['leptome', 'poemlet'], + 'poesy': ['poesy', 'posey', 'sepoy'], + 'poet': ['peto', 'poet', 'pote', 'tope'], + 'poetastrical': ['poetastrical', 'spectatorial'], + 'poetical': ['copalite', 'poetical'], + 'poeticism': ['impeticos', 'poeticism'], + 'poetics': ['poetics', 'septoic'], + 'poetly': ['peyotl', 'poetly'], + 'poetryless': ['poetryless', 'presystole'], + 'pogo': ['goop', 'pogo'], + 'poh': ['hop', 'pho', 'poh'], + 'poha': ['opah', 'paho', 'poha'], + 'pohna': ['phano', 'pohna'], + 'poiana': ['anopia', 'aponia', 'poiana'], + 'poietic': ['epiotic', 'poietic'], + 'poimenic': ['mincopie', 'poimenic'], + 'poinder': ['poinder', 'ponerid'], + 'point': ['pinto', 'point'], + 'pointel': ['pointel', 'pontile', 'topline'], + 'pointer': ['pointer', 'protein', 'pterion', 'repoint', 'tropine'], + 'pointlet': ['pentitol', 'pointlet'], + 'pointrel': ['pointrel', 'terpinol'], + 'poisonless': ['poisonless', 'solenopsis'], + 'poker': ['poker', 'proke'], + 'pol': ['lop', 'pol'], + 'polab': ['pablo', 'polab'], + 'polacre': ['capreol', 'polacre'], + 'polander': ['polander', 'ponderal', 'prenodal'], + 'polar': ['parol', 'polar', 'poral', 'proal'], + 'polarid': ['dipolar', 'polarid'], + 'polarimetry': ['polarimetry', 'premorality', 'temporarily'], + 'polaristic': ['polaristic', 'poristical', 'saprolitic'], + 'polarly': ['payroll', 'polarly'], + 'polder': ['podler', 'polder', 'replod'], + 'pole': ['lope', 'olpe', 'pole'], + 'polearm': ['leproma', 'palermo', 'pleroma', 'polearm'], + 'polecat': ['pacolet', 'polecat'], + 'polemic': ['compile', 'polemic'], + 'polemics': ['clipsome', 'polemics'], + 'polemist': ['milepost', 'polemist'], + 'polenta': ['lepanto', 'nepotal', 'petalon', 'polenta'], + 'poler': ['loper', 'poler'], + 'polesman': ['neoplasm', 'pleonasm', 'polesman', 'splenoma'], + 'polestar': ['petrosal', 'polestar'], + 'poliad': ['podial', 'poliad'], + 'polianite': ['epilation', 'polianite'], + 'policyholder': ['policyholder', 'polychloride'], + 'polio': ['polio', 'pooli'], + 'polis': ['polis', 'spoil'], + 'polished': ['depolish', 'polished'], + 'polisher': ['polisher', 'repolish'], + 'polistes': ['polistes', 'telopsis'], + 'politarch': ['carpolith', 'politarch', 'trophical'], + 'politicly': ['lipolytic', 'politicly'], + 'politics': ['colpitis', 'politics', 'psilotic'], + 'polk': ['klop', 'polk'], + 'pollenite': ['pellotine', 'pollenite'], + 'poller': ['poller', 'repoll'], + 'pollinate': ['pellation', 'pollinate'], + 'polo': ['loop', 'polo', 'pool'], + 'poloist': ['loopist', 'poloist', 'topsoil'], + 'polonia': ['apionol', 'polonia'], + 'polos': ['polos', 'sloop', 'spool'], + 'polt': ['plot', 'polt'], + 'poly': ['ploy', 'poly'], + 'polyacid': ['polyacid', 'polyadic'], + 'polyactinal': ['pactionally', 'polyactinal'], + 'polyadic': ['polyacid', 'polyadic'], + 'polyarchist': ['chiroplasty', 'polyarchist'], + 'polychloride': ['policyholder', 'polychloride'], + 'polychroism': ['polychroism', 'polyorchism'], + 'polycitral': ['polycitral', 'tropically'], + 'polycodium': ['lycopodium', 'polycodium'], + 'polycotyl': ['collotypy', 'polycotyl'], + 'polyeidic': ['polyeidic', 'polyideic'], + 'polyeidism': ['polyeidism', 'polyideism'], + 'polyester': ['polyester', 'proselyte'], + 'polygamodioecious': ['dioeciopolygamous', 'polygamodioecious'], + 'polyhalite': ['paleolithy', 'polyhalite', 'polythelia'], + 'polyideic': ['polyeidic', 'polyideic'], + 'polyideism': ['polyeidism', 'polyideism'], + 'polymastic': ['myoplastic', 'polymastic'], + 'polymasty': ['myoplasty', 'polymasty'], + 'polymere': ['employer', 'polymere'], + 'polymeric': ['micropyle', 'polymeric'], + 'polymetochia': ['homeotypical', 'polymetochia'], + 'polymnia': ['olympian', 'polymnia'], + 'polymyodi': ['polymyodi', 'polymyoid'], + 'polymyoid': ['polymyodi', 'polymyoid'], + 'polyorchism': ['polychroism', 'polyorchism'], + 'polyp': ['loppy', 'polyp'], + 'polyphemian': ['lymphopenia', 'polyphemian'], + 'polyphonist': ['polyphonist', 'psilophyton'], + 'polypite': ['lipotype', 'polypite'], + 'polyprene': ['polyprene', 'propylene'], + 'polypterus': ['polypterus', 'suppletory'], + 'polysomitic': ['myocolpitis', 'polysomitic'], + 'polyspore': ['polyspore', 'prosopyle'], + 'polythelia': ['paleolithy', 'polyhalite', 'polythelia'], + 'polythene': ['polythene', 'telephony'], + 'polyuric': ['croupily', 'polyuric'], + 'pom': ['mop', 'pom'], + 'pomade': ['apedom', 'pomade'], + 'pomane': ['mopane', 'pomane'], + 'pome': ['mope', 'poem', 'pome'], + 'pomeranian': ['pomeranian', 'praenomina'], + 'pomerium': ['emporium', 'pomerium', 'proemium'], + 'pomey': ['myope', 'pomey'], + 'pomo': ['moop', 'pomo'], + 'pomonal': ['lampoon', 'pomonal'], + 'pompilus': ['pimplous', 'pompilus', 'populism'], + 'pomster': ['pomster', 'stomper'], + 'ponca': ['capon', 'ponca'], + 'ponce': ['copen', 'ponce'], + 'ponchoed': ['chenopod', 'ponchoed'], + 'poncirus': ['coprinus', 'poncirus'], + 'ponderal': ['polander', 'ponderal', 'prenodal'], + 'ponderate': ['ponderate', 'predonate'], + 'ponderation': ['ponderation', 'predonation'], + 'ponderer': ['ponderer', 'reponder'], + 'pondfish': ['fishpond', 'pondfish'], + 'pone': ['nope', 'open', 'peon', 'pone'], + 'ponerid': ['poinder', 'ponerid'], + 'poneroid': ['poneroid', 'porodine'], + 'poney': ['peony', 'poney'], + 'ponica': ['aponic', 'ponica'], + 'ponier': ['opiner', 'orpine', 'ponier'], + 'pontederia': ['pontederia', 'proteidean'], + 'pontee': ['nepote', 'pontee', 'poteen'], + 'pontes': ['pontes', 'posnet'], + 'ponticular': ['ponticular', 'untropical'], + 'pontificalia': ['palification', 'pontificalia'], + 'pontile': ['pointel', 'pontile', 'topline'], + 'pontonier': ['entropion', 'pontonier', 'prenotion'], + 'pontus': ['pontus', 'unspot', 'unstop'], + 'pooch': ['choop', 'pooch'], + 'pooh': ['hoop', 'phoo', 'pooh'], + 'pooka': ['oopak', 'pooka'], + 'pool': ['loop', 'polo', 'pool'], + 'pooler': ['looper', 'pooler'], + 'pooli': ['polio', 'pooli'], + 'pooly': ['loopy', 'pooly'], + 'poon': ['noop', 'poon'], + 'poonac': ['acopon', 'poonac'], + 'poonga': ['apogon', 'poonga'], + 'poor': ['poor', 'proo'], + 'poot': ['poot', 'toop', 'topo'], + 'pope': ['pepo', 'pope'], + 'popeler': ['peopler', 'popeler'], + 'popery': ['popery', 'pyrope'], + 'popgun': ['oppugn', 'popgun'], + 'popian': ['oppian', 'papion', 'popian'], + 'popish': ['popish', 'shippo'], + 'popliteal': ['papillote', 'popliteal'], + 'poppel': ['poppel', 'popple'], + 'popple': ['poppel', 'popple'], + 'populism': ['pimplous', 'pompilus', 'populism'], + 'populus': ['populus', 'pulpous'], + 'poral': ['parol', 'polar', 'poral', 'proal'], + 'porcate': ['coperta', 'pectora', 'porcate'], + 'porcelain': ['oliprance', 'porcelain'], + 'porcelanite': ['porcelanite', 'praelection'], + 'porcula': ['copular', 'croupal', 'cupolar', 'porcula'], + 'pore': ['pore', 'rope'], + 'pored': ['doper', 'pedro', 'pored'], + 'porelike': ['porelike', 'ropelike'], + 'porer': ['porer', 'prore', 'roper'], + 'porge': ['grope', 'porge'], + 'porger': ['groper', 'porger'], + 'poriness': ['poriness', 'pression', 'ropiness'], + 'poring': ['poring', 'roping'], + 'poristical': ['polaristic', 'poristical', 'saprolitic'], + 'porites': ['periost', 'porites', 'reposit', 'riposte'], + 'poritidae': ['poritidae', 'triopidae'], + 'porker': ['porker', 'proker'], + 'pornerastic': ['cotranspire', 'pornerastic'], + 'porodine': ['poneroid', 'porodine'], + 'poros': ['poros', 'proso', 'sopor', 'spoor'], + 'porosity': ['isotropy', 'porosity'], + 'porotic': ['porotic', 'portico'], + 'porpentine': ['porpentine', 'prepontine'], + 'porphine': ['hornpipe', 'porphine'], + 'porphyrous': ['porphyrous', 'pyrophorus'], + 'porrection': ['correption', 'porrection'], + 'porret': ['porret', 'porter', 'report', 'troper'], + 'porta': ['aport', 'parto', 'porta'], + 'portail': ['portail', 'toprail'], + 'portal': ['patrol', 'portal', 'tropal'], + 'portance': ['coparent', 'portance'], + 'ported': ['deport', 'ported', 'redtop'], + 'portend': ['portend', 'protend'], + 'porteno': ['porteno', 'protone'], + 'portension': ['portension', 'protension'], + 'portent': ['portent', 'torpent'], + 'portentous': ['notopterus', 'portentous'], + 'porter': ['porret', 'porter', 'report', 'troper'], + 'porterage': ['porterage', 'reportage'], + 'portership': ['portership', 'pretorship'], + 'portfire': ['portfire', 'profiter'], + 'portia': ['portia', 'tapiro'], + 'portico': ['porotic', 'portico'], + 'portify': ['portify', 'torpify'], + 'portional': ['ploration', 'portional', 'prolation'], + 'portioner': ['portioner', 'reportion'], + 'portlet': ['plotter', 'portlet'], + 'portly': ['portly', 'protyl', 'tropyl'], + 'porto': ['porto', 'proto', 'troop'], + 'portoise': ['isotrope', 'portoise'], + 'portolan': ['portolan', 'pronotal'], + 'portor': ['portor', 'torpor'], + 'portray': ['parroty', 'portray', 'tropary'], + 'portrayal': ['parlatory', 'portrayal'], + 'portside': ['dipteros', 'portside'], + 'portsider': ['portsider', 'postrider'], + 'portunidae': ['depuration', 'portunidae'], + 'portunus': ['outspurn', 'portunus'], + 'pory': ['pory', 'pyro', 'ropy'], + 'posca': ['posca', 'scopa'], + 'pose': ['epos', 'peso', 'pose', 'sope'], + 'poser': ['poser', 'prose', 'ropes', 'spore'], + 'poseur': ['poseur', 'pouser', 'souper', 'uprose'], + 'posey': ['poesy', 'posey', 'sepoy'], + 'posh': ['phos', 'posh', 'shop', 'soph'], + 'posingly': ['posingly', 'spongily'], + 'position': ['position', 'sopition'], + 'positional': ['positional', 'spoilation', 'spoliation'], + 'positioned': ['deposition', 'positioned'], + 'positioner': ['positioner', 'reposition'], + 'positron': ['notropis', 'positron', 'sorption'], + 'positum': ['positum', 'utopism'], + 'posnet': ['pontes', 'posnet'], + 'posse': ['posse', 'speos'], + 'possessioner': ['possessioner', 'repossession'], + 'post': ['post', 'spot', 'stop', 'tops'], + 'postage': ['gestapo', 'postage'], + 'postaortic': ['parostotic', 'postaortic'], + 'postdate': ['despotat', 'postdate'], + 'posted': ['despot', 'posted'], + 'posteen': ['pentose', 'posteen'], + 'poster': ['poster', 'presto', 'repost', 'respot', 'stoper'], + 'posterial': ['posterial', 'saprolite'], + 'posterior': ['posterior', 'repositor'], + 'posterish': ['posterish', 'prothesis', 'sophister', 'storeship', 'tephrosis'], + 'posteroinferior': ['inferoposterior', 'posteroinferior'], + 'posterosuperior': ['posterosuperior', 'superoposterior'], + 'postgenial': ['postgenial', 'spangolite'], + 'posthaste': ['posthaste', 'tosephtas'], + 'postic': ['copist', 'coptis', 'optics', 'postic'], + 'postical': ['postical', 'slipcoat'], + 'postil': ['pistol', 'postil', 'spoilt'], + 'posting': ['posting', 'stoping'], + 'postischial': ['postischial', 'sophistical'], + 'postless': ['postless', 'spotless', 'stopless'], + 'postlike': ['postlike', 'spotlike'], + 'postman': ['postman', 'topsman'], + 'postmedial': ['plastidome', 'postmedial'], + 'postnaris': ['postnaris', 'sopranist'], + 'postnominal': ['monoplanist', 'postnominal'], + 'postrider': ['portsider', 'postrider'], + 'postsacral': ['postsacral', 'sarcoplast'], + 'postsign': ['postsign', 'signpost'], + 'postthoracic': ['octastrophic', 'postthoracic'], + 'postulata': ['autoplast', 'postulata'], + 'postural': ['postural', 'pulsator', 'sportula'], + 'posture': ['petrous', 'posture', 'proetus', 'proteus', 'septuor', 'spouter'], + 'posturer': ['posturer', 'resprout', 'sprouter'], + 'postuterine': ['postuterine', 'pretentious'], + 'postwar': ['postwar', 'sapwort'], + 'postward': ['drawstop', 'postward'], + 'postwoman': ['postwoman', 'womanpost'], + 'posy': ['opsy', 'posy'], + 'pot': ['opt', 'pot', 'top'], + 'potable': ['optable', 'potable'], + 'potableness': ['optableness', 'potableness'], + 'potash': ['pashto', 'pathos', 'potash'], + 'potass': ['potass', 'topass'], + 'potate': ['aptote', 'optate', 'potate', 'teapot'], + 'potation': ['optation', 'potation'], + 'potative': ['optative', 'potative'], + 'potator': ['potator', 'taproot'], + 'pote': ['peto', 'poet', 'pote', 'tope'], + 'poteen': ['nepote', 'pontee', 'poteen'], + 'potential': ['peltation', 'potential'], + 'poter': ['poter', 'prote', 'repot', 'tepor', 'toper', 'trope'], + 'poteye': ['peyote', 'poteye'], + 'pothouse': ['housetop', 'pothouse'], + 'poticary': ['cyrtopia', 'poticary'], + 'potifer': ['firetop', 'potifer'], + 'potion': ['option', 'potion'], + 'potlatch': ['potlatch', 'tolpatch'], + 'potlike': ['kitlope', 'potlike', 'toplike'], + 'potmaker': ['potmaker', 'topmaker'], + 'potmaking': ['potmaking', 'topmaking'], + 'potman': ['potman', 'tampon', 'topman'], + 'potometer': ['optometer', 'potometer'], + 'potstick': ['potstick', 'tipstock'], + 'potstone': ['potstone', 'topstone'], + 'pottled': ['plotted', 'pottled'], + 'pouce': ['coupe', 'pouce'], + 'poucer': ['couper', 'croupe', 'poucer', 'recoup'], + 'pouch': ['choup', 'pouch'], + 'poulpe': ['poulpe', 'pupelo'], + 'poult': ['plout', 'pluto', 'poult'], + 'poulter': ['plouter', 'poulter'], + 'poultice': ['epulotic', 'poultice'], + 'pounce': ['pounce', 'uncope'], + 'pounder': ['pounder', 'repound', 'unroped'], + 'pour': ['pour', 'roup'], + 'pourer': ['pourer', 'repour', 'rouper'], + 'pouser': ['poseur', 'pouser', 'souper', 'uprose'], + 'pout': ['pout', 'toup'], + 'pouter': ['pouter', 'roupet', 'troupe'], + 'pow': ['pow', 'wop'], + 'powder': ['powder', 'prowed'], + 'powderer': ['powderer', 'repowder'], + 'powerful': ['powerful', 'upflower'], + 'praam': ['param', 'parma', 'praam'], + 'practitional': ['antitropical', 'practitional'], + 'prad': ['pard', 'prad'], + 'pradeep': ['papered', 'pradeep'], + 'praecox': ['exocarp', 'praecox'], + 'praelabrum': ['praelabrum', 'preambular'], + 'praelection': ['porcelanite', 'praelection'], + 'praelector': ['praelector', 'receptoral'], + 'praenomina': ['pomeranian', 'praenomina'], + 'praepostor': ['praepostor', 'pterospora'], + 'praesphenoid': ['nephropsidae', 'praesphenoid'], + 'praetor': ['praetor', 'prorate'], + 'praetorian': ['praetorian', 'reparation'], + 'praise': ['aspire', 'paries', 'praise', 'sirpea', 'spirea'], + 'praiser': ['aspirer', 'praiser', 'serpari'], + 'praising': ['aspiring', 'praising', 'singarip'], + 'praisingly': ['aspiringly', 'praisingly'], + 'praline': ['pearlin', 'plainer', 'praline'], + 'pram': ['pram', 'ramp'], + 'prandial': ['diplanar', 'prandial'], + 'prankle': ['planker', 'prankle'], + 'prase': ['asper', 'parse', 'prase', 'spaer', 'spare', 'spear'], + 'praseolite': ['periosteal', 'praseolite'], + 'prasine': ['persian', 'prasine', 'saprine'], + 'prasinous': ['prasinous', 'psaronius'], + 'prasoid': ['prasoid', 'sparoid'], + 'prasophagous': ['prasophagous', 'saprophagous'], + 'prat': ['part', 'prat', 'rapt', 'tarp', 'trap'], + 'prate': ['apert', 'pater', 'peart', 'prate', 'taper', 'terap'], + 'prater': ['parter', 'prater'], + 'pratey': ['petary', 'pratey'], + 'pratfall': ['pratfall', 'trapfall'], + 'pratincoline': ['nonpearlitic', 'pratincoline'], + 'pratincolous': ['patroclinous', 'pratincolous'], + 'prattle': ['partlet', 'platter', 'prattle'], + 'prau': ['prau', 'rupa'], + 'prawner': ['prawner', 'prewarn'], + 'prayer': ['prayer', 'repray'], + 'preach': ['aperch', 'eparch', 'percha', 'preach'], + 'preacher': ['preacher', 'repreach'], + 'preaching': ['engraphic', 'preaching'], + 'preachman': ['marchpane', 'preachman'], + 'preachy': ['eparchy', 'preachy'], + 'preacid': ['epacrid', 'peracid', 'preacid'], + 'preact': ['carpet', 'peract', 'preact'], + 'preaction': ['preaction', 'precation', 'recaption'], + 'preactive': ['preactive', 'precative'], + 'preactively': ['preactively', 'precatively'], + 'preacute': ['peracute', 'preacute'], + 'preadmonition': ['demipronation', 'preadmonition', 'predomination'], + 'preadorn': ['pardoner', 'preadorn'], + 'preadventure': ['peradventure', 'preadventure'], + 'preallably': ['ballplayer', 'preallably'], + 'preallow': ['preallow', 'walloper'], + 'preamble': ['peramble', 'preamble'], + 'preambular': ['praelabrum', 'preambular'], + 'preambulate': ['perambulate', 'preambulate'], + 'preambulation': ['perambulation', 'preambulation'], + 'preambulatory': ['perambulatory', 'preambulatory'], + 'preanal': ['planera', 'preanal'], + 'prearm': ['prearm', 'ramper'], + 'preascitic': ['accipitres', 'preascitic'], + 'preauditory': ['preauditory', 'repudiatory'], + 'prebacillary': ['bicarpellary', 'prebacillary'], + 'prebasal': ['parsable', 'prebasal', 'sparable'], + 'prebend': ['perbend', 'prebend'], + 'prebeset': ['bepester', 'prebeset'], + 'prebid': ['bedrip', 'prebid'], + 'precant': ['carpent', 'precant'], + 'precantation': ['actinopteran', 'precantation'], + 'precast': ['precast', 'spectra'], + 'precation': ['preaction', 'precation', 'recaption'], + 'precative': ['preactive', 'precative'], + 'precatively': ['preactively', 'precatively'], + 'precaution': ['precaution', 'unoperatic'], + 'precautional': ['inoperculata', 'precautional'], + 'precedable': ['deprecable', 'precedable'], + 'preceder': ['preceder', 'precreed'], + 'precent': ['percent', 'precent'], + 'precept': ['percept', 'precept'], + 'preception': ['perception', 'preception'], + 'preceptive': ['perceptive', 'preceptive'], + 'preceptively': ['perceptively', 'preceptively'], + 'preceptual': ['perceptual', 'preceptual'], + 'preceptually': ['perceptually', 'preceptually'], + 'prechloric': ['perchloric', 'prechloric'], + 'prechoose': ['prechoose', 'rheoscope'], + 'precipitate': ['peripatetic', 'precipitate'], + 'precipitator': ['precipitator', 'prepatriotic'], + 'precis': ['crepis', 'cripes', 'persic', 'precis', 'spicer'], + 'precise': ['precise', 'scripee'], + 'precisian': ['periscian', 'precisian'], + 'precision': ['coinspire', 'precision'], + 'precitation': ['actinopteri', 'crepitation', 'precitation'], + 'precite': ['ereptic', 'precite', 'receipt'], + 'precited': ['decrepit', 'depicter', 'precited'], + 'preclose': ['perclose', 'preclose'], + 'preclusion': ['perculsion', 'preclusion'], + 'preclusive': ['perculsive', 'preclusive'], + 'precoil': ['peloric', 'precoil'], + 'precompound': ['percompound', 'precompound'], + 'precondense': ['precondense', 'respondence'], + 'preconnubial': ['preconnubial', 'pronunciable'], + 'preconsole': ['necropoles', 'preconsole'], + 'preconsultor': ['preconsultor', 'supercontrol'], + 'precontest': ['precontest', 'torpescent'], + 'precopy': ['coppery', 'precopy'], + 'precostal': ['ceroplast', 'precostal'], + 'precredit': ['precredit', 'predirect', 'repredict'], + 'precreditor': ['precreditor', 'predirector'], + 'precreed': ['preceder', 'precreed'], + 'precurrent': ['percurrent', 'precurrent'], + 'precursory': ['percursory', 'precursory'], + 'precyst': ['precyst', 'sceptry', 'spectry'], + 'predata': ['adapter', 'predata', 'readapt'], + 'predate': ['padtree', 'predate', 'tapered'], + 'predatism': ['predatism', 'spermatid'], + 'predative': ['deprivate', 'predative'], + 'predator': ['predator', 'protrade', 'teardrop'], + 'preday': ['pedary', 'preday'], + 'predealer': ['predealer', 'repleader'], + 'predecree': ['creepered', 'predecree'], + 'predefect': ['perfected', 'predefect'], + 'predeication': ['depreciation', 'predeication'], + 'prederive': ['prederive', 'redeprive'], + 'predespair': ['disprepare', 'predespair'], + 'predestine': ['predestine', 'presidente'], + 'predetail': ['pedaliter', 'predetail'], + 'predevotion': ['overpointed', 'predevotion'], + 'predial': ['pedrail', 'predial'], + 'prediastolic': ['prediastolic', 'psiloceratid'], + 'predication': ['predication', 'procidentia'], + 'predictory': ['cryptodire', 'predictory'], + 'predirect': ['precredit', 'predirect', 'repredict'], + 'predirector': ['precreditor', 'predirector'], + 'prediscretion': ['prediscretion', 'redescription'], + 'predislike': ['predislike', 'spiderlike'], + 'predivinable': ['indeprivable', 'predivinable'], + 'predominate': ['pentameroid', 'predominate'], + 'predomination': ['demipronation', 'preadmonition', 'predomination'], + 'predonate': ['ponderate', 'predonate'], + 'predonation': ['ponderation', 'predonation'], + 'predoubter': ['predoubter', 'preobtrude'], + 'predrive': ['depriver', 'predrive'], + 'preen': ['neper', 'preen', 'repen'], + 'prefactor': ['aftercrop', 'prefactor'], + 'prefator': ['forepart', 'prefator'], + 'prefavorite': ['perforative', 'prefavorite'], + 'prefect': ['perfect', 'prefect'], + 'prefectly': ['perfectly', 'prefectly'], + 'prefervid': ['perfervid', 'prefervid'], + 'prefiction': ['prefiction', 'proficient'], + 'prefoliation': ['perfoliation', 'prefoliation'], + 'preform': ['perform', 'preform'], + 'preformant': ['performant', 'preformant'], + 'preformative': ['performative', 'preformative'], + 'preformism': ['misperform', 'preformism'], + 'pregainer': ['peregrina', 'pregainer'], + 'prehandicap': ['handicapper', 'prehandicap'], + 'prehaps': ['perhaps', 'prehaps'], + 'prehazard': ['perhazard', 'prehazard'], + 'preheal': ['preheal', 'rephael'], + 'preheat': ['haptere', 'preheat'], + 'preheated': ['heartdeep', 'preheated'], + 'prehension': ['hesperinon', 'prehension'], + 'prehnite': ['nephrite', 'prehnite', 'trephine'], + 'prehnitic': ['nephritic', 'phrenitic', 'prehnitic'], + 'prehuman': ['prehuman', 'unhamper'], + 'preimpose': ['perispome', 'preimpose'], + 'preindicate': ['parenticide', 'preindicate'], + 'preinduce': ['preinduce', 'unpierced'], + 'preintone': ['interpone', 'peritenon', 'pinnotere', 'preintone'], + 'prelabrum': ['prelabrum', 'prelumbar'], + 'prelacteal': ['carpellate', 'parcellate', 'prelacteal'], + 'prelate': ['pearlet', 'pleater', 'prelate', 'ptereal', 'replate', 'repleat'], + 'prelatehood': ['heteropodal', 'prelatehood'], + 'prelatic': ['particle', 'plicater', 'prelatic'], + 'prelatical': ['capitellar', 'prelatical'], + 'prelation': ['prelation', 'rantipole'], + 'prelatism': ['palmister', 'prelatism'], + 'prelease': ['eelspear', 'prelease'], + 'prelect': ['plectre', 'prelect'], + 'prelection': ['perlection', 'prelection'], + 'prelim': ['limper', 'prelim', 'rimple'], + 'prelingual': ['perlingual', 'prelingual'], + 'prelocate': ['percolate', 'prelocate'], + 'preloss': ['plessor', 'preloss'], + 'preludial': ['dipleural', 'preludial'], + 'prelumbar': ['prelabrum', 'prelumbar'], + 'prelusion': ['prelusion', 'repulsion'], + 'prelusive': ['prelusive', 'repulsive'], + 'prelusively': ['prelusively', 'repulsively'], + 'prelusory': ['prelusory', 'repulsory'], + 'premate': ['premate', 'tempera'], + 'premedia': ['epiderma', 'premedia'], + 'premedial': ['epidermal', 'impleader', 'premedial'], + 'premedication': ['pedometrician', 'premedication'], + 'premenace': ['permeance', 'premenace'], + 'premerit': ['premerit', 'preremit', 'repermit'], + 'premial': ['impaler', 'impearl', 'lempira', 'premial'], + 'premiant': ['imperant', 'pairment', 'partimen', 'premiant', 'tripeman'], + 'premiate': ['imperate', 'premiate'], + 'premier': ['premier', 'reprime'], + 'premious': ['imposure', 'premious'], + 'premise': ['emprise', 'imprese', 'premise', 'spireme'], + 'premiss': ['impress', 'persism', 'premiss'], + 'premixture': ['permixture', 'premixture'], + 'premodel': ['leperdom', 'premodel'], + 'premolar': ['premolar', 'premoral'], + 'premold': ['meldrop', 'premold'], + 'premonetary': ['premonetary', 'pyranometer'], + 'premoral': ['premolar', 'premoral'], + 'premorality': ['polarimetry', 'premorality', 'temporarily'], + 'premosaic': ['paroecism', 'premosaic'], + 'premover': ['premover', 'prevomer'], + 'premusical': ['premusical', 'superclaim'], + 'prenasal': ['pernasal', 'prenasal'], + 'prenatal': ['parental', 'paternal', 'prenatal'], + 'prenatalist': ['intraseptal', 'paternalist', 'prenatalist'], + 'prenatally': ['parentally', 'paternally', 'prenatally'], + 'prenative': ['interpave', 'prenative'], + 'prender': ['prender', 'prendre'], + 'prendre': ['prender', 'prendre'], + 'prenodal': ['polander', 'ponderal', 'prenodal'], + 'prenominical': ['nonempirical', 'prenominical'], + 'prenotice': ['prenotice', 'reception'], + 'prenotion': ['entropion', 'pontonier', 'prenotion'], + 'prentice': ['piercent', 'prentice'], + 'preobtrude': ['predoubter', 'preobtrude'], + 'preocular': ['opercular', 'preocular'], + 'preominate': ['permeation', 'preominate'], + 'preopen': ['preopen', 'propene'], + 'preopinion': ['preopinion', 'prionopine'], + 'preoption': ['preoption', 'protopine'], + 'preoral': ['peroral', 'preoral'], + 'preorally': ['perorally', 'preorally'], + 'prep': ['prep', 'repp'], + 'prepalatine': ['periplaneta', 'prepalatine'], + 'prepare': ['paperer', 'perpera', 'prepare', 'repaper'], + 'prepatriotic': ['precipitator', 'prepatriotic'], + 'prepay': ['papery', 'prepay', 'yapper'], + 'preplot': ['preplot', 'toppler'], + 'prepollent': ['prepollent', 'propellent'], + 'prepontine': ['porpentine', 'prepontine'], + 'prepositure': ['peripterous', 'prepositure'], + 'prepuce': ['prepuce', 'upcreep'], + 'prerational': ['prerational', 'proletarian'], + 'prerealization': ['prerealization', 'proletarianize'], + 'prereceive': ['prereceive', 'reperceive'], + 'prerecital': ['perirectal', 'prerecital'], + 'prereduction': ['interproduce', 'prereduction'], + 'prerefer': ['prerefer', 'reprefer'], + 'prereform': ['performer', 'prereform', 'reperform'], + 'preremit': ['premerit', 'preremit', 'repermit'], + 'prerental': ['prerental', 'replanter'], + 'prerich': ['chirper', 'prerich'], + 'preromantic': ['improcreant', 'preromantic'], + 'presage': ['asperge', 'presage'], + 'presager': ['asperger', 'presager'], + 'presay': ['presay', 'speary'], + 'prescapular': ['prescapular', 'supercarpal'], + 'prescient': ['prescient', 'reinspect'], + 'prescientific': ['interspecific', 'prescientific'], + 'prescribe': ['perscribe', 'prescribe'], + 'prescutal': ['prescutal', 'scalpture'], + 'preseal': ['pleaser', 'preseal', 'relapse'], + 'preseason': ['parsonese', 'preseason'], + 'presell': ['presell', 'respell', 'speller'], + 'present': ['penster', 'present', 'serpent', 'strepen'], + 'presenter': ['presenter', 'represent'], + 'presential': ['alpestrine', 'episternal', 'interlapse', 'presential'], + 'presentist': ['persistent', 'presentist', 'prettiness'], + 'presentive': ['presentive', 'pretensive', 'vespertine'], + 'presentively': ['presentively', 'pretensively'], + 'presentiveness': ['presentiveness', 'pretensiveness'], + 'presently': ['presently', 'serpently'], + 'preserve': ['perverse', 'preserve'], + 'preset': ['pester', 'preset', 'restep', 'streep'], + 'preshare': ['preshare', 'rephrase'], + 'preship': ['preship', 'shipper'], + 'preshortage': ['preshortage', 'stereograph'], + 'preside': ['perseid', 'preside'], + 'presidencia': ['acipenserid', 'presidencia'], + 'president': ['president', 'serpentid'], + 'presidente': ['predestine', 'presidente'], + 'presider': ['presider', 'serriped'], + 'presign': ['presign', 'springe'], + 'presignal': ['espringal', 'presignal', 'relapsing'], + 'presimian': ['mainprise', 'presimian'], + 'presley': ['presley', 'sleepry'], + 'presser': ['presser', 'repress'], + 'pression': ['poriness', 'pression', 'ropiness'], + 'pressive': ['pressive', 'viperess'], + 'prest': ['prest', 'spret'], + 'prestable': ['beplaster', 'prestable'], + 'prestant': ['prestant', 'transept'], + 'prestate': ['prestate', 'pretaste'], + 'presto': ['poster', 'presto', 'repost', 'respot', 'stoper'], + 'prestock': ['prestock', 'sprocket'], + 'prestomial': ['peristomal', 'prestomial'], + 'prestrain': ['prestrain', 'transpire'], + 'presume': ['presume', 'supreme'], + 'presurmise': ['impressure', 'presurmise'], + 'presustain': ['presustain', 'puritaness', 'supersaint'], + 'presystole': ['poetryless', 'presystole'], + 'pretan': ['arpent', + 'enrapt', + 'entrap', + 'panter', + 'parent', + 'pretan', + 'trepan'], + 'pretaste': ['prestate', 'pretaste'], + 'pretensive': ['presentive', 'pretensive', 'vespertine'], + 'pretensively': ['presentively', 'pretensively'], + 'pretensiveness': ['presentiveness', 'pretensiveness'], + 'pretentious': ['postuterine', 'pretentious'], + 'pretercanine': ['irrepentance', 'pretercanine'], + 'preterient': ['preterient', 'triterpene'], + 'pretermit': ['permitter', 'pretermit'], + 'pretheological': ['herpetological', 'pretheological'], + 'pretibial': ['bipartile', 'pretibial'], + 'pretonic': ['inceptor', 'pretonic'], + 'pretorship': ['portership', 'pretorship'], + 'pretrace': ['pretrace', 'recarpet'], + 'pretracheal': ['archprelate', 'pretracheal'], + 'pretrain': ['pretrain', 'terrapin'], + 'pretransmission': ['pretransmission', 'transimpression'], + 'pretreat': ['patterer', 'pretreat'], + 'prettiness': ['persistent', 'presentist', 'prettiness'], + 'prevailer': ['prevailer', 'reprieval'], + 'prevalid': ['deprival', 'prevalid'], + 'prevention': ['prevention', 'provenient'], + 'preversion': ['perversion', 'preversion'], + 'preveto': ['overpet', 'preveto', 'prevote'], + 'previde': ['deprive', 'previde'], + 'previous': ['pervious', 'previous', 'viperous'], + 'previously': ['perviously', 'previously', 'viperously'], + 'previousness': ['perviousness', 'previousness', 'viperousness'], + 'prevoid': ['prevoid', 'provide'], + 'prevomer': ['premover', 'prevomer'], + 'prevote': ['overpet', 'preveto', 'prevote'], + 'prewar': ['prewar', 'rewrap', 'warper'], + 'prewarn': ['prawner', 'prewarn'], + 'prewhip': ['prewhip', 'whipper'], + 'prewrap': ['prewrap', 'wrapper'], + 'prexy': ['prexy', 'pyrex'], + 'prey': ['prey', 'pyre', 'rype'], + 'pria': ['pair', 'pari', 'pria', 'ripa'], + 'price': ['price', 'repic'], + 'priced': ['percid', 'priced'], + 'prich': ['chirp', 'prich'], + 'prickfoot': ['prickfoot', 'tickproof'], + 'prickle': ['pickler', 'prickle'], + 'pride': ['pride', 'pried', 'redip'], + 'pridian': ['pindari', 'pridian'], + 'pried': ['pride', 'pried', 'redip'], + 'prier': ['prier', 'riper'], + 'priest': ['priest', 'pteris', 'sprite', 'stripe'], + 'priestal': ['epistlar', 'pilaster', 'plaister', 'priestal'], + 'priesthood': ['priesthood', 'spritehood'], + 'priestless': ['priestless', 'stripeless'], + 'prig': ['grip', 'prig'], + 'prigman': ['gripman', 'prigman', 'ramping'], + 'prima': ['impar', 'pamir', 'prima'], + 'primage': ['epigram', 'primage'], + 'primal': ['imparl', 'primal'], + 'primates': ['maspiter', 'pastimer', 'primates'], + 'primatial': ['impartial', 'primatial'], + 'primely': ['primely', 'reimply'], + 'primeness': ['primeness', 'spenerism'], + 'primost': ['primost', 'tropism'], + 'primrose': ['primrose', 'promiser'], + 'primsie': ['pismire', 'primsie'], + 'primus': ['primus', 'purism'], + 'prince': ['pincer', 'prince'], + 'princehood': ['cnidophore', 'princehood'], + 'princeite': ['princeite', 'recipient'], + 'princelike': ['pincerlike', 'princelike'], + 'princely': ['pencilry', 'princely'], + 'princesse': ['crepiness', 'princesse'], + 'prine': ['piner', 'prine', 'repin', 'ripen'], + 'pringle': ['pingler', 'pringle'], + 'printed': ['deprint', 'printed'], + 'printer': ['printer', 'reprint'], + 'priodontes': ['desorption', 'priodontes'], + 'prionopine': ['preopinion', 'prionopine'], + 'prisage': ['prisage', 'spairge'], + 'prisal': ['prisal', 'spiral'], + 'prismatoid': ['diatropism', 'prismatoid'], + 'prisometer': ['prisometer', 'spirometer'], + 'prisonable': ['bipersonal', 'prisonable'], + 'pristane': ['pinaster', 'pristane'], + 'pristine': ['enspirit', 'pristine'], + 'pristis': ['pristis', 'tripsis'], + 'prius': ['prius', 'sirup'], + 'proadmission': ['adpromission', 'proadmission'], + 'proal': ['parol', 'polar', 'poral', 'proal'], + 'proalien': ['pelorian', 'peronial', 'proalien'], + 'proamniotic': ['comparition', 'proamniotic'], + 'proathletic': ['proathletic', 'prothetical'], + 'proatlas': ['pastoral', 'proatlas'], + 'proavis': ['pavisor', 'proavis'], + 'probationer': ['probationer', 'reprobation'], + 'probe': ['probe', 'rebop'], + 'procaciously': ['plousiocracy', 'procaciously'], + 'procaine': ['caponier', 'coprinae', 'procaine'], + 'procanal': ['coplanar', 'procanal'], + 'procapital': ['applicator', 'procapital'], + 'procedure': ['procedure', 'reproduce'], + 'proceeder': ['proceeder', 'reproceed'], + 'procellas': ['procellas', 'scalloper'], + 'procerite': ['procerite', 'receiptor'], + 'procession': ['procession', 'scorpiones'], + 'prochemical': ['microcephal', 'prochemical'], + 'procidentia': ['predication', 'procidentia'], + 'proclaimer': ['proclaimer', 'reproclaim'], + 'procne': ['crepon', 'procne'], + 'procnemial': ['complainer', 'procnemial', 'recomplain'], + 'procommission': ['compromission', 'procommission'], + 'procreant': ['copartner', 'procreant'], + 'procreate': ['procreate', 'pterocera'], + 'procreation': ['incorporate', 'procreation'], + 'proctal': ['caltrop', 'proctal'], + 'proctitis': ['proctitis', 'protistic', 'tropistic'], + 'proctocolitis': ['coloproctitis', 'proctocolitis'], + 'procuress': ['percussor', 'procuress'], + 'prod': ['dorp', 'drop', 'prod'], + 'proddle': ['plodder', 'proddle'], + 'proem': ['merop', 'moper', 'proem', 'remop'], + 'proemial': ['emporial', 'proemial'], + 'proemium': ['emporium', 'pomerium', 'proemium'], + 'proethical': ['carpholite', 'proethical'], + 'proetid': ['diopter', 'peridot', 'proetid', 'protide', 'pteroid'], + 'proetidae': ['periodate', 'proetidae', 'proteidae'], + 'proetus': ['petrous', 'posture', 'proetus', 'proteus', 'septuor', 'spouter'], + 'proficient': ['prefiction', 'proficient'], + 'profit': ['forpit', 'profit'], + 'profiter': ['portfire', 'profiter'], + 'progeny': ['progeny', 'pyrogen'], + 'prohibiter': ['prohibiter', 'reprohibit'], + 'proidealistic': ['peridiastolic', 'periodicalist', 'proidealistic'], + 'proke': ['poker', 'proke'], + 'proker': ['porker', 'proker'], + 'prolacrosse': ['prolacrosse', 'sclerospora'], + 'prolapse': ['prolapse', 'sapropel'], + 'prolation': ['ploration', 'portional', 'prolation'], + 'prolegate': ['petrogale', 'petrolage', 'prolegate'], + 'proletarian': ['prerational', 'proletarian'], + 'proletarianize': ['prerealization', 'proletarianize'], + 'proletariat': ['proletariat', 'reptatorial'], + 'proletary': ['proletary', 'pyrolater'], + 'prolicense': ['prolicense', 'proselenic'], + 'prolongate': ['prolongate', 'protogenal'], + 'promerit': ['importer', 'promerit', 'reimport'], + 'promethean': ['heptameron', 'promethean'], + 'promise': ['imposer', 'promise', 'semipro'], + 'promisee': ['perisome', 'promisee', 'reimpose'], + 'promiser': ['primrose', 'promiser'], + 'promitosis': ['isotropism', 'promitosis'], + 'promnesia': ['mesropian', 'promnesia', 'spironema'], + 'promonarchist': ['micranthropos', 'promonarchist'], + 'promote': ['promote', 'protome'], + 'pronaos': ['pronaos', 'soprano'], + 'pronate': ['operant', 'pronate', 'protean'], + 'pronative': ['overpaint', 'pronative'], + 'proneur': ['proneur', 'purrone'], + 'pronotal': ['portolan', 'pronotal'], + 'pronto': ['pronto', 'proton'], + 'pronunciable': ['preconnubial', 'pronunciable'], + 'proo': ['poor', 'proo'], + 'proofer': ['proofer', 'reproof'], + 'prop': ['prop', 'ropp'], + 'propellent': ['prepollent', 'propellent'], + 'propene': ['preopen', 'propene'], + 'prophloem': ['pleomorph', 'prophloem'], + 'propine': ['piperno', 'propine'], + 'propinoic': ['propinoic', 'propionic'], + 'propionic': ['propinoic', 'propionic'], + 'propitial': ['propitial', 'triplopia'], + 'proportioner': ['proportioner', 'reproportion'], + 'propose': ['opposer', 'propose'], + 'propraetorial': ['propraetorial', 'protoperlaria'], + 'proprietous': ['peritropous', 'proprietous'], + 'propylene': ['polyprene', 'propylene'], + 'propyne': ['propyne', 'pyropen'], + 'prorate': ['praetor', 'prorate'], + 'proration': ['proration', 'troparion'], + 'prore': ['porer', 'prore', 'roper'], + 'prorebate': ['perborate', 'prorebate', 'reprobate'], + 'proreduction': ['proreduction', 'reproduction'], + 'prorevision': ['prorevision', 'provisioner', 'reprovision'], + 'prorogate': ['graperoot', 'prorogate'], + 'prosaist': ['prosaist', 'protasis'], + 'prosateur': ['prosateur', 'pterosaur'], + 'prose': ['poser', 'prose', 'ropes', 'spore'], + 'prosecretin': ['prosecretin', 'reinspector'], + 'prosectorial': ['corporealist', 'prosectorial'], + 'prosectorium': ['micropterous', 'prosectorium'], + 'proselenic': ['prolicense', 'proselenic'], + 'proselyte': ['polyester', 'proselyte'], + 'proseminate': ['impersonate', 'proseminate'], + 'prosemination': ['impersonation', 'prosemination', 'semipronation'], + 'proseneschal': ['chaperonless', 'proseneschal'], + 'prosification': ['antisoporific', 'prosification', 'sporification'], + 'prosilient': ['linopteris', 'prosilient'], + 'prosiphonate': ['nephroptosia', 'prosiphonate'], + 'proso': ['poros', 'proso', 'sopor', 'spoor'], + 'prosodiacal': ['dorsoapical', 'prosodiacal'], + 'prosopyle': ['polyspore', 'prosopyle'], + 'prossy': ['prossy', 'spyros'], + 'prostatectomy': ['cryptostomate', 'prostatectomy'], + 'prosternate': ['paternoster', 'prosternate', 'transportee'], + 'prostomiate': ['metroptosia', 'prostomiate'], + 'protactic': ['catoptric', 'protactic'], + 'protasis': ['prosaist', 'protasis'], + 'prote': ['poter', 'prote', 'repot', 'tepor', 'toper', 'trope'], + 'protead': ['adopter', 'protead', 'readopt'], + 'protean': ['operant', 'pronate', 'protean'], + 'protease': ['asterope', 'protease'], + 'protectional': ['lactoprotein', 'protectional'], + 'proteic': ['perotic', 'proteic', 'tropeic'], + 'proteida': ['apteroid', 'proteida'], + 'proteidae': ['periodate', 'proetidae', 'proteidae'], + 'proteidean': ['pontederia', 'proteidean'], + 'protein': ['pointer', 'protein', 'pterion', 'repoint', 'tropine'], + 'proteinic': ['epornitic', 'proteinic'], + 'proteles': ['proteles', 'serpolet'], + 'protelidae': ['leopardite', 'protelidae'], + 'protend': ['portend', 'protend'], + 'protension': ['portension', 'protension'], + 'proteolysis': ['elytroposis', 'proteolysis'], + 'proteose': ['esotrope', 'proteose'], + 'protest': ['protest', 'spotter'], + 'protester': ['protester', 'reprotest'], + 'proteus': ['petrous', 'posture', 'proetus', 'proteus', 'septuor', 'spouter'], + 'protheca': ['archpoet', 'protheca'], + 'prothesis': ['posterish', 'prothesis', 'sophister', 'storeship', 'tephrosis'], + 'prothetical': ['proathletic', 'prothetical'], + 'prothoracic': ['acrotrophic', 'prothoracic'], + 'protide': ['diopter', 'peridot', 'proetid', 'protide', 'pteroid'], + 'protist': ['protist', 'tropist'], + 'protistic': ['proctitis', 'protistic', 'tropistic'], + 'proto': ['porto', 'proto', 'troop'], + 'protocneme': ['mecopteron', 'protocneme'], + 'protogenal': ['prolongate', 'protogenal'], + 'protoma': ['protoma', 'taproom'], + 'protomagnesium': ['protomagnesium', 'spermatogonium'], + 'protome': ['promote', 'protome'], + 'protomorphic': ['morphotropic', 'protomorphic'], + 'proton': ['pronto', 'proton'], + 'protone': ['porteno', 'protone'], + 'protonemal': ['monopteral', 'protonemal'], + 'protoparent': ['protoparent', 'protopteran'], + 'protopathic': ['haptotropic', 'protopathic'], + 'protopathy': ['protopathy', 'protophyta'], + 'protoperlaria': ['propraetorial', 'protoperlaria'], + 'protophyta': ['protopathy', 'protophyta'], + 'protophyte': ['protophyte', 'tropophyte'], + 'protophytic': ['protophytic', 'tropophytic'], + 'protopine': ['preoption', 'protopine'], + 'protopteran': ['protoparent', 'protopteran'], + 'protore': ['protore', 'trooper'], + 'protosulphide': ['protosulphide', 'sulphoproteid'], + 'prototheme': ['photometer', 'prototheme'], + 'prototherian': ['ornithoptera', 'prototherian'], + 'prototrophic': ['prototrophic', 'trophotropic'], + 'protrade': ['predator', 'protrade', 'teardrop'], + 'protreaty': ['protreaty', 'reptatory'], + 'protuberantial': ['perturbational', 'protuberantial'], + 'protyl': ['portly', 'protyl', 'tropyl'], + 'provenient': ['prevention', 'provenient'], + 'provide': ['prevoid', 'provide'], + 'provider': ['overdrip', 'provider'], + 'provisioner': ['prorevision', 'provisioner', 'reprovision'], + 'prowed': ['powder', 'prowed'], + 'prude': ['drupe', 'duper', 'perdu', 'prude', 'pured'], + 'prudent': ['prudent', 'prunted', 'uptrend'], + 'prudential': ['prudential', 'putredinal'], + 'prudist': ['disrupt', 'prudist'], + 'prudy': ['prudy', 'purdy', 'updry'], + 'prue': ['peru', 'prue', 'pure'], + 'prune': ['perun', 'prune'], + 'prunted': ['prudent', 'prunted', 'uptrend'], + 'prussic': ['prussic', 'scirpus'], + 'prut': ['prut', 'turp'], + 'pry': ['pry', 'pyr'], + 'pryer': ['perry', 'pryer'], + 'pryse': ['pryse', 'spyer'], + 'psalm': ['plasm', 'psalm', 'slamp'], + 'psalmic': ['plasmic', 'psalmic'], + 'psalmister': ['psalmister', 'spermalist'], + 'psalmodial': ['plasmodial', 'psalmodial'], + 'psalmodic': ['plasmodic', 'psalmodic'], + 'psaloid': ['psaloid', 'salpoid'], + 'psalter': ['palster', 'persalt', 'plaster', 'psalter', 'spartle', 'stapler'], + 'psalterian': ['alpestrian', 'palestrian', 'psalterian'], + 'psalterion': ['interposal', 'psalterion'], + 'psaltery': ['plastery', 'psaltery'], + 'psaltress': ['psaltress', 'strapless'], + 'psaronius': ['prasinous', 'psaronius'], + 'psedera': ['psedera', 'respade'], + 'psellism': ['misspell', 'psellism'], + 'pseudelytron': ['pseudelytron', 'unproselyted'], + 'pseudimago': ['megapodius', 'pseudimago'], + 'pseudophallic': ['diplocephalus', 'pseudophallic'], + 'psha': ['hasp', 'pash', 'psha', 'shap'], + 'psi': ['psi', 'sip'], + 'psiloceratid': ['prediastolic', 'psiloceratid'], + 'psilophyton': ['polyphonist', 'psilophyton'], + 'psilotic': ['colpitis', 'politics', 'psilotic'], + 'psittacine': ['antiseptic', 'psittacine'], + 'psoadic': ['psoadic', 'scapoid', 'sciapod'], + 'psoas': ['passo', 'psoas'], + 'psocidae': ['diascope', 'psocidae', 'scopidae'], + 'psocine': ['psocine', 'scopine'], + 'psora': ['psora', 'sapor', 'sarpo'], + 'psoralea': ['parosela', 'psoralea'], + 'psoroid': ['psoroid', 'sporoid'], + 'psorous': ['psorous', 'soursop', 'sporous'], + 'psychobiological': ['biopsychological', 'psychobiological'], + 'psychobiology': ['biopsychology', 'psychobiology'], + 'psychogalvanic': ['galvanopsychic', 'psychogalvanic'], + 'psychomancy': ['psychomancy', 'scyphomancy'], + 'psychomonism': ['monopsychism', 'psychomonism'], + 'psychoneurological': ['neuropsychological', 'psychoneurological'], + 'psychoneurosis': ['neuropsychosis', 'psychoneurosis'], + 'psychophysiological': ['physiopsychological', 'psychophysiological'], + 'psychophysiology': ['physiopsychology', 'psychophysiology'], + 'psychorrhagy': ['chrysography', 'psychorrhagy'], + 'psychosomatic': ['psychosomatic', 'somatopsychic'], + 'psychotechnology': ['psychotechnology', 'technopsychology'], + 'psychotheism': ['psychotheism', 'theopsychism'], + 'psychotria': ['physiocrat', 'psychotria'], + 'ptelea': ['apelet', 'ptelea'], + 'ptereal': ['pearlet', 'pleater', 'prelate', 'ptereal', 'replate', 'repleat'], + 'pterian': ['painter', 'pertain', 'pterian', 'repaint'], + 'pterideous': ['depositure', 'pterideous'], + 'pteridological': ['dipterological', 'pteridological'], + 'pteridologist': ['dipterologist', 'pteridologist'], + 'pteridology': ['dipterology', 'pteridology'], + 'pterion': ['pointer', 'protein', 'pterion', 'repoint', 'tropine'], + 'pteris': ['priest', 'pteris', 'sprite', 'stripe'], + 'pterocera': ['procreate', 'pterocera'], + 'pterodactylidae': ['dactylopteridae', 'pterodactylidae'], + 'pterodactylus': ['dactylopterus', 'pterodactylus'], + 'pterographer': ['petrographer', 'pterographer'], + 'pterographic': ['petrographic', 'pterographic'], + 'pterographical': ['petrographical', 'pterographical'], + 'pterography': ['petrography', 'pterography', 'typographer'], + 'pteroid': ['diopter', 'peridot', 'proetid', 'protide', 'pteroid'], + 'pteroma': ['pteroma', 'tempora'], + 'pteropus': ['pteropus', 'stoppeur'], + 'pterosaur': ['prosateur', 'pterosaur'], + 'pterospora': ['praepostor', 'pterospora'], + 'pteryla': ['apertly', 'peartly', 'platery', 'pteryla', 'taperly'], + 'pterylographical': ['petrographically', 'pterylographical'], + 'pterylological': ['petrologically', 'pterylological'], + 'pterylosis': ['peristylos', 'pterylosis'], + 'ptilota': ['ptilota', 'talipot', 'toptail'], + 'ptinus': ['ptinus', 'unspit'], + 'ptolemean': ['leptonema', 'ptolemean'], + 'ptomain': ['maintop', 'ptomain', 'tampion', 'timpano'], + 'ptomainic': ['impaction', 'ptomainic'], + 'ptyalin': ['inaptly', 'planity', 'ptyalin'], + 'ptyalocele': ['clypeolate', 'ptyalocele'], + 'ptyalogenic': ['genotypical', 'ptyalogenic'], + 'pu': ['pu', 'up'], + 'pua': ['pau', 'pua'], + 'puan': ['napu', 'puan', 'puna'], + 'publisher': ['publisher', 'republish'], + 'puckball': ['puckball', 'pullback'], + 'puckrel': ['plucker', 'puckrel'], + 'pud': ['dup', 'pud'], + 'pudendum': ['pudendum', 'undumped'], + 'pudent': ['pudent', 'uptend'], + 'pudic': ['cupid', 'pudic'], + 'pudical': ['paludic', 'pudical'], + 'pudicity': ['cupidity', 'pudicity'], + 'puerer': ['puerer', 'purree'], + 'puffer': ['puffer', 'repuff'], + 'pug': ['gup', 'pug'], + 'pugman': ['panmug', 'pugman'], + 'puisne': ['puisne', 'supine'], + 'puist': ['puist', 'upsit'], + 'puja': ['jaup', 'puja'], + 'puke': ['keup', 'puke'], + 'pule': ['lupe', 'pelu', 'peul', 'pule'], + 'pulian': ['paulin', 'pulian'], + 'pulicene': ['clupeine', 'pulicene'], + 'pulicidal': ['picudilla', 'pulicidal'], + 'pulicide': ['lupicide', 'pediculi', 'pulicide'], + 'puling': ['gulpin', 'puling'], + 'pulish': ['huspil', 'pulish'], + 'pullback': ['puckball', 'pullback'], + 'pulp': ['plup', 'pulp'], + 'pulper': ['pulper', 'purple'], + 'pulpiter': ['pulpiter', 'repulpit'], + 'pulpous': ['populus', 'pulpous'], + 'pulpstone': ['pulpstone', 'unstopple'], + 'pulsant': ['pulsant', 'upslant'], + 'pulsate': ['pulsate', 'spatule', 'upsteal'], + 'pulsatile': ['palluites', 'pulsatile'], + 'pulsation': ['platinous', 'pulsation'], + 'pulsator': ['postural', 'pulsator', 'sportula'], + 'pulse': ['lepus', 'pulse'], + 'pulsion': ['pulsion', 'unspoil', 'upsilon'], + 'pulvic': ['pulvic', 'vulpic'], + 'pumper': ['pumper', 'repump'], + 'pumple': ['peplum', 'pumple'], + 'puna': ['napu', 'puan', 'puna'], + 'puncher': ['puncher', 'unperch'], + 'punctilio': ['punctilio', 'unpolitic'], + 'puncturer': ['puncturer', 'upcurrent'], + 'punger': ['punger', 'repugn'], + 'pungle': ['plunge', 'pungle'], + 'puniceous': ['pecunious', 'puniceous'], + 'punish': ['inpush', 'punish', 'unship'], + 'punisher': ['punisher', 'repunish'], + 'punishment': ['punishment', 'unshipment'], + 'punlet': ['penult', 'punlet', 'puntel'], + 'punnet': ['punnet', 'unpent'], + 'puno': ['noup', 'puno', 'upon'], + 'punta': ['punta', 'unapt', 'untap'], + 'puntal': ['puntal', 'unplat'], + 'puntel': ['penult', 'punlet', 'puntel'], + 'punti': ['input', 'punti'], + 'punto': ['punto', 'unpot', 'untop'], + 'pupa': ['paup', 'pupa'], + 'pupelo': ['poulpe', 'pupelo'], + 'purana': ['purana', 'uparna'], + 'purdy': ['prudy', 'purdy', 'updry'], + 'pure': ['peru', 'prue', 'pure'], + 'pured': ['drupe', 'duper', 'perdu', 'prude', 'pured'], + 'puree': ['puree', 'rupee'], + 'purer': ['purer', 'purre'], + 'purine': ['purine', 'unripe', 'uprein'], + 'purism': ['primus', 'purism'], + 'purist': ['purist', 'spruit', 'uprist', 'upstir'], + 'puritan': ['pintura', 'puritan', 'uptrain'], + 'puritaness': ['presustain', 'puritaness', 'supersaint'], + 'purler': ['purler', 'purrel'], + 'purple': ['pulper', 'purple'], + 'purpose': ['peropus', 'purpose'], + 'purpuroxanthin': ['purpuroxanthin', 'xanthopurpurin'], + 'purre': ['purer', 'purre'], + 'purree': ['puerer', 'purree'], + 'purrel': ['purler', 'purrel'], + 'purrone': ['proneur', 'purrone'], + 'purse': ['purse', 'resup', 'sprue', 'super'], + 'purser': ['purser', 'spruer'], + 'purslane': ['purslane', 'serpulan', 'supernal'], + 'purslet': ['purslet', 'spurlet', 'spurtle'], + 'pursuer': ['pursuer', 'usurper'], + 'pursy': ['pursy', 'pyrus', 'syrup'], + 'pus': ['pus', 'sup'], + 'pushtu': ['pushtu', 'upshut'], + 'pustule': ['pluteus', 'pustule'], + 'pustulose': ['pustulose', 'stupulose'], + 'put': ['put', 'tup'], + 'putanism': ['putanism', 'sumpitan'], + 'putation': ['outpaint', 'putation'], + 'putredinal': ['prudential', 'putredinal'], + 'putrid': ['putrid', 'turpid'], + 'putridly': ['putridly', 'turpidly'], + 'pya': ['pay', 'pya', 'yap'], + 'pyal': ['paly', 'play', 'pyal', 'pyla'], + 'pycnial': ['pliancy', 'pycnial'], + 'pyelic': ['epicly', 'pyelic'], + 'pyelitis': ['pyelitis', 'sipylite'], + 'pyelocystitis': ['cystopyelitis', 'pyelocystitis'], + 'pyelonephritis': ['nephropyelitis', 'pyelonephritis'], + 'pyeloureterogram': ['pyeloureterogram', 'ureteropyelogram'], + 'pyemesis': ['empyesis', 'pyemesis'], + 'pygmalion': ['maypoling', 'pygmalion'], + 'pyin': ['piny', 'pyin'], + 'pyla': ['paly', 'play', 'pyal', 'pyla'], + 'pylades': ['pylades', 'splayed'], + 'pylagore': ['playgoer', 'pylagore'], + 'pylar': ['parly', 'pylar', 'pyral'], + 'pyonephrosis': ['nephropyosis', 'pyonephrosis'], + 'pyopneumothorax': ['pneumopyothorax', 'pyopneumothorax'], + 'pyosepticemia': ['pyosepticemia', 'septicopyemia'], + 'pyosepticemic': ['pyosepticemic', 'septicopyemic'], + 'pyr': ['pry', 'pyr'], + 'pyracanth': ['pantarchy', 'pyracanth'], + 'pyral': ['parly', 'pylar', 'pyral'], + 'pyrales': ['parsley', 'pyrales', 'sparely', 'splayer'], + 'pyralid': ['pyralid', 'rapidly'], + 'pyramidale': ['lampyridae', 'pyramidale'], + 'pyranometer': ['premonetary', 'pyranometer'], + 'pyre': ['prey', 'pyre', 'rype'], + 'pyrena': ['napery', 'pyrena'], + 'pyrenic': ['cyprine', 'pyrenic'], + 'pyrenoid': ['pyrenoid', 'pyridone', 'pyrodine'], + 'pyretogenic': ['pyretogenic', 'pyrogenetic'], + 'pyrex': ['prexy', 'pyrex'], + 'pyrgocephaly': ['pelycography', 'pyrgocephaly'], + 'pyridone': ['pyrenoid', 'pyridone', 'pyrodine'], + 'pyrites': ['pyrites', 'sperity'], + 'pyritoid': ['pityroid', 'pyritoid'], + 'pyro': ['pory', 'pyro', 'ropy'], + 'pyroarsenite': ['arsenopyrite', 'pyroarsenite'], + 'pyrochemical': ['microcephaly', 'pyrochemical'], + 'pyrocomenic': ['pyrocomenic', 'pyromeconic'], + 'pyrodine': ['pyrenoid', 'pyridone', 'pyrodine'], + 'pyrogen': ['progeny', 'pyrogen'], + 'pyrogenetic': ['pyretogenic', 'pyrogenetic'], + 'pyrolater': ['proletary', 'pyrolater'], + 'pyromantic': ['importancy', 'patronymic', 'pyromantic'], + 'pyromeconic': ['pyrocomenic', 'pyromeconic'], + 'pyrope': ['popery', 'pyrope'], + 'pyropen': ['propyne', 'pyropen'], + 'pyrophorus': ['porphyrous', 'pyrophorus'], + 'pyrotheria': ['erythropia', 'pyrotheria'], + 'pyruline': ['pyruline', 'unripely'], + 'pyrus': ['pursy', 'pyrus', 'syrup'], + 'pyruvil': ['pyruvil', 'pyvuril'], + 'pythagorism': ['myographist', 'pythagorism'], + 'pythia': ['pythia', 'typhia'], + 'pythic': ['phytic', 'pitchy', 'pythic', 'typhic'], + 'pythogenesis': ['phytogenesis', 'pythogenesis'], + 'pythogenetic': ['phytogenetic', 'pythogenetic'], + 'pythogenic': ['phytogenic', 'pythogenic', 'typhogenic'], + 'pythogenous': ['phytogenous', 'pythogenous'], + 'python': ['phyton', 'python'], + 'pythonic': ['hypnotic', 'phytonic', 'pythonic', 'typhonic'], + 'pythonism': ['hypnotism', 'pythonism'], + 'pythonist': ['hypnotist', 'pythonist'], + 'pythonize': ['hypnotize', 'pythonize'], + 'pythonoid': ['hypnotoid', 'pythonoid'], + 'pyvuril': ['pyruvil', 'pyvuril'], + 'quadrual': ['quadrual', 'quadrula'], + 'quadrula': ['quadrual', 'quadrula'], + 'quail': ['quail', 'quila'], + 'quake': ['quake', 'queak'], + 'quale': ['equal', 'quale', 'queal'], + 'qualitied': ['liquidate', 'qualitied'], + 'quamoclit': ['coquitlam', 'quamoclit'], + 'quannet': ['quannet', 'tanquen'], + 'quartile': ['quartile', 'requital', 'triequal'], + 'quartine': ['antiquer', 'quartine'], + 'quata': ['quata', 'taqua'], + 'quatrin': ['quatrin', 'tarquin'], + 'queak': ['quake', 'queak'], + 'queal': ['equal', 'quale', 'queal'], + 'queeve': ['eveque', 'queeve'], + 'quencher': ['quencher', 'requench'], + 'querier': ['querier', 'require'], + 'queriman': ['queriman', 'ramequin'], + 'querist': ['querist', 'squiret'], + 'quernal': ['quernal', 'ranquel'], + 'quester': ['quester', 'request'], + 'questioner': ['questioner', 'requestion'], + 'questor': ['questor', 'torques'], + 'quiet': ['quiet', 'quite'], + 'quietable': ['equitable', 'quietable'], + 'quieter': ['quieter', 'requite'], + 'quietist': ['equitist', 'quietist'], + 'quietsome': ['quietsome', 'semiquote'], + 'quiina': ['quiina', 'quinia'], + 'quila': ['quail', 'quila'], + 'quiles': ['quiles', 'quisle'], + 'quinate': ['antique', 'quinate'], + 'quince': ['cinque', 'quince'], + 'quinia': ['quiina', 'quinia'], + 'quinite': ['inquiet', 'quinite'], + 'quinnat': ['quinnat', 'quintan'], + 'quinse': ['quinse', 'sequin'], + 'quintan': ['quinnat', 'quintan'], + 'quintato': ['quintato', 'totaquin'], + 'quinze': ['quinze', 'zequin'], + 'quirt': ['quirt', 'qurti'], + 'quisle': ['quiles', 'quisle'], + 'quite': ['quiet', 'quite'], + 'quits': ['quits', 'squit'], + 'quote': ['quote', 'toque'], + 'quoter': ['quoter', 'roquet', 'torque'], + 'qurti': ['quirt', 'qurti'], + 'ra': ['ar', 'ra'], + 'raad': ['adar', 'arad', 'raad', 'rada'], + 'raash': ['asarh', 'raash', 'sarah'], + 'rab': ['bar', 'bra', 'rab'], + 'raband': ['bandar', 'raband'], + 'rabatine': ['atabrine', 'rabatine'], + 'rabatte': ['baretta', 'rabatte', 'tabaret'], + 'rabbanite': ['barnabite', 'rabbanite', 'rabbinate'], + 'rabbet': ['barbet', 'rabbet', 'tabber'], + 'rabbinate': ['barnabite', 'rabbanite', 'rabbinate'], + 'rabble': ['barbel', 'labber', 'rabble'], + 'rabboni': ['barbion', 'rabboni'], + 'rabi': ['abir', 'bari', 'rabi'], + 'rabic': ['baric', 'carib', 'rabic'], + 'rabid': ['barid', 'bidar', 'braid', 'rabid'], + 'rabidly': ['bardily', 'rabidly', 'ridably'], + 'rabidness': ['bardiness', 'rabidness'], + 'rabies': ['braise', 'rabies', 'rebias'], + 'rabin': ['abrin', 'bairn', 'brain', 'brian', 'rabin'], + 'rabinet': ['atebrin', 'rabinet'], + 'raccoon': ['carcoon', 'raccoon'], + 'race': ['acer', 'acre', 'care', 'crea', 'race'], + 'racemate': ['camerate', 'macerate', 'racemate'], + 'racemation': ['aeromantic', 'cameration', 'maceration', 'racemation'], + 'raceme': ['amerce', 'raceme'], + 'racemed': ['decream', 'racemed'], + 'racemic': ['ceramic', 'racemic'], + 'racer': ['carer', 'crare', 'racer'], + 'rach': ['arch', 'char', 'rach'], + 'rache': ['acher', 'arche', 'chare', 'chera', 'rache', 'reach'], + 'rachel': ['rachel', 'rechal'], + 'rachianectes': ['rachianectes', 'rhacianectes'], + 'rachidial': ['diarchial', 'rachidial'], + 'rachitis': ['architis', 'rachitis'], + 'racial': ['alaric', 'racial'], + 'racialist': ['racialist', 'satirical'], + 'racing': ['arcing', 'racing'], + 'racist': ['crista', 'racist'], + 'rack': ['cark', 'rack'], + 'racker': ['racker', 'rerack'], + 'racket': ['racket', 'retack', 'tacker'], + 'racking': ['arcking', 'carking', 'racking'], + 'rackingly': ['carkingly', 'rackingly'], + 'rackle': ['calker', 'lacker', 'rackle', 'recalk', 'reckla'], + 'racon': ['acorn', 'acron', 'racon'], + 'raconteur': ['cuarteron', 'raconteur'], + 'racoon': ['caroon', 'corona', 'racoon'], + 'racy': ['cary', 'racy'], + 'rad': ['dar', 'rad'], + 'rada': ['adar', 'arad', 'raad', 'rada'], + 'raddle': ['ladder', 'raddle'], + 'raddleman': ['dreamland', 'raddleman'], + 'radectomy': ['myctodera', 'radectomy'], + 'radek': ['daker', 'drake', 'kedar', 'radek'], + 'radiable': ['labridae', 'radiable'], + 'radiale': ['ardelia', 'laridae', 'radiale'], + 'radian': ['adrian', 'andira', 'andria', 'radian', 'randia'], + 'radiance': ['caridean', 'dircaean', 'radiance'], + 'radiant': ['intrada', 'radiant'], + 'radiata': ['dataria', 'radiata'], + 'radical': ['cardial', 'radical'], + 'radicant': ['antacrid', 'cardiant', 'radicant', 'tridacna'], + 'radicel': ['decrial', 'radicel', 'radicle'], + 'radices': ['diceras', 'radices', 'sidecar'], + 'radicle': ['decrial', 'radicel', 'radicle'], + 'radicose': ['idocrase', 'radicose'], + 'radicule': ['auricled', 'radicule'], + 'radiculose': ['coresidual', 'radiculose'], + 'radiectomy': ['acidometry', 'medicatory', 'radiectomy'], + 'radii': ['dairi', 'darii', 'radii'], + 'radio': ['aroid', 'doria', 'radio'], + 'radioautograph': ['autoradiograph', 'radioautograph'], + 'radioautographic': ['autoradiographic', 'radioautographic'], + 'radioautography': ['autoradiography', 'radioautography'], + 'radiohumeral': ['humeroradial', 'radiohumeral'], + 'radiolite': ['editorial', 'radiolite'], + 'radiolucent': ['radiolucent', 'reductional'], + 'radioman': ['adoniram', 'radioman'], + 'radiomicrometer': ['microradiometer', 'radiomicrometer'], + 'radiophone': ['phoronidea', 'radiophone'], + 'radiophony': ['hypodorian', 'radiophony'], + 'radiotelephone': ['radiotelephone', 'teleradiophone'], + 'radiotron': ['ordinator', 'radiotron'], + 'radish': ['ardish', 'radish'], + 'radius': ['darius', 'radius'], + 'radman': ['mandra', 'radman'], + 'radon': ['adorn', 'donar', 'drona', 'radon'], + 'radula': ['adular', 'aludra', 'radula'], + 'rafael': ['aflare', 'rafael'], + 'rafe': ['fare', 'fear', 'frae', 'rafe'], + 'raffee': ['affeer', 'raffee'], + 'raffia': ['affair', 'raffia'], + 'raffle': ['farfel', 'raffle'], + 'rafik': ['fakir', 'fraik', 'kafir', 'rafik'], + 'raft': ['frat', 'raft'], + 'raftage': ['fregata', 'raftage'], + 'rafter': ['frater', 'rafter'], + 'rag': ['gar', 'gra', 'rag'], + 'raga': ['agar', 'agra', 'gara', 'raga'], + 'rage': ['ager', 'agre', 'gare', 'gear', 'rage'], + 'rageless': ['eelgrass', 'gearless', 'rageless'], + 'ragfish': ['garfish', 'ragfish'], + 'ragged': ['dagger', 'gadger', 'ragged'], + 'raggee': ['agrege', 'raggee'], + 'raggety': ['gargety', 'raggety'], + 'raggle': ['gargle', 'gregal', 'lagger', 'raggle'], + 'raggled': ['draggle', 'raggled'], + 'raggy': ['aggry', 'raggy'], + 'ragingly': ['grayling', 'ragingly'], + 'raglanite': ['antiglare', 'raglanite'], + 'raglet': ['raglet', 'tergal'], + 'raglin': ['nargil', 'raglin'], + 'ragman': ['amgarn', 'mangar', 'marang', 'ragman'], + 'ragnar': ['garran', 'ragnar'], + 'ragshag': ['ragshag', 'shagrag'], + 'ragtag': ['ragtag', 'tagrag'], + 'ragtime': ['migrate', 'ragtime'], + 'ragule': ['ragule', 'regula'], + 'raguly': ['glaury', 'raguly'], + 'raia': ['aira', 'aria', 'raia'], + 'raid': ['arid', 'dari', 'raid'], + 'raider': ['arride', 'raider'], + 'raif': ['fair', 'fiar', 'raif'], + 'raiidae': ['ariidae', 'raiidae'], + 'rail': ['aril', 'lair', 'lari', 'liar', 'lira', 'rail', 'rial'], + 'railage': ['lairage', 'railage', 'regalia'], + 'railer': ['railer', 'rerail'], + 'railhead': ['headrail', 'railhead'], + 'railless': ['lairless', 'railless'], + 'railman': ['lairman', 'laminar', 'malarin', 'railman'], + 'raiment': ['minaret', 'raiment', 'tireman'], + 'rain': ['arni', 'iran', 'nair', 'rain', 'rani'], + 'raincoat': ['craniota', 'croatian', 'narcotia', 'raincoat'], + 'rainful': ['rainful', 'unfrail'], + 'rainspout': ['rainspout', 'supinator'], + 'rainy': ['nairy', 'rainy'], + 'rais': ['rais', 'sair', 'sari'], + 'raise': ['aries', 'arise', 'raise', 'serai'], + 'raiseman': ['erasmian', 'raiseman'], + 'raiser': ['raiser', 'sierra'], + 'raisin': ['raisin', 'sirian'], + 'raj': ['jar', 'raj'], + 'raja': ['ajar', 'jara', 'raja'], + 'rajah': ['ajhar', 'rajah'], + 'rajeev': ['evejar', 'rajeev'], + 'rake': ['rake', 'reak'], + 'rakesteel': ['rakesteel', 'rakestele'], + 'rakestele': ['rakesteel', 'rakestele'], + 'rakh': ['hark', 'khar', 'rakh'], + 'raki': ['ikra', 'kari', 'raki'], + 'rakish': ['rakish', 'riksha', 'shikar', 'shikra', 'sikhra'], + 'rakit': ['kitar', 'krait', 'rakit', 'traik'], + 'raku': ['kuar', 'raku', 'rauk'], + 'ralf': ['farl', 'ralf'], + 'ralliance': ['alliancer', 'ralliance'], + 'ralline': ['ralline', 'renilla'], + 'ram': ['arm', 'mar', 'ram'], + 'rama': ['amar', 'amra', 'mara', 'rama'], + 'ramada': ['armada', 'damara', 'ramada'], + 'ramage': ['gemara', 'ramage'], + 'ramaite': ['ametria', 'artemia', 'meratia', 'ramaite'], + 'ramal': ['alarm', 'malar', 'maral', 'marla', 'ramal'], + 'ramanas': ['ramanas', 'sramana'], + 'ramate': ['ramate', 'retama'], + 'ramble': ['ambler', 'blamer', 'lamber', 'marble', 'ramble'], + 'rambler': ['marbler', 'rambler'], + 'rambling': ['marbling', 'rambling'], + 'rambo': ['broma', 'rambo'], + 'rambutan': ['rambutan', 'tamburan'], + 'rame': ['erma', 'mare', 'rame', 'ream'], + 'ramed': ['armed', 'derma', 'dream', 'ramed'], + 'rament': ['manter', 'marten', 'rament'], + 'ramental': ['maternal', 'ramental'], + 'ramequin': ['queriman', 'ramequin'], + 'ramesh': ['masher', 'ramesh', 'shamer'], + 'ramet': ['armet', + 'mater', + 'merat', + 'metra', + 'ramet', + 'tamer', + 'terma', + 'trame', + 'trema'], + 'rami': ['amir', 'irma', 'mari', 'mira', 'rami', 'rima'], + 'ramie': ['aimer', 'maire', 'marie', 'ramie'], + 'ramiferous': ['armiferous', 'ramiferous'], + 'ramigerous': ['armigerous', 'ramigerous'], + 'ramillie': ['milliare', 'ramillie'], + 'ramisection': ['anisometric', + 'creationism', + 'miscreation', + 'ramisection', + 'reactionism'], + 'ramist': ['marist', 'matris', 'ramist'], + 'ramline': ['marline', 'mineral', 'ramline'], + 'rammel': ['lammer', 'rammel'], + 'rammy': ['mymar', 'rammy'], + 'ramon': ['manor', 'moran', 'norma', 'ramon', 'roman'], + 'ramona': ['oarman', 'ramona'], + 'ramose': ['amores', 'ramose', 'sorema'], + 'ramosely': ['marysole', 'ramosely'], + 'ramp': ['pram', 'ramp'], + 'rampant': ['mantrap', 'rampant'], + 'ramped': ['damper', 'ramped'], + 'ramper': ['prearm', 'ramper'], + 'rampike': ['perakim', 'permiak', 'rampike'], + 'ramping': ['gripman', 'prigman', 'ramping'], + 'ramsey': ['ramsey', 'smeary'], + 'ramson': ['ramson', 'ransom'], + 'ramtil': ['mitral', 'ramtil'], + 'ramule': ['mauler', 'merula', 'ramule'], + 'ramulus': ['malurus', 'ramulus'], + 'ramus': ['musar', 'ramus', 'rusma', 'surma'], + 'ramusi': ['misura', 'ramusi'], + 'ran': ['arn', 'nar', 'ran'], + 'rana': ['arna', 'rana'], + 'ranales': ['arsenal', 'ranales'], + 'rance': ['caner', 'crane', 'crena', 'nacre', 'rance'], + 'rancel': ['lancer', 'rancel'], + 'rancer': ['craner', 'rancer'], + 'ranche': ['enarch', 'ranche'], + 'ranchero': ['anchorer', 'ranchero', 'reanchor'], + 'rancho': ['anchor', 'archon', 'charon', 'rancho'], + 'rancid': ['andric', 'cardin', 'rancid'], + 'rand': ['darn', 'nard', 'rand'], + 'randan': ['annard', 'randan'], + 'randem': ['damner', 'manred', 'randem', 'remand'], + 'rander': ['darner', 'darren', 'errand', 'rander', 'redarn'], + 'randia': ['adrian', 'andira', 'andria', 'radian', 'randia'], + 'randing': ['darning', 'randing'], + 'randite': ['antired', 'detrain', 'randite', 'trained'], + 'randle': ['aldern', + 'darnel', + 'enlard', + 'lander', + 'lenard', + 'randle', + 'reland'], + 'random': ['random', 'rodman'], + 'rane': ['arne', 'earn', 'rane'], + 'ranere': ['earner', 'ranere'], + 'rang': ['garn', 'gnar', 'rang'], + 'range': ['anger', 'areng', 'grane', 'range'], + 'ranged': ['danger', 'gander', 'garden', 'ranged'], + 'rangeless': ['largeness', 'rangeless', 'regalness'], + 'ranger': ['garner', 'ranger'], + 'rangey': ['anergy', 'rangey'], + 'ranginess': ['angriness', 'ranginess'], + 'rangle': ['angler', 'arleng', 'garnel', 'largen', 'rangle', 'regnal'], + 'rangy': ['angry', 'rangy'], + 'rani': ['arni', 'iran', 'nair', 'rain', 'rani'], + 'ranid': ['darin', 'dinar', 'drain', 'indra', 'nadir', 'ranid'], + 'ranidae': ['araneid', 'ariadne', 'ranidae'], + 'raniform': ['nariform', 'raniform'], + 'raninae': ['aranein', 'raninae'], + 'ranine': ['narine', 'ranine'], + 'rank': ['knar', 'kran', 'nark', 'rank'], + 'ranked': ['darken', 'kanred', 'ranked'], + 'ranker': ['ranker', 'rerank'], + 'rankish': ['krishna', 'rankish'], + 'rannel': ['lanner', 'rannel'], + 'ranquel': ['quernal', 'ranquel'], + 'ransom': ['ramson', 'ransom'], + 'rant': ['natr', 'rant', 'tarn', 'tran'], + 'rantepole': ['petrolean', 'rantepole'], + 'ranter': ['arrent', 'errant', 'ranter', 'ternar'], + 'rantipole': ['prelation', 'rantipole'], + 'ranula': ['alraun', 'alruna', 'ranula'], + 'rap': ['par', 'rap'], + 'rape': ['aper', 'pare', 'pear', 'rape', 'reap'], + 'rapeful': ['rapeful', 'upflare'], + 'raper': ['parer', 'raper'], + 'raphael': ['phalera', 'raphael'], + 'raphaelic': ['eparchial', 'raphaelic'], + 'raphe': ['hepar', 'phare', 'raphe'], + 'raphia': ['pahari', 'pariah', 'raphia'], + 'raphides': ['diphaser', 'parished', 'raphides', 'sephardi'], + 'raphis': ['parish', 'raphis', 'rhapis'], + 'rapic': ['capri', 'picra', 'rapic'], + 'rapid': ['adrip', 'rapid'], + 'rapidly': ['pyralid', 'rapidly'], + 'rapier': ['pairer', 'rapier', 'repair'], + 'rapine': ['parine', 'rapine'], + 'raping': ['paring', 'raping'], + 'rapparee': ['appearer', 'rapparee', 'reappear'], + 'rappe': ['paper', 'rappe'], + 'rappel': ['lapper', 'rappel'], + 'rappite': ['periapt', 'rappite'], + 'rapt': ['part', 'prat', 'rapt', 'tarp', 'trap'], + 'raptly': ['paltry', 'partly', 'raptly'], + 'raptor': ['parrot', 'raptor'], + 'rapture': ['parture', 'rapture'], + 'rare': ['rare', 'rear'], + 'rarebit': ['arbiter', 'rarebit'], + 'rareripe': ['rareripe', 'repairer'], + 'rarish': ['arrish', 'harris', 'rarish', 'sirrah'], + 'ras': ['ras', 'sar'], + 'rasa': ['rasa', 'sara'], + 'rascacio': ['coracias', 'rascacio'], + 'rascal': ['lascar', 'rascal', 'sacral', 'scalar'], + 'rase': ['arse', 'rase', 'sare', 'sear', 'sera'], + 'rasen': ['anser', 'nares', 'rasen', 'snare'], + 'raser': ['ersar', 'raser', 'serra'], + 'rasher': ['rasher', 'sharer'], + 'rashing': ['garnish', 'rashing'], + 'rashti': ['rashti', 'tarish'], + 'rasion': ['arsino', 'rasion', 'sonrai'], + 'rasp': ['rasp', 'spar'], + 'rasped': ['rasped', 'spader', 'spread'], + 'rasper': ['parser', 'rasper', 'sparer'], + 'rasping': ['aspring', 'rasping', 'sparing'], + 'raspingly': ['raspingly', 'sparingly'], + 'raspingness': ['raspingness', 'sparingness'], + 'raspite': ['piaster', 'piastre', 'raspite', 'spirate', 'traipse'], + 'raspy': ['raspy', 'spary', 'spray'], + 'rasse': ['arses', 'rasse'], + 'raster': ['arrest', 'astrer', 'raster', 'starer'], + 'rastik': ['rastik', 'sarkit', 'straik'], + 'rastle': ['laster', + 'lastre', + 'rastle', + 'relast', + 'resalt', + 'salter', + 'slater', + 'stelar'], + 'rastus': ['rastus', 'tarsus'], + 'rat': ['art', 'rat', 'tar', 'tra'], + 'rata': ['rata', 'taar', 'tara'], + 'ratable': ['alberta', 'latebra', 'ratable'], + 'ratal': ['altar', 'artal', 'ratal', 'talar'], + 'ratanhia': ['ratanhia', 'rhatania'], + 'ratbite': ['biretta', 'brattie', 'ratbite'], + 'ratch': ['chart', 'ratch'], + 'ratchel': ['clethra', 'latcher', 'ratchel', 'relatch', 'talcher', 'trachle'], + 'ratcher': ['charter', 'ratcher'], + 'ratchet': ['chatter', 'ratchet'], + 'ratchety': ['chattery', 'ratchety', 'trachyte'], + 'ratching': ['charting', 'ratching'], + 'rate': ['rate', 'tare', 'tear', 'tera'], + 'rated': ['dater', 'derat', 'detar', 'drate', 'rated', 'trade', 'tread'], + 'ratel': ['alert', 'alter', 'artel', 'later', 'ratel', 'taler', 'telar'], + 'rateless': ['rateless', 'tasseler', 'tearless', 'tesseral'], + 'ratfish': ['ratfish', 'tashrif'], + 'rath': ['hart', 'rath', 'tahr', 'thar', 'trah'], + 'rathe': ['earth', 'hater', 'heart', 'herat', 'rathe'], + 'rathed': ['dearth', 'hatred', 'rathed', 'thread'], + 'rathely': ['earthly', 'heartly', 'lathery', 'rathely'], + 'ratherest': ['ratherest', 'shatterer'], + 'rathest': ['rathest', 'shatter'], + 'rathite': ['hartite', 'rathite'], + 'rathole': ['loather', 'rathole'], + 'raticidal': ['raticidal', 'triadical'], + 'raticide': ['ceratiid', 'raticide'], + 'ratine': ['nerita', 'ratine', 'retain', 'retina', 'tanier'], + 'rating': ['rating', 'tringa'], + 'ratio': ['ariot', 'ratio'], + 'ration': ['aroint', 'ration'], + 'rationable': ['alboranite', 'rationable'], + 'rational': ['notarial', 'rational', 'rotalian'], + 'rationale': ['alienator', 'rationale'], + 'rationalize': ['rationalize', 'realization'], + 'rationally': ['notarially', 'rationally'], + 'rationate': ['notariate', 'rationate'], + 'ratitae': ['arietta', 'ratitae'], + 'ratite': ['attire', 'ratite', 'tertia'], + 'ratitous': ['outstair', 'ratitous'], + 'ratlike': ['artlike', 'ratlike', 'tarlike'], + 'ratline': ['entrail', + 'latiner', + 'latrine', + 'ratline', + 'reliant', + 'retinal', + 'trenail'], + 'rattage': ['garetta', 'rattage', 'regatta'], + 'rattan': ['rattan', 'tantra', 'tartan'], + 'ratteen': ['entreat', 'ratteen', 'tarente', 'ternate', 'tetrane'], + 'ratten': ['attern', 'natter', 'ratten', 'tarten'], + 'ratti': ['ratti', 'titar', 'trait'], + 'rattish': ['athirst', 'rattish', 'tartish'], + 'rattle': ['artlet', 'latter', 'rattle', 'tartle', 'tatler'], + 'rattles': ['rattles', 'slatter', 'starlet', 'startle'], + 'rattlesome': ['rattlesome', 'saltometer'], + 'rattly': ['rattly', 'tartly'], + 'ratton': ['attorn', 'ratton', 'rottan'], + 'rattus': ['astrut', 'rattus', 'stuart'], + 'ratwood': ['ratwood', 'tarwood'], + 'raught': ['raught', 'tughra'], + 'rauk': ['kuar', 'raku', 'rauk'], + 'raul': ['alur', 'laur', 'lura', 'raul', 'ural'], + 'rauli': ['rauli', 'urali', 'urial'], + 'raun': ['raun', 'uran', 'urna'], + 'raunge': ['nauger', 'raunge', 'ungear'], + 'rave': ['aver', 'rave', 'vare', 'vera'], + 'ravel': ['arvel', 'larve', 'laver', 'ravel', 'velar'], + 'ravelin': ['elinvar', 'ravelin', 'reanvil', 'valerin'], + 'ravelly': ['ravelly', 'valeryl'], + 'ravendom': ['overdamn', 'ravendom'], + 'ravenelia': ['ravenelia', 'veneralia'], + 'ravenish': ['enravish', 'ravenish', 'vanisher'], + 'ravi': ['ravi', 'riva', 'vair', 'vari', 'vira'], + 'ravigote': ['ravigote', 'rogative'], + 'ravin': ['invar', 'ravin', 'vanir'], + 'ravine': ['averin', 'ravine'], + 'ravined': ['invader', 'ravined', 'viander'], + 'raving': ['grivna', 'raving'], + 'ravissant': ['ravissant', 'srivatsan'], + 'raw': ['raw', 'war'], + 'rawboned': ['downbear', 'rawboned'], + 'rawish': ['rawish', 'wairsh', 'warish'], + 'rax': ['arx', 'rax'], + 'ray': ['ary', 'ray', 'yar'], + 'raya': ['arya', 'raya'], + 'rayan': ['aryan', 'nayar', 'rayan'], + 'rayed': ['deary', 'deray', 'rayed', 'ready', 'yeard'], + 'raylet': ['lyrate', 'raylet', 'realty', 'telary'], + 'rayonnance': ['annoyancer', 'rayonnance'], + 'raze': ['ezra', 'raze'], + 're': ['er', 're'], + 'rea': ['aer', 'are', 'ear', 'era', 'rea'], + 'reaal': ['areal', 'reaal'], + 'reabandon': ['abandoner', 'reabandon'], + 'reabolish': ['abolisher', 'reabolish'], + 'reabsent': ['absenter', 'reabsent'], + 'reabsorb': ['absorber', 'reabsorb'], + 'reaccession': ['accessioner', 'reaccession'], + 'reaccomplish': ['accomplisher', 'reaccomplish'], + 'reaccord': ['accorder', 'reaccord'], + 'reaccost': ['ectosarc', 'reaccost'], + 'reach': ['acher', 'arche', 'chare', 'chera', 'rache', 'reach'], + 'reachieve': ['echeveria', 'reachieve'], + 'react': ['caret', + 'carte', + 'cater', + 'crate', + 'creat', + 'creta', + 'react', + 'recta', + 'trace'], + 'reactance': ['cancerate', 'reactance'], + 'reaction': ['actioner', 'anerotic', 'ceration', 'creation', 'reaction'], + 'reactional': ['creational', 'crotalinae', 'laceration', 'reactional'], + 'reactionary': ['creationary', 'reactionary'], + 'reactionism': ['anisometric', + 'creationism', + 'miscreation', + 'ramisection', + 'reactionism'], + 'reactionist': ['creationist', 'reactionist'], + 'reactive': ['creative', 'reactive'], + 'reactively': ['creatively', 'reactively'], + 'reactiveness': ['creativeness', 'reactiveness'], + 'reactivity': ['creativity', 'reactivity'], + 'reactor': ['creator', 'reactor'], + 'read': ['ared', 'daer', 'dare', 'dear', 'read'], + 'readapt': ['adapter', 'predata', 'readapt'], + 'readd': ['adder', 'dread', 'readd'], + 'readdress': ['addresser', 'readdress'], + 'reader': ['reader', 'redare', 'reread'], + 'reading': ['degrain', 'deraign', 'deringa', 'gradine', 'grained', 'reading'], + 'readjust': ['adjuster', 'readjust'], + 'readopt': ['adopter', 'protead', 'readopt'], + 'readorn': ['adorner', 'readorn'], + 'ready': ['deary', 'deray', 'rayed', 'ready', 'yeard'], + 'reaffect': ['affecter', 'reaffect'], + 'reaffirm': ['affirmer', 'reaffirm'], + 'reafflict': ['afflicter', 'reafflict'], + 'reagent': ['grantee', 'greaten', 'reagent', 'rentage'], + 'reagin': ['arenig', 'earing', 'gainer', 'reagin', 'regain'], + 'reak': ['rake', 'reak'], + 'real': ['earl', 'eral', 'lear', 'real'], + 'reales': ['alerse', 'leaser', 'reales', 'resale', 'reseal', 'sealer'], + 'realest': ['realest', 'reslate', 'resteal', 'stealer', 'teasler'], + 'realign': ['aligner', 'engrail', 'realign', 'reginal'], + 'realignment': ['engrailment', 'realignment'], + 'realism': ['mislear', 'realism'], + 'realist': ['aletris', 'alister', 'listera', 'realist', 'saltier'], + 'realistic': ['eristical', 'realistic'], + 'reality': ['irately', 'reality'], + 'realive': ['realive', 'valerie'], + 'realization': ['rationalize', 'realization'], + 'reallot': ['reallot', 'rotella', 'tallero'], + 'reallow': ['allower', 'reallow'], + 'reallude': ['laureled', 'reallude'], + 'realmlet': ['realmlet', 'tremella'], + 'realter': ['alterer', 'realter', 'relater'], + 'realtor': ['realtor', 'relator'], + 'realty': ['lyrate', 'raylet', 'realty', 'telary'], + 'ream': ['erma', 'mare', 'rame', 'ream'], + 'reamage': ['megaera', 'reamage'], + 'reamass': ['amasser', 'reamass'], + 'reamend': ['amender', 'meander', 'reamend', 'reedman'], + 'reamer': ['marree', 'reamer'], + 'reamuse': ['measure', 'reamuse'], + 'reamy': ['mayer', 'reamy'], + 'reanchor': ['anchorer', 'ranchero', 'reanchor'], + 'reanneal': ['annealer', 'lernaean', 'reanneal'], + 'reannex': ['annexer', 'reannex'], + 'reannoy': ['annoyer', 'reannoy'], + 'reanoint': ['anointer', 'inornate', 'nonirate', 'reanoint'], + 'reanswer': ['answerer', 'reanswer'], + 'reanvil': ['elinvar', 'ravelin', 'reanvil', 'valerin'], + 'reap': ['aper', 'pare', 'pear', 'rape', 'reap'], + 'reapdole': ['leoparde', 'reapdole'], + 'reappeal': ['appealer', 'reappeal'], + 'reappear': ['appearer', 'rapparee', 'reappear'], + 'reapplaud': ['applauder', 'reapplaud'], + 'reappoint': ['appointer', 'reappoint'], + 'reapportion': ['apportioner', 'reapportion'], + 'reapprehend': ['apprehender', 'reapprehend'], + 'reapproach': ['approacher', 'reapproach'], + 'rear': ['rare', 'rear'], + 'reargue': ['augerer', 'reargue'], + 'reargument': ['garmenture', 'reargument'], + 'rearise': ['rearise', 'reraise'], + 'rearm': ['armer', 'rearm'], + 'rearray': ['arrayer', 'rearray'], + 'rearrest': ['arrester', 'rearrest'], + 'reascend': ['ascender', 'reascend'], + 'reascent': ['reascent', 'sarcenet'], + 'reascertain': ['ascertainer', 'reascertain', 'secretarian'], + 'reask': ['asker', 'reask', 'saker', 'sekar'], + 'reason': ['arseno', 'reason'], + 'reassail': ['assailer', 'reassail'], + 'reassault': ['assaulter', 'reassault', 'saleratus'], + 'reassay': ['assayer', 'reassay'], + 'reassent': ['assenter', 'reassent', 'sarsenet'], + 'reassert': ['asserter', 'reassert'], + 'reassign': ['assigner', 'reassign'], + 'reassist': ['assister', 'reassist'], + 'reassort': ['assertor', 'assorter', 'oratress', 'reassort'], + 'reastonish': ['astonisher', 'reastonish', 'treasonish'], + 'reasty': ['atresy', 'estray', 'reasty', 'stayer'], + 'reasy': ['reasy', 'resay', 'sayer', 'seary'], + 'reattach': ['attacher', 'reattach'], + 'reattack': ['attacker', 'reattack'], + 'reattain': ['attainer', 'reattain', 'tertiana'], + 'reattempt': ['attempter', 'reattempt'], + 'reattend': ['attender', 'nattered', 'reattend'], + 'reattest': ['attester', 'reattest'], + 'reattract': ['attracter', 'reattract'], + 'reattraction': ['reattraction', 'retractation'], + 'reatus': ['auster', 'reatus'], + 'reavail': ['reavail', 'valeria'], + 'reave': ['eaver', 'reave'], + 'reavoid': ['avodire', 'avoider', 'reavoid'], + 'reavouch': ['avoucher', 'reavouch'], + 'reavow': ['avower', 'reavow'], + 'reawait': ['awaiter', 'reawait'], + 'reawaken': ['awakener', 'reawaken'], + 'reaward': ['awarder', 'reaward'], + 'reb': ['ber', 'reb'], + 'rebab': ['barbe', 'bebar', 'breba', 'rebab'], + 'reback': ['backer', 'reback'], + 'rebag': ['bagre', 'barge', 'begar', 'rebag'], + 'rebait': ['baiter', 'barite', 'rebait', 'terbia'], + 'rebake': ['beaker', 'berake', 'rebake'], + 'reballast': ['ballaster', 'reballast'], + 'reballot': ['balloter', 'reballot'], + 'reban': ['abner', 'arneb', 'reban'], + 'rebanish': ['banisher', 'rebanish'], + 'rebar': ['barer', 'rebar'], + 'rebargain': ['bargainer', 'rebargain'], + 'rebasis': ['brassie', 'rebasis'], + 'rebate': ['beater', 'berate', 'betear', 'rebate', 'rebeat'], + 'rebater': ['rebater', 'terebra'], + 'rebathe': ['breathe', 'rebathe'], + 'rebato': ['boater', 'borate', 'rebato'], + 'rebawl': ['bawler', 'brelaw', 'rebawl', 'warble'], + 'rebear': ['bearer', 'rebear'], + 'rebeat': ['beater', 'berate', 'betear', 'rebate', 'rebeat'], + 'rebeck': ['becker', 'rebeck'], + 'rebed': ['brede', 'breed', 'rebed'], + 'rebeg': ['gerbe', 'grebe', 'rebeg'], + 'rebeggar': ['beggarer', 'rebeggar'], + 'rebegin': ['bigener', 'rebegin'], + 'rebehold': ['beholder', 'rebehold'], + 'rebellow': ['bellower', 'rebellow'], + 'rebelly': ['bellyer', 'rebelly'], + 'rebelong': ['belonger', 'rebelong'], + 'rebend': ['bender', 'berend', 'rebend'], + 'rebenefit': ['benefiter', 'rebenefit'], + 'rebeset': ['besteer', 'rebeset'], + 'rebestow': ['bestower', 'rebestow'], + 'rebetray': ['betrayer', 'eatberry', 'rebetray', 'teaberry'], + 'rebewail': ['bewailer', 'rebewail'], + 'rebia': ['barie', 'beira', 'erbia', 'rebia'], + 'rebias': ['braise', 'rabies', 'rebias'], + 'rebid': ['bider', 'bredi', 'bride', 'rebid'], + 'rebill': ['biller', 'rebill'], + 'rebillet': ['billeter', 'rebillet'], + 'rebind': ['binder', 'inbred', 'rebind'], + 'rebirth': ['brither', 'rebirth'], + 'rebite': ['bertie', 'betire', 'rebite'], + 'reblade': ['bleared', 'reblade'], + 'reblast': ['blaster', 'reblast', 'stabler'], + 'rebleach': ['bleacher', 'rebleach'], + 'reblend': ['blender', 'reblend'], + 'rebless': ['blesser', 'rebless'], + 'reblock': ['blocker', 'brockle', 'reblock'], + 'rebloom': ['bloomer', 'rebloom'], + 'reblot': ['bolter', 'orblet', 'reblot', 'rebolt'], + 'reblow': ['blower', 'bowler', 'reblow', 'worble'], + 'reblue': ['brulee', 'burele', 'reblue'], + 'rebluff': ['bluffer', 'rebluff'], + 'reblunder': ['blunderer', 'reblunder'], + 'reboant': ['baronet', 'reboant'], + 'reboantic': ['bicornate', 'carbonite', 'reboantic'], + 'reboard': ['arbored', 'boarder', 'reboard'], + 'reboast': ['barotse', 'boaster', 'reboast', 'sorbate'], + 'reboil': ['boiler', 'reboil'], + 'rebold': ['belord', 'bordel', 'rebold'], + 'rebolt': ['bolter', 'orblet', 'reblot', 'rebolt'], + 'rebone': ['boreen', 'enrobe', 'neebor', 'rebone'], + 'rebook': ['booker', 'brooke', 'rebook'], + 'rebop': ['probe', 'rebop'], + 'rebore': ['rebore', 'rerobe'], + 'reborrow': ['borrower', 'reborrow'], + 'rebound': ['beround', 'bounder', 'rebound', 'unbored', 'unorbed', 'unrobed'], + 'rebounder': ['rebounder', 'underrobe'], + 'rebox': ['boxer', 'rebox'], + 'rebrace': ['cerebra', 'rebrace'], + 'rebraid': ['braider', 'rebraid'], + 'rebranch': ['brancher', 'rebranch'], + 'rebrand': ['bernard', 'brander', 'rebrand'], + 'rebrandish': ['brandisher', 'rebrandish'], + 'rebreed': ['breeder', 'rebreed'], + 'rebrew': ['brewer', 'rebrew'], + 'rebribe': ['berberi', 'rebribe'], + 'rebring': ['bringer', 'rebring'], + 'rebroach': ['broacher', 'rebroach'], + 'rebroadcast': ['broadcaster', 'rebroadcast'], + 'rebrown': ['browner', 'rebrown'], + 'rebrush': ['brusher', 'rebrush'], + 'rebud': ['bedur', 'rebud', 'redub'], + 'rebudget': ['budgeter', 'rebudget'], + 'rebuff': ['buffer', 'rebuff'], + 'rebuffet': ['buffeter', 'rebuffet'], + 'rebuild': ['builder', 'rebuild'], + 'rebulk': ['bulker', 'rebulk'], + 'rebunch': ['buncher', 'rebunch'], + 'rebundle': ['blendure', 'rebundle'], + 'reburden': ['burdener', 'reburden'], + 'reburn': ['burner', 'reburn'], + 'reburnish': ['burnisher', 'reburnish'], + 'reburst': ['burster', 'reburst'], + 'rebus': ['burse', 'rebus', 'suber'], + 'rebush': ['busher', 'rebush'], + 'rebut': ['brute', 'buret', 'rebut', 'tuber'], + 'rebute': ['rebute', 'retube'], + 'rebuttal': ['burletta', 'rebuttal'], + 'rebutton': ['buttoner', 'rebutton'], + 'rebuy': ['buyer', 'rebuy'], + 'recalk': ['calker', 'lacker', 'rackle', 'recalk', 'reckla'], + 'recall': ['caller', 'cellar', 'recall'], + 'recampaign': ['campaigner', 'recampaign'], + 'recancel': ['canceler', 'clarence', 'recancel'], + 'recant': ['canter', + 'creant', + 'cretan', + 'nectar', + 'recant', + 'tanrec', + 'trance'], + 'recantation': ['recantation', 'triacontane'], + 'recanter': ['canterer', 'recanter', 'recreant', 'terrance'], + 'recap': ['caper', 'crape', 'pacer', 'perca', 'recap'], + 'recaption': ['preaction', 'precation', 'recaption'], + 'recarpet': ['pretrace', 'recarpet'], + 'recart': ['arrect', 'carter', 'crater', 'recart', 'tracer'], + 'recase': ['cesare', 'crease', 'recase', 'searce'], + 'recash': ['arches', 'chaser', 'eschar', 'recash', 'search'], + 'recast': ['carest', 'caster', 'recast'], + 'recatch': ['catcher', 'recatch'], + 'recede': ['decree', 'recede'], + 'recedent': ['centered', 'decenter', 'decentre', 'recedent'], + 'receder': ['decreer', 'receder'], + 'receipt': ['ereptic', 'precite', 'receipt'], + 'receiptor': ['procerite', 'receiptor'], + 'receivables': ['receivables', 'serviceable'], + 'received': ['deceiver', 'received'], + 'recement': ['cementer', 'cerement', 'recement'], + 'recension': ['ninescore', 'recension'], + 'recensionist': ['intercession', 'recensionist'], + 'recent': ['center', 'recent', 'tenrec'], + 'recenter': ['centerer', 'recenter', 'recentre', 'terrence'], + 'recentre': ['centerer', 'recenter', 'recentre', 'terrence'], + 'reception': ['prenotice', 'reception'], + 'receptoral': ['praelector', 'receptoral'], + 'recess': ['cesser', 'recess'], + 'rechain': ['chainer', 'enchair', 'rechain'], + 'rechal': ['rachel', 'rechal'], + 'rechamber': ['chamberer', 'rechamber'], + 'rechange': ['encharge', 'rechange'], + 'rechant': ['chanter', 'rechant'], + 'rechar': ['archer', 'charer', 'rechar'], + 'recharter': ['charterer', 'recharter'], + 'rechase': ['archsee', 'rechase'], + 'rechaser': ['rechaser', 'research', 'searcher'], + 'rechasten': ['chastener', 'rechasten'], + 'rechaw': ['chawer', 'rechaw'], + 'recheat': ['cheater', 'hectare', 'recheat', 'reteach', 'teacher'], + 'recheck': ['checker', 'recheck'], + 'recheer': ['cheerer', 'recheer'], + 'rechew': ['chewer', 'rechew'], + 'rechip': ['cipher', 'rechip'], + 'rechisel': ['chiseler', 'rechisel'], + 'rechristen': ['christener', 'rechristen'], + 'rechuck': ['chucker', 'rechuck'], + 'recidivous': ['recidivous', 'veridicous'], + 'recipe': ['piecer', 'pierce', 'recipe'], + 'recipiend': ['perdicine', 'recipiend'], + 'recipient': ['princeite', 'recipient'], + 'reciprocate': ['carpocerite', 'reciprocate'], + 'recirculate': ['clericature', 'recirculate'], + 'recision': ['recision', 'soricine'], + 'recital': ['article', 'recital'], + 'recitativo': ['recitativo', 'victoriate'], + 'recite': ['cerite', 'certie', 'recite', 'tierce'], + 'recitement': ['centimeter', 'recitement', 'remittence'], + 'reckla': ['calker', 'lacker', 'rackle', 'recalk', 'reckla'], + 'reckless': ['clerkess', 'reckless'], + 'reckling': ['clerking', 'reckling'], + 'reckon': ['conker', 'reckon'], + 'reclaim': ['claimer', 'miracle', 'reclaim'], + 'reclaimer': ['calmierer', 'reclaimer'], + 'reclama': ['cameral', 'caramel', 'carmela', 'ceramal', 'reclama'], + 'reclang': ['cangler', 'glancer', 'reclang'], + 'reclasp': ['clasper', 'reclasp', 'scalper'], + 'reclass': ['carless', 'classer', 'reclass'], + 'reclean': ['cleaner', 'reclean'], + 'reclear': ['clearer', 'reclear'], + 'reclimb': ['climber', 'reclimb'], + 'reclinate': ['intercale', 'interlace', 'lacertine', 'reclinate'], + 'reclinated': ['credential', 'interlaced', 'reclinated'], + 'recluse': ['luceres', 'recluse'], + 'recluseness': ['censureless', 'recluseness'], + 'reclusion': ['cornelius', 'inclosure', 'reclusion'], + 'reclusive': ['reclusive', 'versicule'], + 'recoach': ['caroche', 'coacher', 'recoach'], + 'recoal': ['carole', 'coaler', 'coelar', 'oracle', 'recoal'], + 'recoast': ['coaster', 'recoast'], + 'recoat': ['coater', 'recoat'], + 'recock': ['cocker', 'recock'], + 'recoil': ['coiler', 'recoil'], + 'recoilment': ['clinometer', 'recoilment'], + 'recoin': ['cerion', 'coiner', 'neroic', 'orcein', 'recoin'], + 'recoinage': ['aerogenic', 'recoinage'], + 'recollate': ['electoral', 'recollate'], + 'recollation': ['collationer', 'recollation'], + 'recollection': ['collectioner', 'recollection'], + 'recollet': ['colleter', 'coteller', 'coterell', 'recollet'], + 'recolor': ['colorer', 'recolor'], + 'recomb': ['comber', 'recomb'], + 'recomfort': ['comforter', 'recomfort'], + 'recommand': ['commander', 'recommand'], + 'recommend': ['commender', 'recommend'], + 'recommission': ['commissioner', 'recommission'], + 'recompact': ['compacter', 'recompact'], + 'recompass': ['compasser', 'recompass'], + 'recompetition': ['competitioner', 'recompetition'], + 'recomplain': ['complainer', 'procnemial', 'recomplain'], + 'recompound': ['compounder', 'recompound'], + 'recomprehend': ['comprehender', 'recomprehend'], + 'recon': ['coner', 'crone', 'recon'], + 'reconceal': ['concealer', 'reconceal'], + 'reconcert': ['concreter', 'reconcert'], + 'reconcession': ['concessioner', 'reconcession'], + 'reconcoct': ['concocter', 'reconcoct'], + 'recondemn': ['condemner', 'recondemn'], + 'recondensation': ['nondesecration', 'recondensation'], + 'recondition': ['conditioner', 'recondition'], + 'reconfer': ['confrere', 'enforcer', 'reconfer'], + 'reconfess': ['confesser', 'reconfess'], + 'reconfirm': ['confirmer', 'reconfirm'], + 'reconform': ['conformer', 'reconform'], + 'reconfound': ['confounder', 'reconfound'], + 'reconfront': ['confronter', 'reconfront'], + 'recongeal': ['congealer', 'recongeal'], + 'reconjoin': ['conjoiner', 'reconjoin'], + 'reconnect': ['concenter', 'reconnect'], + 'reconnoiter': ['reconnoiter', 'reconnoitre'], + 'reconnoitre': ['reconnoiter', 'reconnoitre'], + 'reconsent': ['consenter', 'nonsecret', 'reconsent'], + 'reconsider': ['considerer', 'reconsider'], + 'reconsign': ['consigner', 'reconsign'], + 'reconstitution': ['constitutioner', 'reconstitution'], + 'reconstruct': ['constructer', 'reconstruct'], + 'reconsult': ['consulter', 'reconsult'], + 'recontend': ['contender', 'recontend'], + 'recontest': ['contester', 'recontest'], + 'recontinue': ['recontinue', 'unctioneer'], + 'recontract': ['contracter', 'correctant', 'recontract'], + 'reconvention': ['conventioner', 'reconvention'], + 'reconvert': ['converter', 'reconvert'], + 'reconvey': ['conveyer', 'reconvey'], + 'recook': ['cooker', 'recook'], + 'recool': ['cooler', 'recool'], + 'recopper': ['copperer', 'recopper'], + 'recopyright': ['copyrighter', 'recopyright'], + 'record': ['corder', 'record'], + 'recordation': ['corrodentia', 'recordation'], + 'recork': ['corker', 'recork', 'rocker'], + 'recorrection': ['correctioner', 'recorrection'], + 'recorrupt': ['corrupter', 'recorrupt'], + 'recounsel': ['enclosure', 'recounsel'], + 'recount': ['cornute', 'counter', 'recount', 'trounce'], + 'recountal': ['nucleator', 'recountal'], + 'recoup': ['couper', 'croupe', 'poucer', 'recoup'], + 'recourse': ['recourse', 'resource'], + 'recover': ['coverer', 'recover'], + 'recramp': ['cramper', 'recramp'], + 'recrank': ['cranker', 'recrank'], + 'recrate': ['caterer', 'recrate', 'retrace', 'terrace'], + 'recreant': ['canterer', 'recanter', 'recreant', 'terrance'], + 'recredit': ['cedriret', 'directer', 'recredit', 'redirect'], + 'recrew': ['crewer', 'recrew'], + 'recrimination': ['intermorainic', 'recrimination'], + 'recroon': ['coroner', 'crooner', 'recroon'], + 'recross': ['crosser', 'recross'], + 'recrowd': ['crowder', 'recrowd'], + 'recrown': ['crowner', 'recrown'], + 'recrudency': ['decurrency', 'recrudency'], + 'recruital': ['curtailer', 'recruital', 'reticular'], + 'recrush': ['crusher', 'recrush'], + 'recta': ['caret', + 'carte', + 'cater', + 'crate', + 'creat', + 'creta', + 'react', + 'recta', + 'trace'], + 'rectal': ['carlet', 'cartel', 'claret', 'rectal', 'talcer'], + 'rectalgia': ['cartilage', 'rectalgia'], + 'recti': ['citer', 'recti', 'ticer', 'trice'], + 'rectifiable': ['certifiable', 'rectifiable'], + 'rectification': ['certification', 'cretification', 'rectification'], + 'rectificative': ['certificative', 'rectificative'], + 'rectificator': ['certificator', 'rectificator'], + 'rectificatory': ['certificatory', 'rectificatory'], + 'rectified': ['certified', 'rectified'], + 'rectifier': ['certifier', 'rectifier'], + 'rectify': ['certify', 'cretify', 'rectify'], + 'rection': ['cerotin', 'cointer', 'cotrine', 'cretion', 'noticer', 'rection'], + 'rectitude': ['certitude', 'rectitude'], + 'rectoress': ['crosstree', 'rectoress'], + 'rectorship': ['cristopher', 'rectorship'], + 'rectotome': ['octometer', 'rectotome', 'tocometer'], + 'rectovesical': ['rectovesical', 'vesicorectal'], + 'recur': ['curer', 'recur'], + 'recurl': ['curler', 'recurl'], + 'recurse': ['recurse', 'rescuer', 'securer'], + 'recurtain': ['recurtain', 'unerratic'], + 'recurvation': ['countervair', 'overcurtain', 'recurvation'], + 'recurvous': ['recurvous', 'verrucous'], + 'recusance': ['recusance', 'securance'], + 'recusant': ['etruscan', 'recusant'], + 'recusation': ['nectarious', 'recusation'], + 'recusator': ['craterous', 'recusator'], + 'recuse': ['cereus', 'ceruse', 'recuse', 'rescue', 'secure'], + 'recut': ['cruet', 'eruct', 'recut', 'truce'], + 'red': ['erd', 'red'], + 'redact': ['cedrat', 'decart', 'redact'], + 'redaction': ['citronade', 'endaortic', 'redaction'], + 'redactional': ['declaration', 'redactional'], + 'redamage': ['dreamage', 'redamage'], + 'redan': ['andre', 'arend', 'daren', 'redan'], + 'redare': ['reader', 'redare', 'reread'], + 'redarken': ['darkener', 'redarken'], + 'redarn': ['darner', 'darren', 'errand', 'rander', 'redarn'], + 'redart': ['darter', + 'dartre', + 'redart', + 'retard', + 'retrad', + 'tarred', + 'trader'], + 'redate': ['derate', 'redate'], + 'redaub': ['dauber', 'redaub'], + 'redawn': ['andrew', 'redawn', 'wander', 'warden'], + 'redbait': ['redbait', 'tribade'], + 'redbud': ['budder', 'redbud'], + 'redcoat': ['cordate', 'decator', 'redcoat'], + 'redden': ['nedder', 'redden'], + 'reddingite': ['digredient', 'reddingite'], + 'rede': ['deer', 'dere', 'dree', 'rede', 'reed'], + 'redeal': ['dealer', 'leader', 'redeal', 'relade', 'relead'], + 'redeck': ['decker', 'redeck'], + 'redeed': ['redeed', 'reeded'], + 'redeem': ['deemer', 'meered', 'redeem', 'remede'], + 'redefault': ['defaulter', 'redefault'], + 'redefeat': ['defeater', 'federate', 'redefeat'], + 'redefine': ['needfire', 'redefine'], + 'redeflect': ['redeflect', 'reflected'], + 'redelay': ['delayer', 'layered', 'redelay'], + 'redeliver': ['deliverer', 'redeliver'], + 'redemand': ['demander', 'redemand'], + 'redemolish': ['demolisher', 'redemolish'], + 'redeny': ['redeny', 'yender'], + 'redepend': ['depender', 'redepend'], + 'redeprive': ['prederive', 'redeprive'], + 'rederivation': ['rederivation', 'veratroidine'], + 'redescend': ['descender', 'redescend'], + 'redescription': ['prediscretion', 'redescription'], + 'redesign': ['designer', 'redesign', 'resigned'], + 'redesman': ['redesman', 'seamrend'], + 'redetect': ['detecter', 'redetect'], + 'redevelop': ['developer', 'redevelop'], + 'redfin': ['finder', 'friend', 'redfin', 'refind'], + 'redhoop': ['redhoop', 'rhodope'], + 'redia': ['aider', 'deair', 'irade', 'redia'], + 'redient': ['nitered', 'redient', 'teinder'], + 'redig': ['dirge', 'gride', 'redig', 'ridge'], + 'redigest': ['digester', 'redigest'], + 'rediminish': ['diminisher', 'rediminish'], + 'redintegrator': ['redintegrator', 'retrogradient'], + 'redip': ['pride', 'pried', 'redip'], + 'redirect': ['cedriret', 'directer', 'recredit', 'redirect'], + 'redisable': ['desirable', 'redisable'], + 'redisappear': ['disappearer', 'redisappear'], + 'rediscount': ['discounter', 'rediscount'], + 'rediscover': ['discoverer', 'rediscover'], + 'rediscuss': ['discusser', 'rediscuss'], + 'redispatch': ['dispatcher', 'redispatch'], + 'redisplay': ['displayer', 'redisplay'], + 'redispute': ['disrepute', 'redispute'], + 'redistend': ['dendrites', 'distender', 'redistend'], + 'redistill': ['distiller', 'redistill'], + 'redistinguish': ['distinguisher', 'redistinguish'], + 'redistrain': ['distrainer', 'redistrain'], + 'redisturb': ['disturber', 'redisturb'], + 'redive': ['derive', 'redive'], + 'redivert': ['diverter', 'redivert', 'verditer'], + 'redleg': ['gelder', 'ledger', 'redleg'], + 'redlegs': ['redlegs', 'sledger'], + 'redo': ['doer', 'redo', 'rode', 'roed'], + 'redock': ['corked', 'docker', 'redock'], + 'redolent': ['redolent', 'rondelet'], + 'redoom': ['doomer', 'mooder', 'redoom', 'roomed'], + 'redoubling': ['bouldering', 'redoubling'], + 'redoubt': ['doubter', 'obtrude', 'outbred', 'redoubt'], + 'redound': ['redound', 'rounded', 'underdo'], + 'redowa': ['redowa', 'woader'], + 'redraft': ['drafter', 'redraft'], + 'redrag': ['darger', 'gerard', 'grader', 'redrag', 'regard'], + 'redraw': ['drawer', 'redraw', 'reward', 'warder'], + 'redrawer': ['redrawer', 'rewarder', 'warderer'], + 'redream': ['dreamer', 'redream'], + 'redress': ['dresser', 'redress'], + 'redrill': ['driller', 'redrill'], + 'redrive': ['deriver', 'redrive', 'rivered'], + 'redry': ['derry', 'redry', 'ryder'], + 'redtail': ['dilater', 'lardite', 'redtail'], + 'redtop': ['deport', 'ported', 'redtop'], + 'redub': ['bedur', 'rebud', 'redub'], + 'reductant': ['reductant', 'traducent', 'truncated'], + 'reduction': ['introduce', 'reduction'], + 'reductional': ['radiolucent', 'reductional'], + 'redue': ['redue', 'urdee'], + 'redunca': ['durance', 'redunca', 'unraced'], + 'redwithe': ['redwithe', 'withered'], + 'redye': ['redye', 'reedy'], + 'ree': ['eer', 'ere', 'ree'], + 'reechy': ['cheery', 'reechy'], + 'reed': ['deer', 'dere', 'dree', 'rede', 'reed'], + 'reeded': ['redeed', 'reeded'], + 'reeden': ['endere', 'needer', 'reeden'], + 'reedily': ['reedily', 'reyield', 'yielder'], + 'reeding': ['energid', 'reeding'], + 'reedling': ['engirdle', 'reedling'], + 'reedman': ['amender', 'meander', 'reamend', 'reedman'], + 'reedwork': ['reedwork', 'reworked'], + 'reedy': ['redye', 'reedy'], + 'reef': ['feer', 'free', 'reef'], + 'reefing': ['feering', 'feigner', 'freeing', 'reefing', 'refeign'], + 'reek': ['eker', 'reek'], + 'reel': ['leer', 'reel'], + 'reeler': ['reeler', 'rereel'], + 'reelingly': ['leeringly', 'reelingly'], + 'reem': ['mere', 'reem'], + 'reeming': ['reeming', 'regimen'], + 'reen': ['erne', 'neer', 'reen'], + 'reenge': ['neeger', 'reenge', 'renege'], + 'rees': ['erse', 'rees', 'seer', 'sere'], + 'reese': ['esere', 'reese', 'resee'], + 'reesk': ['esker', 'keres', 'reesk', 'seker', 'skeer', 'skere'], + 'reest': ['ester', + 'estre', + 'reest', + 'reset', + 'steer', + 'stere', + 'stree', + 'terse', + 'tsere'], + 'reester': ['reester', 'steerer'], + 'reestle': ['reestle', 'resteel', 'steeler'], + 'reesty': ['reesty', 'yester'], + 'reet': ['reet', 'teer', 'tree'], + 'reetam': ['reetam', 'retame', 'teamer'], + 'reeveland': ['landreeve', 'reeveland'], + 'refall': ['faller', 'refall'], + 'refashion': ['fashioner', 'refashion'], + 'refasten': ['fastener', 'fenestra', 'refasten'], + 'refavor': ['favorer', 'overfar', 'refavor'], + 'refeed': ['feeder', 'refeed'], + 'refeel': ['feeler', 'refeel', 'reflee'], + 'refeign': ['feering', 'feigner', 'freeing', 'reefing', 'refeign'], + 'refel': ['fleer', 'refel'], + 'refer': ['freer', 'refer'], + 'referment': ['fermenter', 'referment'], + 'refetch': ['fetcher', 'refetch'], + 'refight': ['fighter', 'freight', 'refight'], + 'refill': ['filler', 'refill'], + 'refilter': ['filterer', 'refilter'], + 'refinable': ['inferable', 'refinable'], + 'refind': ['finder', 'friend', 'redfin', 'refind'], + 'refine': ['ferine', 'refine'], + 'refined': ['definer', 'refined'], + 'refiner': ['refiner', 'reinfer'], + 'refinger': ['fingerer', 'refinger'], + 'refining': ['infringe', 'refining'], + 'refinish': ['finisher', 'refinish'], + 'refit': ['freit', 'refit'], + 'refix': ['fixer', 'refix'], + 'reflash': ['flasher', 'reflash'], + 'reflected': ['redeflect', 'reflected'], + 'reflee': ['feeler', 'refeel', 'reflee'], + 'refling': ['ferling', 'flinger', 'refling'], + 'refloat': ['floater', 'florate', 'refloat'], + 'reflog': ['golfer', 'reflog'], + 'reflood': ['flooder', 'reflood'], + 'refloor': ['floorer', 'refloor'], + 'reflourish': ['flourisher', 'reflourish'], + 'reflow': ['flower', 'fowler', 'reflow', 'wolfer'], + 'reflower': ['flowerer', 'reflower'], + 'reflush': ['flusher', 'reflush'], + 'reflux': ['fluxer', 'reflux'], + 'refluxed': ['flexured', 'refluxed'], + 'refly': ['ferly', 'flyer', 'refly'], + 'refocus': ['focuser', 'refocus'], + 'refold': ['folder', 'refold'], + 'refoment': ['fomenter', 'refoment'], + 'refoot': ['footer', 'refoot'], + 'reforecast': ['forecaster', 'reforecast'], + 'reforest': ['forester', 'fosterer', 'reforest'], + 'reforfeit': ['forfeiter', 'reforfeit'], + 'reform': ['former', 'reform'], + 'reformado': ['doorframe', 'reformado'], + 'reformed': ['deformer', 'reformed'], + 'reformism': ['misreform', 'reformism'], + 'reformist': ['reformist', 'restiform'], + 'reforward': ['forwarder', 'reforward'], + 'refound': ['founder', 'refound'], + 'refoundation': ['foundationer', 'refoundation'], + 'refreshen': ['freshener', 'refreshen'], + 'refrighten': ['frightener', 'refrighten'], + 'refront': ['fronter', 'refront'], + 'reft': ['fret', 'reft', 'tref'], + 'refuel': ['ferule', 'fueler', 'refuel'], + 'refund': ['funder', 'refund'], + 'refurbish': ['furbisher', 'refurbish'], + 'refurl': ['furler', 'refurl'], + 'refurnish': ['furnisher', 'refurnish'], + 'refusingly': ['refusingly', 'syringeful'], + 'refutal': ['faulter', 'refutal', 'tearful'], + 'refute': ['fuerte', 'refute'], + 'reg': ['erg', 'ger', 'reg'], + 'regain': ['arenig', 'earing', 'gainer', 'reagin', 'regain'], + 'regal': ['argel', 'ergal', 'garle', 'glare', 'lager', 'large', 'regal'], + 'regalia': ['lairage', 'railage', 'regalia'], + 'regalian': ['algerian', 'geranial', 'regalian'], + 'regalist': ['glaister', 'regalist'], + 'regallop': ['galloper', 'regallop'], + 'regally': ['allergy', 'gallery', 'largely', 'regally'], + 'regalness': ['largeness', 'rangeless', 'regalness'], + 'regard': ['darger', 'gerard', 'grader', 'redrag', 'regard'], + 'regarnish': ['garnisher', 'regarnish'], + 'regather': ['gatherer', 'regather'], + 'regatta': ['garetta', 'rattage', 'regatta'], + 'regelate': ['eglatere', 'regelate', 'relegate'], + 'regelation': ['regelation', 'relegation'], + 'regenesis': ['energesis', 'regenesis'], + 'regent': ['gerent', 'regent'], + 'reges': ['reges', 'serge'], + 'reget': ['egret', 'greet', 'reget'], + 'regga': ['agger', 'gager', 'regga'], + 'reggie': ['greige', 'reggie'], + 'regia': ['geira', 'regia'], + 'regild': ['gilder', 'girdle', 'glider', 'regild', 'ridgel'], + 'regill': ['giller', 'grille', 'regill'], + 'regimen': ['reeming', 'regimen'], + 'regimenal': ['margeline', 'regimenal'], + 'regin': ['grein', 'inger', 'nigre', 'regin', 'reign', 'ringe'], + 'reginal': ['aligner', 'engrail', 'realign', 'reginal'], + 'reginald': ['dragline', 'reginald', 'ringlead'], + 'region': ['ignore', 'region'], + 'regional': ['geraniol', 'regional'], + 'registered': ['deregister', 'registered'], + 'registerer': ['registerer', 'reregister'], + 'regive': ['grieve', 'regive'], + 'regladden': ['gladdener', 'glandered', 'regladden'], + 'reglair': ['grailer', 'reglair'], + 'regle': ['leger', 'regle'], + 'reglet': ['gretel', 'reglet'], + 'regloss': ['glosser', 'regloss'], + 'reglove': ['overleg', 'reglove'], + 'reglow': ['glower', 'reglow'], + 'regma': ['grame', 'marge', 'regma'], + 'regnal': ['angler', 'arleng', 'garnel', 'largen', 'rangle', 'regnal'], + 'regraft': ['grafter', 'regraft'], + 'regrant': ['granter', 'regrant'], + 'regrasp': ['grasper', 'regrasp', 'sparger'], + 'regrass': ['grasser', 'regrass'], + 'regrate': ['greater', 'regrate', 'terrage'], + 'regrating': ['gartering', 'regrating'], + 'regrator': ['garroter', 'regrator'], + 'regreen': ['greener', 'regreen', 'reneger'], + 'regreet': ['greeter', 'regreet'], + 'regrind': ['grinder', 'regrind'], + 'regrinder': ['derringer', 'regrinder'], + 'regrip': ['griper', 'regrip'], + 'regroup': ['grouper', 'regroup'], + 'regrow': ['grower', 'regrow'], + 'reguard': ['guarder', 'reguard'], + 'regula': ['ragule', 'regula'], + 'regulation': ['regulation', 'urogenital'], + 'reguli': ['ligure', 'reguli'], + 'regur': ['regur', 'urger'], + 'regush': ['gusher', 'regush'], + 'reh': ['her', 'reh', 'rhe'], + 'rehale': ['healer', 'rehale', 'reheal'], + 'rehallow': ['hallower', 'rehallow'], + 'rehammer': ['hammerer', 'rehammer'], + 'rehang': ['hanger', 'rehang'], + 'reharden': ['hardener', 'reharden'], + 'reharm': ['harmer', 'reharm'], + 'reharness': ['harnesser', 'reharness'], + 'reharrow': ['harrower', 'reharrow'], + 'reharvest': ['harvester', 'reharvest'], + 'rehash': ['hasher', 'rehash'], + 'rehaul': ['hauler', 'rehaul'], + 'rehazard': ['hazarder', 'rehazard'], + 'rehead': ['adhere', 'header', 'hedera', 'rehead'], + 'reheal': ['healer', 'rehale', 'reheal'], + 'reheap': ['heaper', 'reheap'], + 'rehear': ['hearer', 'rehear'], + 'rehearser': ['rehearser', 'reshearer'], + 'rehearten': ['heartener', 'rehearten'], + 'reheat': ['heater', 'hereat', 'reheat'], + 'reheel': ['heeler', 'reheel'], + 'reheighten': ['heightener', 'reheighten'], + 'rehoist': ['hoister', 'rehoist'], + 'rehollow': ['hollower', 'rehollow'], + 'rehonor': ['honorer', 'rehonor'], + 'rehook': ['hooker', 'rehook'], + 'rehoop': ['hooper', 'rehoop'], + 'rehung': ['hunger', 'rehung'], + 'reid': ['dier', 'dire', 'reid', 'ride'], + 'reif': ['fire', 'reif', 'rife'], + 'reify': ['fiery', 'reify'], + 'reign': ['grein', 'inger', 'nigre', 'regin', 'reign', 'ringe'], + 'reignore': ['erigeron', 'reignore'], + 'reillustrate': ['reillustrate', 'ultrasterile'], + 'reim': ['emir', 'imer', 'mire', 'reim', 'remi', 'riem', 'rime'], + 'reimbody': ['embryoid', 'reimbody'], + 'reimpart': ['imparter', 'reimpart'], + 'reimplant': ['implanter', 'reimplant'], + 'reimply': ['primely', 'reimply'], + 'reimport': ['importer', 'promerit', 'reimport'], + 'reimpose': ['perisome', 'promisee', 'reimpose'], + 'reimpress': ['impresser', 'reimpress'], + 'reimpression': ['reimpression', 'repermission'], + 'reimprint': ['imprinter', 'reimprint'], + 'reimprison': ['imprisoner', 'reimprison'], + 'rein': ['neri', 'rein', 'rine'], + 'reina': ['erian', 'irena', 'reina'], + 'reincentive': ['internecive', 'reincentive'], + 'reincite': ['icterine', 'reincite'], + 'reincrudate': ['antireducer', 'reincrudate', 'untraceried'], + 'reindeer': ['denierer', 'reindeer'], + 'reindict': ['indicter', 'indirect', 'reindict'], + 'reindue': ['reindue', 'uredine'], + 'reinfect': ['frenetic', 'infecter', 'reinfect'], + 'reinfer': ['refiner', 'reinfer'], + 'reinfest': ['infester', 'reinfest'], + 'reinflate': ['interleaf', 'reinflate'], + 'reinflict': ['inflicter', 'reinflict'], + 'reinform': ['informer', 'reinform', 'reniform'], + 'reinhabit': ['inhabiter', 'reinhabit'], + 'reins': ['reins', 'resin', 'rinse', 'risen', 'serin', 'siren'], + 'reinsane': ['anserine', 'reinsane'], + 'reinsert': ['inserter', 'reinsert'], + 'reinsist': ['insister', 'reinsist', 'sinister', 'sisterin'], + 'reinspect': ['prescient', 'reinspect'], + 'reinspector': ['prosecretin', 'reinspector'], + 'reinspirit': ['inspiriter', 'reinspirit'], + 'reinstall': ['installer', 'reinstall'], + 'reinstation': ['reinstation', 'santorinite'], + 'reinstill': ['instiller', 'reinstill'], + 'reinstruct': ['instructer', 'intercrust', 'reinstruct'], + 'reinsult': ['insulter', 'lustrine', 'reinsult'], + 'reintend': ['indenter', 'intender', 'reintend'], + 'reinter': ['reinter', 'terrine'], + 'reinterest': ['interester', 'reinterest'], + 'reinterpret': ['interpreter', 'reinterpret'], + 'reinterrupt': ['interrupter', 'reinterrupt'], + 'reinterview': ['interviewer', 'reinterview'], + 'reintrench': ['intrencher', 'reintrench'], + 'reintrude': ['reintrude', 'unretired'], + 'reinvent': ['inventer', 'reinvent', 'ventrine', 'vintener'], + 'reinvert': ['inverter', 'reinvert', 'trinerve'], + 'reinvest': ['reinvest', 'servient'], + 'reis': ['reis', 'rise', 'seri', 'sier', 'sire'], + 'reit': ['iter', 'reit', 'rite', 'teri', 'tier', 'tire'], + 'reiter': ['errite', 'reiter', 'retier', 'retire', 'tierer'], + 'reiterable': ['reiterable', 'reliberate'], + 'rejail': ['jailer', 'rejail'], + 'rejerk': ['jerker', 'rejerk'], + 'rejoin': ['joiner', 'rejoin'], + 'rejolt': ['jolter', 'rejolt'], + 'rejourney': ['journeyer', 'rejourney'], + 'reki': ['erik', 'kier', 'reki'], + 'rekick': ['kicker', 'rekick'], + 'rekill': ['killer', 'rekill'], + 'rekiss': ['kisser', 'rekiss'], + 'reknit': ['reknit', 'tinker'], + 'reknow': ['knower', 'reknow', 'wroken'], + 'rel': ['ler', 'rel'], + 'relabel': ['labeler', 'relabel'], + 'relace': ['alerce', 'cereal', 'relace'], + 'relacquer': ['lacquerer', 'relacquer'], + 'relade': ['dealer', 'leader', 'redeal', 'relade', 'relead'], + 'reladen': ['leander', 'learned', 'reladen'], + 'relais': ['israel', 'relais', 'resail', 'sailer', 'serail', 'serial'], + 'relament': ['lamenter', 'relament', 'remantle'], + 'relamp': ['lamper', 'palmer', 'relamp'], + 'reland': ['aldern', + 'darnel', + 'enlard', + 'lander', + 'lenard', + 'randle', + 'reland'], + 'relap': ['lepra', 'paler', 'parel', 'parle', 'pearl', 'perla', 'relap'], + 'relapse': ['pleaser', 'preseal', 'relapse'], + 'relapsing': ['espringal', 'presignal', 'relapsing'], + 'relast': ['laster', + 'lastre', + 'rastle', + 'relast', + 'resalt', + 'salter', + 'slater', + 'stelar'], + 'relata': ['latera', 'relata'], + 'relatability': ['alterability', 'bilaterality', 'relatability'], + 'relatable': ['alterable', 'relatable'], + 'relatch': ['clethra', 'latcher', 'ratchel', 'relatch', 'talcher', 'trachle'], + 'relate': ['earlet', 'elater', 'relate'], + 'related': ['delater', 'related', 'treadle'], + 'relater': ['alterer', 'realter', 'relater'], + 'relation': ['oriental', 'relation', 'tirolean'], + 'relationism': ['misrelation', 'orientalism', 'relationism'], + 'relationist': ['orientalist', 'relationist'], + 'relative': ['levirate', 'relative'], + 'relativization': ['relativization', 'revitalization'], + 'relativize': ['relativize', 'revitalize'], + 'relator': ['realtor', 'relator'], + 'relaunch': ['launcher', 'relaunch'], + 'relay': ['early', 'layer', 'relay'], + 'relead': ['dealer', 'leader', 'redeal', 'relade', 'relead'], + 'releap': ['leaper', 'releap', 'repale', 'repeal'], + 'relearn': ['learner', 'relearn'], + 'releather': ['leatherer', 'releather', 'tarheeler'], + 'relection': ['centriole', 'electrion', 'relection'], + 'relegate': ['eglatere', 'regelate', 'relegate'], + 'relegation': ['regelation', 'relegation'], + 'relend': ['lender', 'relend'], + 'reletter': ['letterer', 'reletter'], + 'relevant': ['levanter', 'relevant', 'revelant'], + 'relevation': ['relevation', 'revelation'], + 'relevator': ['relevator', 'revelator', 'veratrole'], + 'relevel': ['leveler', 'relevel'], + 'reliably': ['beryllia', 'reliably'], + 'reliance': ['cerealin', 'cinereal', 'reliance'], + 'reliant': ['entrail', + 'latiner', + 'latrine', + 'ratline', + 'reliant', + 'retinal', + 'trenail'], + 'reliantly': ['interally', 'reliantly'], + 'reliberate': ['reiterable', 'reliberate'], + 'relic': ['crile', 'elric', 'relic'], + 'relick': ['licker', 'relick', 'rickle'], + 'relicted': ['derelict', 'relicted'], + 'relier': ['lierre', 'relier'], + 'relieving': ['inveigler', 'relieving'], + 'relievo': ['overlie', 'relievo'], + 'relift': ['fertil', 'filter', 'lifter', 'relift', 'trifle'], + 'religation': ['genitorial', 'religation'], + 'relight': ['lighter', 'relight', 'rightle'], + 'relighten': ['lightener', 'relighten', 'threeling'], + 'religion': ['ligroine', 'religion'], + 'relimit': ['limiter', 'relimit'], + 'reline': ['lierne', 'reline'], + 'relink': ['linker', 'relink'], + 'relish': ['hirsel', 'hirsle', 'relish'], + 'relishy': ['relishy', 'shirley'], + 'relist': ['lister', 'relist'], + 'relisten': ['enlister', 'esterlin', 'listener', 'relisten'], + 'relive': ['levier', 'relive', 'reveil', 'revile', 'veiler'], + 'reload': ['loader', 'ordeal', 'reload'], + 'reloan': ['lenora', 'loaner', 'orlean', 'reloan'], + 'relocation': ['iconolater', 'relocation'], + 'relock': ['locker', 'relock'], + 'relook': ['looker', 'relook'], + 'relose': ['relose', 'resole'], + 'relost': ['relost', 'reslot', 'rostel', 'sterol', 'torsel'], + 'relot': ['lerot', 'orlet', 'relot'], + 'relower': ['lowerer', 'relower'], + 'reluct': ['cutler', 'reluct'], + 'reluctation': ['countertail', 'reluctation'], + 'relumine': ['lemurine', 'meruline', 'relumine'], + 'rely': ['lyre', 'rely'], + 'remade': ['meader', 'remade'], + 'remagnification': ['germanification', 'remagnification'], + 'remagnify': ['germanify', 'remagnify'], + 'remail': ['mailer', 'remail'], + 'remain': ['ermani', 'marine', 'remain'], + 'remains': ['remains', 'seminar'], + 'remaintain': ['antimerina', 'maintainer', 'remaintain'], + 'reman': ['enarm', 'namer', 'reman'], + 'remand': ['damner', 'manred', 'randem', 'remand'], + 'remanet': ['remanet', 'remeant', 'treeman'], + 'remantle': ['lamenter', 'relament', 'remantle'], + 'remap': ['amper', 'remap'], + 'remarch': ['charmer', 'marcher', 'remarch'], + 'remark': ['marker', 'remark'], + 'remarket': ['marketer', 'remarket'], + 'remarry': ['marryer', 'remarry'], + 'remarshal': ['marshaler', 'remarshal'], + 'remask': ['masker', 'remask'], + 'remass': ['masser', 'remass'], + 'remast': ['martes', 'master', 'remast', 'stream'], + 'remasticate': ['metrectasia', 'remasticate'], + 'rematch': ['matcher', 'rematch'], + 'remeant': ['remanet', 'remeant', 'treeman'], + 'remede': ['deemer', 'meered', 'redeem', 'remede'], + 'remeet': ['meeter', 'remeet', 'teemer'], + 'remelt': ['melter', 'remelt'], + 'remend': ['mender', 'remend'], + 'remetal': ['lameter', 'metaler', 'remetal'], + 'remi': ['emir', 'imer', 'mire', 'reim', 'remi', 'riem', 'rime'], + 'remication': ['marcionite', 'microtinae', 'remication'], + 'remigate': ['emigrate', 'remigate'], + 'remigation': ['emigration', 'remigation'], + 'remill': ['miller', 'remill'], + 'remind': ['minder', 'remind'], + 'remint': ['minter', 'remint', 'termin'], + 'remiped': ['demirep', 'epiderm', 'impeder', 'remiped'], + 'remisrepresent': ['misrepresenter', 'remisrepresent'], + 'remission': ['missioner', 'remission'], + 'remisunderstand': ['misunderstander', 'remisunderstand'], + 'remit': ['merit', 'miter', 'mitre', 'remit', 'timer'], + 'remittal': ['remittal', 'termital'], + 'remittance': ['carminette', 'remittance'], + 'remittence': ['centimeter', 'recitement', 'remittence'], + 'remitter': ['remitter', 'trimeter'], + 'remix': ['mixer', 'remix'], + 'remnant': ['manrent', 'remnant'], + 'remock': ['mocker', 'remock'], + 'remodel': ['demerol', 'modeler', 'remodel'], + 'remold': ['dermol', 'molder', 'remold'], + 'remontant': ['nonmatter', 'remontant'], + 'remontoir': ['interroom', 'remontoir'], + 'remop': ['merop', 'moper', 'proem', 'remop'], + 'remora': ['remora', 'roamer'], + 'remord': ['dormer', 'remord'], + 'remote': ['meteor', 'remote'], + 'remotive': ['overtime', 'remotive'], + 'remould': ['remould', 'ruledom'], + 'remount': ['monture', 'mounter', 'remount'], + 'removable': ['overblame', 'removable'], + 'remunerate': ['remunerate', 'renumerate'], + 'remuneration': ['remuneration', 'renumeration'], + 'remurmur': ['murmurer', 'remurmur'], + 'remus': ['muser', 'remus', 'serum'], + 'remuster': ['musterer', 'remuster'], + 'renable': ['enabler', 'renable'], + 'renably': ['blarney', 'renably'], + 'renail': ['arline', 'larine', 'linear', 'nailer', 'renail'], + 'renaissance': ['necessarian', 'renaissance'], + 'renal': ['learn', 'renal'], + 'rename': ['enarme', 'meaner', 'rename'], + 'renavigate': ['renavigate', 'vegetarian'], + 'rend': ['dern', 'rend'], + 'rendition': ['rendition', 'trinodine'], + 'reneg': ['genre', 'green', 'neger', 'reneg'], + 'renegadism': ['grandeeism', 'renegadism'], + 'renegation': ['generation', 'renegation'], + 'renege': ['neeger', 'reenge', 'renege'], + 'reneger': ['greener', 'regreen', 'reneger'], + 'reneglect': ['neglecter', 'reneglect'], + 'renerve': ['renerve', 'venerer'], + 'renes': ['renes', 'sneer'], + 'renet': ['enter', 'neter', 'renet', 'terne', 'treen'], + 'reniform': ['informer', 'reinform', 'reniform'], + 'renilla': ['ralline', 'renilla'], + 'renin': ['inner', 'renin'], + 'reniportal': ['interpolar', 'reniportal'], + 'renish': ['renish', 'shiner', 'shrine'], + 'renitence': ['centenier', 'renitence'], + 'renitency': ['nycterine', 'renitency'], + 'renitent': ['renitent', 'trentine'], + 'renk': ['kern', 'renk'], + 'rennet': ['rennet', 'tenner'], + 'renography': ['granophyre', 'renography'], + 'renominate': ['enantiomer', 'renominate'], + 'renotation': ['renotation', 'retonation'], + 'renotice': ['erection', 'neoteric', 'nocerite', 'renotice'], + 'renourish': ['nourisher', 'renourish'], + 'renovate': ['overneat', 'renovate'], + 'renovater': ['enervator', 'renovater', 'venerator'], + 'renown': ['renown', 'wonner'], + 'rent': ['rent', 'tern'], + 'rentage': ['grantee', 'greaten', 'reagent', 'rentage'], + 'rental': ['altern', 'antler', 'learnt', 'rental', 'ternal'], + 'rentaler': ['rentaler', 'rerental'], + 'rented': ['denter', 'rented', 'tender'], + 'rentee': ['entree', 'rentee', 'retene'], + 'renter': ['renter', 'rerent'], + 'renu': ['renu', 'ruen', 'rune'], + 'renumber': ['numberer', 'renumber'], + 'renumerate': ['remunerate', 'renumerate'], + 'renumeration': ['remuneration', 'renumeration'], + 'reobtain': ['abrotine', 'baritone', 'obtainer', 'reobtain'], + 'reoccasion': ['occasioner', 'reoccasion'], + 'reoccupation': ['cornucopiate', 'reoccupation'], + 'reoffend': ['offender', 'reoffend'], + 'reoffer': ['offerer', 'reoffer'], + 'reoil': ['oiler', 'oriel', 'reoil'], + 'reopen': ['opener', 'reopen', 'repone'], + 'reordain': ['inroader', 'ordainer', 'reordain'], + 'reorder': ['orderer', 'reorder'], + 'reordinate': ['reordinate', 'treronidae'], + 'reornament': ['ornamenter', 'reornament'], + 'reoverflow': ['overflower', 'reoverflow'], + 'reown': ['owner', 'reown', 'rowen'], + 'rep': ['per', 'rep'], + 'repack': ['packer', 'repack'], + 'repaint': ['painter', 'pertain', 'pterian', 'repaint'], + 'repair': ['pairer', 'rapier', 'repair'], + 'repairer': ['rareripe', 'repairer'], + 'repale': ['leaper', 'releap', 'repale', 'repeal'], + 'repand': ['pander', 'repand'], + 'repandly': ['panderly', 'repandly'], + 'repandous': ['panderous', 'repandous'], + 'repanel': ['paneler', 'repanel', 'replane'], + 'repaper': ['paperer', 'perpera', 'prepare', 'repaper'], + 'reparagraph': ['paragrapher', 'reparagraph'], + 'reparation': ['praetorian', 'reparation'], + 'repark': ['parker', 'repark'], + 'repartee': ['repartee', 'repeater'], + 'repartition': ['partitioner', 'repartition'], + 'repass': ['passer', 'repass', 'sparse'], + 'repasser': ['asperser', 'repasser'], + 'repast': ['paster', 'repast', 'trapes'], + 'repaste': ['perates', 'repaste', 'sperate'], + 'repasture': ['repasture', 'supertare'], + 'repatch': ['chapter', 'patcher', 'repatch'], + 'repatent': ['pattener', 'repatent'], + 'repattern': ['patterner', 'repattern'], + 'repawn': ['enwrap', 'pawner', 'repawn'], + 'repay': ['apery', 'payer', 'repay'], + 'repeal': ['leaper', 'releap', 'repale', 'repeal'], + 'repeat': ['petrea', 'repeat', 'retape'], + 'repeater': ['repartee', 'repeater'], + 'repel': ['leper', 'perle', 'repel'], + 'repen': ['neper', 'preen', 'repen'], + 'repension': ['pensioner', 'repension'], + 'repent': ['perten', 'repent'], + 'repentable': ['penetrable', 'repentable'], + 'repentance': ['penetrance', 'repentance'], + 'repentant': ['penetrant', 'repentant'], + 'reperceive': ['prereceive', 'reperceive'], + 'repercussion': ['percussioner', 'repercussion'], + 'repercussive': ['repercussive', 'superservice'], + 'reperform': ['performer', 'prereform', 'reperform'], + 'repermission': ['reimpression', 'repermission'], + 'repermit': ['premerit', 'preremit', 'repermit'], + 'reperplex': ['perplexer', 'reperplex'], + 'reperusal': ['pleasurer', 'reperusal'], + 'repetition': ['petitioner', 'repetition'], + 'rephael': ['preheal', 'rephael'], + 'rephase': ['hespera', 'rephase', 'reshape'], + 'rephotograph': ['photographer', 'rephotograph'], + 'rephrase': ['preshare', 'rephrase'], + 'repic': ['price', 'repic'], + 'repick': ['picker', 'repick'], + 'repiece': ['creepie', 'repiece'], + 'repin': ['piner', 'prine', 'repin', 'ripen'], + 'repine': ['neiper', 'perine', 'pirene', 'repine'], + 'repiner': ['repiner', 'ripener'], + 'repiningly': ['repiningly', 'ripeningly'], + 'repique': ['perique', 'repique'], + 'repitch': ['pitcher', 'repitch'], + 'replace': ['percale', 'replace'], + 'replait': ['partile', 'plaiter', 'replait'], + 'replan': ['parnel', 'planer', 'replan'], + 'replane': ['paneler', 'repanel', 'replane'], + 'replant': ['pantler', 'planter', 'replant'], + 'replantable': ['planetabler', 'replantable'], + 'replanter': ['prerental', 'replanter'], + 'replaster': ['plasterer', 'replaster'], + 'replate': ['pearlet', 'pleater', 'prelate', 'ptereal', 'replate', 'repleat'], + 'replay': ['parley', 'pearly', 'player', 'replay'], + 'replead': ['pearled', 'pedaler', 'pleader', 'replead'], + 'repleader': ['predealer', 'repleader'], + 'repleat': ['pearlet', 'pleater', 'prelate', 'ptereal', 'replate', 'repleat'], + 'repleteness': ['repleteness', 'terpeneless'], + 'repletion': ['interlope', 'interpole', 'repletion', 'terpineol'], + 'repliant': ['interlap', 'repliant', 'triplane'], + 'replica': ['caliper', 'picarel', 'replica'], + 'replight': ['plighter', 'replight'], + 'replod': ['podler', 'polder', 'replod'], + 'replot': ['petrol', 'replot'], + 'replow': ['plower', 'replow'], + 'replum': ['lumper', 'plumer', 'replum', 'rumple'], + 'replunder': ['plunderer', 'replunder'], + 'reply': ['plyer', 'reply'], + 'repocket': ['pocketer', 'repocket'], + 'repoint': ['pointer', 'protein', 'pterion', 'repoint', 'tropine'], + 'repolish': ['polisher', 'repolish'], + 'repoll': ['poller', 'repoll'], + 'reponder': ['ponderer', 'reponder'], + 'repone': ['opener', 'reopen', 'repone'], + 'report': ['porret', 'porter', 'report', 'troper'], + 'reportage': ['porterage', 'reportage'], + 'reporterism': ['misreporter', 'reporterism'], + 'reportion': ['portioner', 'reportion'], + 'reposed': ['deposer', 'reposed'], + 'reposit': ['periost', 'porites', 'reposit', 'riposte'], + 'reposition': ['positioner', 'reposition'], + 'repositor': ['posterior', 'repositor'], + 'repossession': ['possessioner', 'repossession'], + 'repost': ['poster', 'presto', 'repost', 'respot', 'stoper'], + 'repot': ['poter', 'prote', 'repot', 'tepor', 'toper', 'trope'], + 'repound': ['pounder', 'repound', 'unroped'], + 'repour': ['pourer', 'repour', 'rouper'], + 'repowder': ['powderer', 'repowder'], + 'repp': ['prep', 'repp'], + 'repray': ['prayer', 'repray'], + 'repreach': ['preacher', 'repreach'], + 'repredict': ['precredit', 'predirect', 'repredict'], + 'reprefer': ['prerefer', 'reprefer'], + 'represent': ['presenter', 'represent'], + 'representationism': ['misrepresentation', 'representationism'], + 'repress': ['presser', 'repress'], + 'repressive': ['repressive', 'respersive'], + 'reprice': ['piercer', 'reprice'], + 'reprieval': ['prevailer', 'reprieval'], + 'reprime': ['premier', 'reprime'], + 'reprint': ['printer', 'reprint'], + 'reprise': ['reprise', 'respire'], + 'repristination': ['interspiration', 'repristination'], + 'reproachable': ['blepharocera', 'reproachable'], + 'reprobate': ['perborate', 'prorebate', 'reprobate'], + 'reprobation': ['probationer', 'reprobation'], + 'reproceed': ['proceeder', 'reproceed'], + 'reproclaim': ['proclaimer', 'reproclaim'], + 'reproduce': ['procedure', 'reproduce'], + 'reproduction': ['proreduction', 'reproduction'], + 'reprohibit': ['prohibiter', 'reprohibit'], + 'reproof': ['proofer', 'reproof'], + 'reproportion': ['proportioner', 'reproportion'], + 'reprotection': ['interoceptor', 'reprotection'], + 'reprotest': ['protester', 'reprotest'], + 'reprovision': ['prorevision', 'provisioner', 'reprovision'], + 'reps': ['reps', 'resp'], + 'reptant': ['pattern', 'reptant'], + 'reptatorial': ['proletariat', 'reptatorial'], + 'reptatory': ['protreaty', 'reptatory'], + 'reptile': ['perlite', 'reptile'], + 'reptilia': ['liparite', 'reptilia'], + 'republish': ['publisher', 'republish'], + 'repudiatory': ['preauditory', 'repudiatory'], + 'repuff': ['puffer', 'repuff'], + 'repugn': ['punger', 'repugn'], + 'repulpit': ['pulpiter', 'repulpit'], + 'repulsion': ['prelusion', 'repulsion'], + 'repulsive': ['prelusive', 'repulsive'], + 'repulsively': ['prelusively', 'repulsively'], + 'repulsory': ['prelusory', 'repulsory'], + 'repump': ['pumper', 'repump'], + 'repunish': ['punisher', 'repunish'], + 'reputative': ['reputative', 'vituperate'], + 'repute': ['repute', 'uptree'], + 'requench': ['quencher', 'requench'], + 'request': ['quester', 'request'], + 'requestion': ['questioner', 'requestion'], + 'require': ['querier', 'require'], + 'requital': ['quartile', 'requital', 'triequal'], + 'requite': ['quieter', 'requite'], + 'rerack': ['racker', 'rerack'], + 'rerail': ['railer', 'rerail'], + 'reraise': ['rearise', 'reraise'], + 'rerake': ['karree', 'rerake'], + 'rerank': ['ranker', 'rerank'], + 'rerate': ['rerate', 'retare', 'tearer'], + 'reread': ['reader', 'redare', 'reread'], + 'rereel': ['reeler', 'rereel'], + 'reregister': ['registerer', 'reregister'], + 'rerent': ['renter', 'rerent'], + 'rerental': ['rentaler', 'rerental'], + 'rering': ['erring', 'rering', 'ringer'], + 'rerise': ['rerise', 'sirree'], + 'rerivet': ['rerivet', 'riveter'], + 'rerob': ['borer', 'rerob', 'rober'], + 'rerobe': ['rebore', 'rerobe'], + 'reroll': ['reroll', 'roller'], + 'reroof': ['reroof', 'roofer'], + 'reroot': ['reroot', 'rooter', 'torero'], + 'rerow': ['rerow', 'rower'], + 'rerun': ['rerun', 'runer'], + 'resaca': ['ascare', 'caesar', 'resaca'], + 'resack': ['resack', 'sacker', 'screak'], + 'resail': ['israel', 'relais', 'resail', 'sailer', 'serail', 'serial'], + 'resale': ['alerse', 'leaser', 'reales', 'resale', 'reseal', 'sealer'], + 'resalt': ['laster', + 'lastre', + 'rastle', + 'relast', + 'resalt', + 'salter', + 'slater', + 'stelar'], + 'resanction': ['resanction', 'sanctioner'], + 'resaw': ['resaw', 'sawer', 'seraw', 'sware', 'swear', 'warse'], + 'resawer': ['resawer', 'reswear', 'swearer'], + 'resay': ['reasy', 'resay', 'sayer', 'seary'], + 'rescan': ['casern', 'rescan'], + 'rescind': ['discern', 'rescind'], + 'rescinder': ['discerner', 'rescinder'], + 'rescindment': ['discernment', 'rescindment'], + 'rescratch': ['rescratch', 'scratcher'], + 'rescuable': ['rescuable', 'securable'], + 'rescue': ['cereus', 'ceruse', 'recuse', 'rescue', 'secure'], + 'rescuer': ['recurse', 'rescuer', 'securer'], + 'reseal': ['alerse', 'leaser', 'reales', 'resale', 'reseal', 'sealer'], + 'reseam': ['reseam', 'seamer'], + 'research': ['rechaser', 'research', 'searcher'], + 'reseat': ['asteer', + 'easter', + 'eastre', + 'reseat', + 'saeter', + 'seater', + 'staree', + 'teaser', + 'teresa'], + 'resect': ['resect', 'screet', 'secret'], + 'resection': ['resection', 'secretion'], + 'resectional': ['resectional', 'secretional'], + 'reseda': ['erased', 'reseda', 'seared'], + 'resee': ['esere', 'reese', 'resee'], + 'reseed': ['reseed', 'seeder'], + 'reseek': ['reseek', 'seeker'], + 'resell': ['resell', 'seller'], + 'resend': ['resend', 'sender'], + 'resene': ['resene', 'serene'], + 'resent': ['ernest', 'nester', 'resent', 'streen'], + 'reservable': ['reservable', 'reversable'], + 'reserval': ['reserval', 'reversal', 'slaverer'], + 'reserve': ['reserve', 'resever', 'reverse', 'severer'], + 'reserved': ['deserver', 'reserved', 'reversed'], + 'reservedly': ['reservedly', 'reversedly'], + 'reserveful': ['reserveful', 'reverseful'], + 'reserveless': ['reserveless', 'reverseless'], + 'reserver': ['reserver', 'reverser'], + 'reservist': ['reservist', 'reversist'], + 'reset': ['ester', + 'estre', + 'reest', + 'reset', + 'steer', + 'stere', + 'stree', + 'terse', + 'tsere'], + 'resever': ['reserve', 'resever', 'reverse', 'severer'], + 'resew': ['resew', 'sewer', 'sweer'], + 'resex': ['resex', 'xeres'], + 'resh': ['hers', 'resh', 'sher'], + 'reshape': ['hespera', 'rephase', 'reshape'], + 'reshare': ['reshare', 'reshear', 'shearer'], + 'resharpen': ['resharpen', 'sharpener'], + 'reshear': ['reshare', 'reshear', 'shearer'], + 'reshearer': ['rehearser', 'reshearer'], + 'reshift': ['reshift', 'shifter'], + 'reshingle': ['englisher', 'reshingle'], + 'reship': ['perish', 'reship'], + 'reshipment': ['perishment', 'reshipment'], + 'reshoot': ['orthose', 'reshoot', 'shooter', 'soother'], + 'reshoulder': ['reshoulder', 'shoulderer'], + 'reshower': ['reshower', 'showerer'], + 'reshun': ['reshun', 'rushen'], + 'reshunt': ['reshunt', 'shunter'], + 'reshut': ['reshut', 'suther', 'thurse', 'tusher'], + 'reside': ['desire', 'reside'], + 'resident': ['indesert', 'inserted', 'resident'], + 'resider': ['derries', 'desirer', 'resider', 'serried'], + 'residua': ['residua', 'ursidae'], + 'resift': ['fister', 'resift', 'sifter', 'strife'], + 'resigh': ['resigh', 'sigher'], + 'resign': ['resign', 'resing', 'signer', 'singer'], + 'resignal': ['resignal', 'seringal', 'signaler'], + 'resigned': ['designer', 'redesign', 'resigned'], + 'resile': ['lisere', 'resile'], + 'resiliate': ['israelite', 'resiliate'], + 'resilient': ['listerine', 'resilient'], + 'resilition': ['isonitrile', 'resilition'], + 'resilver': ['resilver', 'silverer', 'sliverer'], + 'resin': ['reins', 'resin', 'rinse', 'risen', 'serin', 'siren'], + 'resina': ['arisen', 'arsine', 'resina', 'serian'], + 'resinate': ['arsenite', 'resinate', 'teresian', 'teresina'], + 'resing': ['resign', 'resing', 'signer', 'singer'], + 'resinic': ['irenics', 'resinic', 'sericin', 'sirenic'], + 'resinize': ['resinize', 'sirenize'], + 'resink': ['resink', 'reskin', 'sinker'], + 'resinlike': ['resinlike', 'sirenlike'], + 'resinoid': ['derision', 'ironside', 'resinoid', 'sirenoid'], + 'resinol': ['resinol', 'serolin'], + 'resinous': ['neurosis', 'resinous'], + 'resinously': ['neurolysis', 'resinously'], + 'resiny': ['resiny', 'sireny'], + 'resist': ['resist', 'restis', 'sister'], + 'resistable': ['assertible', 'resistable'], + 'resistance': ['resistance', 'senatrices'], + 'resistful': ['fruitless', 'resistful'], + 'resisting': ['resisting', 'sistering'], + 'resistless': ['resistless', 'sisterless'], + 'resize': ['resize', 'seizer'], + 'resketch': ['resketch', 'sketcher'], + 'reskin': ['resink', 'reskin', 'sinker'], + 'reslash': ['reslash', 'slasher'], + 'reslate': ['realest', 'reslate', 'resteal', 'stealer', 'teasler'], + 'reslay': ['reslay', 'slayer'], + 'reslot': ['relost', 'reslot', 'rostel', 'sterol', 'torsel'], + 'resmell': ['resmell', 'smeller'], + 'resmelt': ['melters', 'resmelt', 'smelter'], + 'resmooth': ['resmooth', 'romeshot', 'smoother'], + 'resnap': ['resnap', 'respan', 'snaper'], + 'resnatch': ['resnatch', 'snatcher', 'stancher'], + 'resoak': ['arkose', 'resoak', 'soaker'], + 'resoap': ['resoap', 'soaper'], + 'resoften': ['resoften', 'softener'], + 'resoil': ['elisor', 'resoil'], + 'resojourn': ['resojourn', 'sojourner'], + 'resolder': ['resolder', 'solderer'], + 'resole': ['relose', 'resole'], + 'resolicit': ['resolicit', 'soliciter'], + 'resolution': ['resolution', 'solutioner'], + 'resonate': ['orestean', 'resonate', 'stearone'], + 'resort': ['resort', 'roster', 'sorter', 'storer'], + 'resorter': ['resorter', 'restorer', 'retrorse'], + 'resound': ['resound', 'sounder', 'unrosed'], + 'resource': ['recourse', 'resource'], + 'resow': ['owser', 'resow', 'serow', 'sower', 'swore', 'worse'], + 'resp': ['reps', 'resp'], + 'respace': ['escaper', 'respace'], + 'respade': ['psedera', 'respade'], + 'respan': ['resnap', 'respan', 'snaper'], + 'respeak': ['respeak', 'speaker'], + 'respect': ['respect', 'scepter', 'specter'], + 'respectless': ['respectless', 'scepterless'], + 'respell': ['presell', 'respell', 'speller'], + 'respersive': ['repressive', 'respersive'], + 'respin': ['pernis', 'respin', 'sniper'], + 'respiration': ['respiration', 'retinispora'], + 'respire': ['reprise', 'respire'], + 'respirit': ['respirit', 'spiriter'], + 'respite': ['respite', 'septier'], + 'resplend': ['resplend', 'splender'], + 'resplice': ['eclipser', 'pericles', 'resplice'], + 'responde': ['personed', 'responde'], + 'respondence': ['precondense', 'respondence'], + 'responsal': ['apronless', 'responsal'], + 'response': ['pessoner', 'response'], + 'respot': ['poster', 'presto', 'repost', 'respot', 'stoper'], + 'respray': ['respray', 'sprayer'], + 'respread': ['respread', 'spreader'], + 'respring': ['respring', 'springer'], + 'resprout': ['posturer', 'resprout', 'sprouter'], + 'respue': ['peruse', 'respue'], + 'resqueak': ['resqueak', 'squeaker'], + 'ressaut': ['erastus', 'ressaut'], + 'rest': ['rest', 'sert', 'stre'], + 'restack': ['restack', 'stacker'], + 'restaff': ['restaff', 'staffer'], + 'restain': ['asterin', 'eranist', 'restain', 'stainer', 'starnie', 'stearin'], + 'restake': ['restake', 'sakeret'], + 'restamp': ['restamp', 'stamper'], + 'restart': ['restart', 'starter'], + 'restate': ['estreat', 'restate', 'retaste'], + 'resteal': ['realest', 'reslate', 'resteal', 'stealer', 'teasler'], + 'resteel': ['reestle', 'resteel', 'steeler'], + 'resteep': ['estrepe', 'resteep', 'steeper'], + 'restem': ['mester', 'restem', 'temser', 'termes'], + 'restep': ['pester', 'preset', 'restep', 'streep'], + 'restful': ['fluster', 'restful'], + 'restiad': ['astride', 'diaster', 'disrate', 'restiad', 'staired'], + 'restiffen': ['restiffen', 'stiffener'], + 'restiform': ['reformist', 'restiform'], + 'resting': ['resting', 'stinger'], + 'restio': ['restio', 'sorite', 'sortie', 'triose'], + 'restis': ['resist', 'restis', 'sister'], + 'restitch': ['restitch', 'stitcher'], + 'restive': ['restive', 'servite'], + 'restock': ['restock', 'stocker'], + 'restorer': ['resorter', 'restorer', 'retrorse'], + 'restow': ['restow', 'stower', 'towser', 'worset'], + 'restowal': ['restowal', 'sealwort'], + 'restraighten': ['restraighten', 'straightener'], + 'restrain': ['restrain', 'strainer', 'transire'], + 'restraint': ['restraint', 'retransit', 'trainster', 'transiter'], + 'restream': ['masterer', 'restream', 'streamer'], + 'restrengthen': ['restrengthen', 'strengthener'], + 'restress': ['restress', 'stresser'], + 'restretch': ['restretch', 'stretcher'], + 'restring': ['restring', 'ringster', 'stringer'], + 'restrip': ['restrip', 'striper'], + 'restrive': ['restrive', 'reverist'], + 'restuff': ['restuff', 'stuffer'], + 'resty': ['resty', 'strey'], + 'restyle': ['restyle', 'tersely'], + 'resucceed': ['resucceed', 'succeeder'], + 'resuck': ['resuck', 'sucker'], + 'resue': ['resue', 'reuse'], + 'resuffer': ['resuffer', 'sufferer'], + 'resuggest': ['resuggest', 'suggester'], + 'resuing': ['insurge', 'resuing'], + 'resuit': ['isuret', 'resuit'], + 'result': ['luster', 'result', 'rustle', 'sutler', 'ulster'], + 'resulting': ['resulting', 'ulstering'], + 'resultless': ['lusterless', 'lustreless', 'resultless'], + 'resummon': ['resummon', 'summoner'], + 'resun': ['nurse', 'resun'], + 'resup': ['purse', 'resup', 'sprue', 'super'], + 'resuperheat': ['resuperheat', 'superheater'], + 'resupinate': ['interpause', 'resupinate'], + 'resupination': ['resupination', 'uranospinite'], + 'resupport': ['resupport', 'supporter'], + 'resuppose': ['resuppose', 'superpose'], + 'resupposition': ['resupposition', 'superposition'], + 'resuppress': ['resuppress', 'suppresser'], + 'resurrender': ['resurrender', 'surrenderer'], + 'resurround': ['resurround', 'surrounder'], + 'resuspect': ['resuspect', 'suspecter'], + 'resuspend': ['resuspend', 'suspender', 'unpressed'], + 'reswallow': ['reswallow', 'swallower'], + 'resward': ['drawers', 'resward'], + 'reswarm': ['reswarm', 'swarmer'], + 'reswear': ['resawer', 'reswear', 'swearer'], + 'resweat': ['resweat', 'sweater'], + 'resweep': ['resweep', 'sweeper'], + 'reswell': ['reswell', 'sweller'], + 'reswill': ['reswill', 'swiller'], + 'retable': ['bearlet', 'bleater', 'elberta', 'retable'], + 'retack': ['racket', 'retack', 'tacker'], + 'retag': ['gater', 'grate', 'great', 'greta', 'retag', 'targe'], + 'retail': ['lirate', 'retail', 'retial', 'tailer'], + 'retailer': ['irrelate', 'retailer'], + 'retain': ['nerita', 'ratine', 'retain', 'retina', 'tanier'], + 'retainal': ['retainal', 'telarian'], + 'retainder': ['irredenta', 'retainder'], + 'retainer': ['arretine', 'eretrian', 'eritrean', 'retainer'], + 'retaining': ['negritian', 'retaining'], + 'retaliate': ['elettaria', 'retaliate'], + 'retalk': ['kartel', 'retalk', 'talker'], + 'retama': ['ramate', 'retama'], + 'retame': ['reetam', 'retame', 'teamer'], + 'retan': ['antre', 'arent', 'retan', 'terna'], + 'retape': ['petrea', 'repeat', 'retape'], + 'retard': ['darter', + 'dartre', + 'redart', + 'retard', + 'retrad', + 'tarred', + 'trader'], + 'retardent': ['retardent', 'tetrander'], + 'retare': ['rerate', 'retare', 'tearer'], + 'retaste': ['estreat', 'restate', 'retaste'], + 'retax': ['extra', 'retax', 'taxer'], + 'retaxation': ['retaxation', 'tetraxonia'], + 'retch': ['chert', 'retch'], + 'reteach': ['cheater', 'hectare', 'recheat', 'reteach', 'teacher'], + 'retelegraph': ['retelegraph', 'telegrapher'], + 'retell': ['retell', 'teller'], + 'retem': ['meter', 'retem'], + 'retemper': ['retemper', 'temperer'], + 'retempt': ['retempt', 'tempter'], + 'retenant': ['retenant', 'tenanter'], + 'retender': ['retender', 'tenderer'], + 'retene': ['entree', 'rentee', 'retene'], + 'retent': ['netter', 'retent', 'tenter'], + 'retention': ['intertone', 'retention'], + 'retepora': ['perorate', 'retepora'], + 'retest': ['retest', 'setter', 'street', 'tester'], + 'rethank': ['rethank', 'thanker'], + 'rethatch': ['rethatch', 'thatcher'], + 'rethaw': ['rethaw', 'thawer', 'wreath'], + 'rethe': ['ether', 'rethe', 'theer', 'there', 'three'], + 'retheness': ['retheness', 'thereness', 'threeness'], + 'rethicken': ['kitchener', 'rethicken', 'thickener'], + 'rethink': ['rethink', 'thinker'], + 'rethrash': ['rethrash', 'thrasher'], + 'rethread': ['rethread', 'threader'], + 'rethreaten': ['rethreaten', 'threatener'], + 'rethresh': ['rethresh', 'thresher'], + 'rethrill': ['rethrill', 'thriller'], + 'rethrow': ['rethrow', 'thrower'], + 'rethrust': ['rethrust', 'thruster'], + 'rethunder': ['rethunder', 'thunderer'], + 'retia': ['arite', 'artie', 'irate', 'retia', 'tarie'], + 'retial': ['lirate', 'retail', 'retial', 'tailer'], + 'reticent': ['reticent', 'tencteri'], + 'reticket': ['reticket', 'ticketer'], + 'reticula': ['arculite', 'cutleria', 'lucretia', 'reticula', 'treculia'], + 'reticular': ['curtailer', 'recruital', 'reticular'], + 'retier': ['errite', 'reiter', 'retier', 'retire', 'tierer'], + 'retighten': ['retighten', 'tightener'], + 'retill': ['retill', 'rillet', 'tiller'], + 'retimber': ['retimber', 'timberer'], + 'retime': ['metier', 'retime', 'tremie'], + 'retin': ['inert', 'inter', 'niter', 'retin', 'trine'], + 'retina': ['nerita', 'ratine', 'retain', 'retina', 'tanier'], + 'retinal': ['entrail', + 'latiner', + 'latrine', + 'ratline', + 'reliant', + 'retinal', + 'trenail'], + 'retinalite': ['retinalite', 'trilineate'], + 'retinene': ['internee', 'retinene'], + 'retinian': ['neritina', 'retinian'], + 'retinispora': ['respiration', 'retinispora'], + 'retinite': ['intertie', 'retinite'], + 'retinker': ['retinker', 'tinkerer'], + 'retinochorioiditis': ['chorioidoretinitis', 'retinochorioiditis'], + 'retinoid': ['neritoid', 'retinoid'], + 'retinue': ['neurite', 'retinue', 'reunite', 'uterine'], + 'retinula': ['lutrinae', 'retinula', 'rutelian', 'tenurial'], + 'retinular': ['retinular', 'trineural'], + 'retip': ['perit', 'retip', 'tripe'], + 'retiral': ['retiral', 'retrial', 'trailer'], + 'retire': ['errite', 'reiter', 'retier', 'retire', 'tierer'], + 'retirer': ['retirer', 'terrier'], + 'retistene': ['retistene', 'serinette'], + 'retoast': ['retoast', 'rosetta', 'stoater', 'toaster'], + 'retold': ['retold', 'rodlet'], + 'retomb': ['retomb', 'trombe'], + 'retonation': ['renotation', 'retonation'], + 'retool': ['looter', 'retool', 'rootle', 'tooler'], + 'retooth': ['retooth', 'toother'], + 'retort': ['retort', 'retrot', 'rotter'], + 'retoss': ['retoss', 'tosser'], + 'retouch': ['retouch', 'toucher'], + 'retour': ['retour', 'router', 'tourer'], + 'retrace': ['caterer', 'recrate', 'retrace', 'terrace'], + 'retrack': ['retrack', 'tracker'], + 'retractation': ['reattraction', 'retractation'], + 'retracted': ['detracter', 'retracted'], + 'retraction': ['retraction', 'triaconter'], + 'retrad': ['darter', + 'dartre', + 'redart', + 'retard', + 'retrad', + 'tarred', + 'trader'], + 'retrade': ['derater', 'retrade', 'retread', 'treader'], + 'retradition': ['retradition', 'traditioner'], + 'retrain': ['arterin', 'retrain', 'terrain', 'trainer'], + 'retral': ['retral', 'terral'], + 'retramp': ['retramp', 'tramper'], + 'retransform': ['retransform', 'transformer'], + 'retransit': ['restraint', 'retransit', 'trainster', 'transiter'], + 'retransplant': ['retransplant', 'transplanter'], + 'retransport': ['retransport', 'transporter'], + 'retravel': ['retravel', 'revertal', 'traveler'], + 'retread': ['derater', 'retrade', 'retread', 'treader'], + 'retreat': ['ettarre', 'retreat', 'treater'], + 'retree': ['retree', 'teerer'], + 'retrench': ['retrench', 'trencher'], + 'retrial': ['retiral', 'retrial', 'trailer'], + 'retrim': ['mitrer', 'retrim', 'trimer'], + 'retrocaecal': ['accelerator', 'retrocaecal'], + 'retrogradient': ['redintegrator', 'retrogradient'], + 'retrorse': ['resorter', 'restorer', 'retrorse'], + 'retrot': ['retort', 'retrot', 'rotter'], + 'retrue': ['retrue', 'ureter'], + 'retrust': ['retrust', 'truster'], + 'retry': ['retry', 'terry'], + 'retter': ['retter', 'terret'], + 'retting': ['gittern', 'gritten', 'retting'], + 'retube': ['rebute', 'retube'], + 'retuck': ['retuck', 'tucker'], + 'retune': ['neuter', 'retune', 'runtee', 'tenure', 'tureen'], + 'returf': ['returf', 'rufter'], + 'return': ['return', 'turner'], + 'retuse': ['retuse', 'tereus'], + 'retwine': ['enwrite', 'retwine'], + 'retwist': ['retwist', 'twister'], + 'retzian': ['retzian', 'terzina'], + 'reub': ['bure', 'reub', 'rube'], + 'reundergo': ['guerdoner', 'reundergo', 'undergoer', 'undergore'], + 'reune': ['enure', 'reune'], + 'reunfold': ['flounder', 'reunfold', 'unfolder'], + 'reunify': ['reunify', 'unfiery'], + 'reunionist': ['reunionist', 'sturionine'], + 'reunite': ['neurite', 'retinue', 'reunite', 'uterine'], + 'reunpack': ['reunpack', 'unpacker'], + 'reuphold': ['reuphold', 'upholder'], + 'reupholster': ['reupholster', 'upholsterer'], + 'reuplift': ['reuplift', 'uplifter'], + 'reuse': ['resue', 'reuse'], + 'reutter': ['reutter', 'utterer'], + 'revacate': ['acervate', 'revacate'], + 'revalidation': ['derivational', 'revalidation'], + 'revamp': ['revamp', 'vamper'], + 'revarnish': ['revarnish', 'varnisher'], + 'reve': ['ever', 'reve', 'veer'], + 'reveal': ['laveer', 'leaver', 'reveal', 'vealer'], + 'reveil': ['levier', 'relive', 'reveil', 'revile', 'veiler'], + 'revel': ['elver', 'lever', 'revel'], + 'revelant': ['levanter', 'relevant', 'revelant'], + 'revelation': ['relevation', 'revelation'], + 'revelator': ['relevator', 'revelator', 'veratrole'], + 'reveler': ['leverer', 'reveler'], + 'revenant': ['revenant', 'venerant'], + 'revend': ['revend', 'vender'], + 'revender': ['revender', 'reverend'], + 'reveneer': ['reveneer', 'veneerer'], + 'revent': ['revent', 'venter'], + 'revenue': ['revenue', 'unreeve'], + 'rever': ['rever', 'verre'], + 'reverend': ['revender', 'reverend'], + 'reverential': ['interleaver', 'reverential'], + 'reverist': ['restrive', 'reverist'], + 'revers': ['revers', 'server', 'verser'], + 'reversable': ['reservable', 'reversable'], + 'reversal': ['reserval', 'reversal', 'slaverer'], + 'reverse': ['reserve', 'resever', 'reverse', 'severer'], + 'reversed': ['deserver', 'reserved', 'reversed'], + 'reversedly': ['reservedly', 'reversedly'], + 'reverseful': ['reserveful', 'reverseful'], + 'reverseless': ['reserveless', 'reverseless'], + 'reverser': ['reserver', 'reverser'], + 'reversewise': ['reversewise', 'revieweress'], + 'reversi': ['reversi', 'reviser'], + 'reversion': ['reversion', 'versioner'], + 'reversist': ['reservist', 'reversist'], + 'revertal': ['retravel', 'revertal', 'traveler'], + 'revest': ['revest', 'servet', 'sterve', 'verset', 'vester'], + 'revet': ['evert', 'revet'], + 'revete': ['revete', 'tervee'], + 'revictual': ['lucrative', 'revictual', 'victualer'], + 'review': ['review', 'viewer'], + 'revieweress': ['reversewise', 'revieweress'], + 'revigorate': ['overgaiter', 'revigorate'], + 'revile': ['levier', 'relive', 'reveil', 'revile', 'veiler'], + 'reviling': ['reviling', 'vierling'], + 'revisal': ['revisal', 'virales'], + 'revise': ['revise', 'siever'], + 'revised': ['deviser', 'diverse', 'revised'], + 'reviser': ['reversi', 'reviser'], + 'revision': ['revision', 'visioner'], + 'revisit': ['revisit', 'visiter'], + 'revisitant': ['revisitant', 'transitive'], + 'revitalization': ['relativization', 'revitalization'], + 'revitalize': ['relativize', 'revitalize'], + 'revocation': ['overaction', 'revocation'], + 'revocative': ['overactive', 'revocative'], + 'revoke': ['evoker', 'revoke'], + 'revolting': ['overglint', 'revolting'], + 'revolute': ['revolute', 'truelove'], + 'revolve': ['evolver', 'revolve'], + 'revomit': ['revomit', 'vomiter'], + 'revote': ['revote', 'vetoer'], + 'revuist': ['revuist', 'stuiver'], + 'rewade': ['drawee', 'rewade'], + 'rewager': ['rewager', 'wagerer'], + 'rewake': ['kerewa', 'rewake'], + 'rewaken': ['rewaken', 'wakener'], + 'rewall': ['rewall', 'waller'], + 'rewallow': ['rewallow', 'wallower'], + 'reward': ['drawer', 'redraw', 'reward', 'warder'], + 'rewarder': ['redrawer', 'rewarder', 'warderer'], + 'rewarm': ['rewarm', 'warmer'], + 'rewarn': ['rewarn', 'warner', 'warren'], + 'rewash': ['hawser', 'rewash', 'washer'], + 'rewater': ['rewater', 'waterer'], + 'rewave': ['rewave', 'weaver'], + 'rewax': ['rewax', 'waxer'], + 'reweaken': ['reweaken', 'weakener'], + 'rewear': ['rewear', 'warree', 'wearer'], + 'rewed': ['dewer', 'ewder', 'rewed'], + 'reweigh': ['reweigh', 'weigher'], + 'reweld': ['reweld', 'welder'], + 'rewet': ['rewet', 'tewer', 'twere'], + 'rewhirl': ['rewhirl', 'whirler'], + 'rewhisper': ['rewhisper', 'whisperer'], + 'rewhiten': ['rewhiten', 'whitener'], + 'rewiden': ['rewiden', 'widener'], + 'rewin': ['erwin', 'rewin', 'winer'], + 'rewind': ['rewind', 'winder'], + 'rewish': ['rewish', 'wisher'], + 'rewithdraw': ['rewithdraw', 'withdrawer'], + 'reword': ['reword', 'worder'], + 'rework': ['rework', 'worker'], + 'reworked': ['reedwork', 'reworked'], + 'rewound': ['rewound', 'unrowed', 'wounder'], + 'rewoven': ['overnew', 'rewoven'], + 'rewrap': ['prewar', 'rewrap', 'warper'], + 'reyield': ['reedily', 'reyield', 'yielder'], + 'rhacianectes': ['rachianectes', 'rhacianectes'], + 'rhaetian': ['earthian', 'rhaetian'], + 'rhaetic': ['certhia', 'rhaetic', 'theriac'], + 'rhamnose': ['horseman', 'rhamnose', 'shoreman'], + 'rhamnoside': ['admonisher', 'rhamnoside'], + 'rhapis': ['parish', 'raphis', 'rhapis'], + 'rhapontic': ['anthropic', 'rhapontic'], + 'rhaponticin': ['panornithic', 'rhaponticin'], + 'rhason': ['rhason', 'sharon', 'shoran'], + 'rhatania': ['ratanhia', 'rhatania'], + 'rhe': ['her', 'reh', 'rhe'], + 'rhea': ['hare', 'hear', 'rhea'], + 'rheen': ['herne', 'rheen'], + 'rheic': ['cheir', 'rheic'], + 'rhein': ['hiren', 'rhein', 'rhine'], + 'rheinic': ['hircine', 'rheinic'], + 'rhema': ['harem', 'herma', 'rhema'], + 'rhematic': ['athermic', 'marchite', 'rhematic'], + 'rheme': ['herem', 'rheme'], + 'rhemist': ['rhemist', 'smither'], + 'rhenium': ['inhumer', 'rhenium'], + 'rheometric': ['chirometer', 'rheometric'], + 'rheophile': ['herophile', 'rheophile'], + 'rheoscope': ['prechoose', 'rheoscope'], + 'rheostatic': ['choristate', 'rheostatic'], + 'rheotactic': ['rheotactic', 'theocratic'], + 'rheotan': ['another', 'athenor', 'rheotan'], + 'rheotropic': ['horopteric', 'rheotropic', 'trichopore'], + 'rhesian': ['arshine', 'nearish', 'rhesian', 'sherani'], + 'rhesus': ['rhesus', 'suresh'], + 'rhetor': ['rhetor', 'rother'], + 'rhetoricals': ['rhetoricals', 'trochlearis'], + 'rhetorize': ['rhetorize', 'theorizer'], + 'rheumatic': ['hematuric', 'rheumatic'], + 'rhine': ['hiren', 'rhein', 'rhine'], + 'rhinestone': ['neornithes', 'rhinestone'], + 'rhineura': ['rhineura', 'unhairer'], + 'rhinocele': ['cholerine', 'rhinocele'], + 'rhinopharyngitis': ['pharyngorhinitis', 'rhinopharyngitis'], + 'rhipidate': ['rhipidate', 'thripidae'], + 'rhizoctonia': ['chorization', 'rhizoctonia', 'zonotrichia'], + 'rhoda': ['hoard', 'rhoda'], + 'rhodaline': ['hodiernal', 'rhodaline'], + 'rhodanthe': ['rhodanthe', 'thornhead'], + 'rhodeose': ['rhodeose', 'seerhood'], + 'rhodes': ['dehors', 'rhodes', 'shoder', 'shored'], + 'rhodic': ['orchid', 'rhodic'], + 'rhodite': ['rhodite', 'theroid'], + 'rhodium': ['humidor', 'rhodium'], + 'rhodope': ['redhoop', 'rhodope'], + 'rhodopsin': ['donorship', 'rhodopsin'], + 'rhoecus': ['choreus', 'chouser', 'rhoecus'], + 'rhopalic': ['orphical', 'rhopalic'], + 'rhus': ['rhus', 'rush'], + 'rhynchotal': ['chloranthy', 'rhynchotal'], + 'rhyton': ['rhyton', 'thorny'], + 'ria': ['air', 'ira', 'ria'], + 'rial': ['aril', 'lair', 'lari', 'liar', 'lira', 'rail', 'rial'], + 'riancy': ['cairny', 'riancy'], + 'riant': ['riant', 'tairn', 'tarin', 'train'], + 'riata': ['arati', 'atria', 'riata', 'tarai', 'tiara'], + 'ribald': ['bildar', 'bridal', 'ribald'], + 'ribaldly': ['bridally', 'ribaldly'], + 'riband': ['brandi', 'riband'], + 'ribat': ['barit', 'ribat'], + 'ribbed': ['dibber', 'ribbed'], + 'ribber': ['briber', 'ribber'], + 'ribble': ['libber', 'ribble'], + 'ribbon': ['ribbon', 'robbin'], + 'ribe': ['beri', 'bier', 'brei', 'ribe'], + 'ribes': ['birse', 'ribes'], + 'riblet': ['beltir', 'riblet'], + 'ribroast': ['arborist', 'ribroast'], + 'ribspare': ['ribspare', 'sparerib'], + 'rice': ['eric', 'rice'], + 'ricer': ['crier', 'ricer'], + 'ricey': ['criey', 'ricey'], + 'richardia': ['charadrii', 'richardia'], + 'richdom': ['chromid', 'richdom'], + 'richen': ['enrich', 'nicher', 'richen'], + 'riches': ['riches', 'shicer'], + 'richt': ['crith', 'richt'], + 'ricine': ['irenic', 'ricine'], + 'ricinoleate': ['arenicolite', 'ricinoleate'], + 'rickets': ['rickets', 'sticker'], + 'rickle': ['licker', 'relick', 'rickle'], + 'rictal': ['citral', 'rictal'], + 'rictus': ['citrus', 'curtis', 'rictus', 'rustic'], + 'ridable': ['bedrail', 'bridale', 'ridable'], + 'ridably': ['bardily', 'rabidly', 'ridably'], + 'riddam': ['madrid', 'riddam'], + 'riddance': ['adendric', 'riddance'], + 'riddel': ['lidder', 'riddel', 'riddle'], + 'ridden': ['dinder', 'ridden', 'rinded'], + 'riddle': ['lidder', 'riddel', 'riddle'], + 'ride': ['dier', 'dire', 'reid', 'ride'], + 'rideau': ['auride', 'rideau'], + 'riden': ['diner', 'riden', 'rinde'], + 'rident': ['dirten', 'rident', 'tinder'], + 'rider': ['drier', 'rider'], + 'ridered': ['deirdre', 'derider', 'derride', 'ridered'], + 'ridge': ['dirge', 'gride', 'redig', 'ridge'], + 'ridgel': ['gilder', 'girdle', 'glider', 'regild', 'ridgel'], + 'ridgelike': ['dirgelike', 'ridgelike'], + 'ridger': ['girder', 'ridger'], + 'ridging': ['girding', 'ridging'], + 'ridgingly': ['girdingly', 'ridgingly'], + 'ridgling': ['girdling', 'ridgling'], + 'ridgy': ['igdyr', 'ridgy'], + 'rie': ['ire', 'rie'], + 'riem': ['emir', 'imer', 'mire', 'reim', 'remi', 'riem', 'rime'], + 'rife': ['fire', 'reif', 'rife'], + 'rifeness': ['finesser', 'rifeness'], + 'rifle': ['filer', 'flier', 'lifer', 'rifle'], + 'rifleman': ['inflamer', 'rifleman'], + 'rift': ['frit', 'rift'], + 'rigadoon': ['gordonia', 'organoid', 'rigadoon'], + 'rigation': ['rigation', 'trigonia'], + 'rigbane': ['bearing', 'begrain', 'brainge', 'rigbane'], + 'right': ['girth', 'grith', 'right'], + 'rightle': ['lighter', 'relight', 'rightle'], + 'rigling': ['girling', 'rigling'], + 'rigolette': ['gloriette', 'rigolette'], + 'rik': ['irk', 'rik'], + 'rikisha': ['rikisha', 'shikari'], + 'rikk': ['kirk', 'rikk'], + 'riksha': ['rakish', 'riksha', 'shikar', 'shikra', 'sikhra'], + 'rile': ['lier', 'lire', 'rile'], + 'rillet': ['retill', 'rillet', 'tiller'], + 'rillett': ['rillett', 'trillet'], + 'rillock': ['rillock', 'rollick'], + 'rim': ['mir', 'rim'], + 'rima': ['amir', 'irma', 'mari', 'mira', 'rami', 'rima'], + 'rimal': ['armil', 'marli', 'rimal'], + 'rimate': ['imaret', 'metria', 'mirate', 'rimate'], + 'rime': ['emir', 'imer', 'mire', 'reim', 'remi', 'riem', 'rime'], + 'rimmed': ['dimmer', 'immerd', 'rimmed'], + 'rimose': ['isomer', 'rimose'], + 'rimple': ['limper', 'prelim', 'rimple'], + 'rimu': ['muir', 'rimu'], + 'rimula': ['rimula', 'uramil'], + 'rimy': ['miry', 'rimy', 'yirm'], + 'rinaldo': ['nailrod', 'ordinal', 'rinaldo', 'rodinal'], + 'rinceau': ['aneuric', 'rinceau'], + 'rincon': ['cornin', 'rincon'], + 'rinde': ['diner', 'riden', 'rinde'], + 'rinded': ['dinder', 'ridden', 'rinded'], + 'rindle': ['linder', 'rindle'], + 'rine': ['neri', 'rein', 'rine'], + 'ring': ['girn', 'grin', 'ring'], + 'ringable': ['balinger', 'ringable'], + 'ringe': ['grein', 'inger', 'nigre', 'regin', 'reign', 'ringe'], + 'ringed': ['engird', 'ringed'], + 'ringer': ['erring', 'rering', 'ringer'], + 'ringgoer': ['gorgerin', 'ringgoer'], + 'ringhead': ['headring', 'ringhead'], + 'ringite': ['igniter', 'ringite', 'tigrine'], + 'ringle': ['linger', 'ringle'], + 'ringlead': ['dragline', 'reginald', 'ringlead'], + 'ringlet': ['ringlet', 'tingler', 'tringle'], + 'ringster': ['restring', 'ringster', 'stringer'], + 'ringtail': ['ringtail', 'trailing'], + 'ringy': ['girny', 'ringy'], + 'rink': ['kirn', 'rink'], + 'rinka': ['inkra', 'krina', 'nakir', 'rinka'], + 'rinse': ['reins', 'resin', 'rinse', 'risen', 'serin', 'siren'], + 'rio': ['rio', 'roi'], + 'riot': ['riot', 'roit', 'trio'], + 'rioting': ['ignitor', 'rioting'], + 'rip': ['pir', 'rip'], + 'ripa': ['pair', 'pari', 'pria', 'ripa'], + 'ripal': ['april', 'pilar', 'ripal'], + 'ripe': ['peri', 'pier', 'ripe'], + 'ripelike': ['pierlike', 'ripelike'], + 'ripen': ['piner', 'prine', 'repin', 'ripen'], + 'ripener': ['repiner', 'ripener'], + 'ripeningly': ['repiningly', 'ripeningly'], + 'riper': ['prier', 'riper'], + 'ripgut': ['ripgut', 'upgirt'], + 'ripost': ['ripost', 'triops', 'tripos'], + 'riposte': ['periost', 'porites', 'reposit', 'riposte'], + 'rippet': ['rippet', 'tipper'], + 'ripple': ['lipper', 'ripple'], + 'ripplet': ['ripplet', 'tippler', 'tripple'], + 'ripup': ['ripup', 'uprip'], + 'rise': ['reis', 'rise', 'seri', 'sier', 'sire'], + 'risen': ['reins', 'resin', 'rinse', 'risen', 'serin', 'siren'], + 'rishi': ['irish', 'rishi', 'sirih'], + 'risk': ['kris', 'risk'], + 'risky': ['risky', 'sirky'], + 'risper': ['risper', 'sprier'], + 'risque': ['risque', 'squire'], + 'risquee': ['esquire', 'risquee'], + 'rissel': ['rissel', 'rissle'], + 'rissle': ['rissel', 'rissle'], + 'rissoa': ['aissor', 'rissoa'], + 'rist': ['rist', 'stir'], + 'rit': ['rit', 'tri'], + 'rita': ['airt', 'rita', 'tari', 'tiar'], + 'rite': ['iter', 'reit', 'rite', 'teri', 'tier', 'tire'], + 'riteless': ['riteless', 'tireless'], + 'ritelessness': ['ritelessness', 'tirelessness'], + 'ritling': ['glitnir', 'ritling'], + 'ritualize': ['ritualize', 'uralitize'], + 'riva': ['ravi', 'riva', 'vair', 'vari', 'vira'], + 'rivage': ['argive', 'rivage'], + 'rival': ['rival', 'viral'], + 'rive': ['rive', 'veri', 'vier', 'vire'], + 'rivel': ['levir', 'liver', 'livre', 'rivel'], + 'riven': ['riven', 'viner'], + 'rivered': ['deriver', 'redrive', 'rivered'], + 'rivet': ['rivet', 'tirve', 'tiver'], + 'riveter': ['rerivet', 'riveter'], + 'rivetless': ['rivetless', 'silvester'], + 'riving': ['irving', 'riving', 'virgin'], + 'rivingly': ['rivingly', 'virginly'], + 'rivose': ['rivose', 'virose'], + 'riyal': ['lairy', 'riyal'], + 'ro': ['or', 'ro'], + 'roach': ['achor', 'chora', 'corah', 'orach', 'roach'], + 'road': ['dora', 'orad', 'road'], + 'roadability': ['adorability', 'roadability'], + 'roadable': ['adorable', 'roadable'], + 'roader': ['adorer', 'roader'], + 'roading': ['gordian', 'idorgan', 'roading'], + 'roadite': ['roadite', 'toadier'], + 'roadman': ['anadrom', 'madrona', 'mandora', 'monarda', 'roadman'], + 'roadster': ['dartrose', 'roadster'], + 'roam': ['amor', 'maro', 'mora', 'omar', 'roam'], + 'roamage': ['georama', 'roamage'], + 'roamer': ['remora', 'roamer'], + 'roaming': ['ingomar', 'moringa', 'roaming'], + 'roan': ['nora', 'orna', 'roan'], + 'roast': ['astor', 'roast'], + 'roastable': ['astrolabe', 'roastable'], + 'roasting': ['orangist', 'organist', 'roasting', 'signator'], + 'rob': ['bor', 'orb', 'rob'], + 'robalo': ['barolo', 'robalo'], + 'roband': ['bandor', 'bondar', 'roband'], + 'robbin': ['ribbon', 'robbin'], + 'robe': ['boer', 'bore', 'robe'], + 'rober': ['borer', 'rerob', 'rober'], + 'roberd': ['border', 'roberd'], + 'roberta': ['arboret', 'roberta', 'taborer'], + 'robin': ['biron', 'inorb', 'robin'], + 'robinet': ['bornite', 'robinet'], + 'robing': ['boring', 'robing'], + 'roble': ['blore', 'roble'], + 'robot': ['boort', 'robot'], + 'robotian': ['abortion', 'robotian'], + 'robotism': ['bimotors', 'robotism'], + 'robur': ['burro', 'robur', 'rubor'], + 'roc': ['cor', 'cro', 'orc', 'roc'], + 'rochea': ['chorea', 'ochrea', 'rochea'], + 'rochet': ['hector', 'rochet', 'tocher', 'troche'], + 'rock': ['cork', 'rock'], + 'rocker': ['corker', 'recork', 'rocker'], + 'rocketer': ['rocketer', 'rocktree'], + 'rockiness': ['corkiness', 'rockiness'], + 'rocking': ['corking', 'rocking'], + 'rockish': ['corkish', 'rockish'], + 'rocktree': ['rocketer', 'rocktree'], + 'rockwood': ['corkwood', 'rockwood', 'woodrock'], + 'rocky': ['corky', 'rocky'], + 'rocta': ['actor', 'corta', 'croat', 'rocta', 'taroc', 'troca'], + 'rod': ['dor', 'rod'], + 'rode': ['doer', 'redo', 'rode', 'roed'], + 'rodentia': ['andorite', 'nadorite', 'ordinate', 'rodentia'], + 'rodential': ['lorandite', 'rodential'], + 'rodinal': ['nailrod', 'ordinal', 'rinaldo', 'rodinal'], + 'rodingite': ['negritoid', 'rodingite'], + 'rodless': ['drossel', 'rodless'], + 'rodlet': ['retold', 'rodlet'], + 'rodman': ['random', 'rodman'], + 'rodney': ['rodney', 'yonder'], + 'roe': ['oer', 'ore', 'roe'], + 'roed': ['doer', 'redo', 'rode', 'roed'], + 'roey': ['oyer', 'roey', 'yore'], + 'rog': ['gor', 'rog'], + 'rogan': ['angor', + 'argon', + 'goran', + 'grano', + 'groan', + 'nagor', + 'orang', + 'organ', + 'rogan', + 'ronga'], + 'rogative': ['ravigote', 'rogative'], + 'roger': ['gorer', 'roger'], + 'roggle': ['logger', 'roggle'], + 'rogue': ['orgue', 'rogue', 'rouge'], + 'rohan': ['nahor', 'norah', 'rohan'], + 'rohob': ['bohor', 'rohob'], + 'rohun': ['huron', 'rohun'], + 'roi': ['rio', 'roi'], + 'roid': ['dori', 'roid'], + 'roil': ['loir', 'lori', 'roil'], + 'roister': ['roister', 'storier'], + 'roit': ['riot', 'roit', 'trio'], + 'rok': ['kor', 'rok'], + 'roka': ['karo', 'kora', 'okra', 'roka'], + 'roke': ['kore', 'roke'], + 'rokey': ['rokey', 'yoker'], + 'roky': ['kory', 'roky', 'york'], + 'roland': ['androl', 'arnold', 'lardon', 'roland', 'ronald'], + 'rolandic': ['ironclad', 'rolandic'], + 'role': ['lore', 'orle', 'role'], + 'rolfe': ['forel', 'rolfe'], + 'roller': ['reroll', 'roller'], + 'rollick': ['rillock', 'rollick'], + 'romaean': ['neorama', 'romaean'], + 'romain': ['marion', 'romain'], + 'romaine': ['moraine', 'romaine'], + 'romal': ['molar', 'moral', 'romal'], + 'roman': ['manor', 'moran', 'norma', 'ramon', 'roman'], + 'romancist': ['narcotism', 'romancist'], + 'romancy': ['acronym', 'romancy'], + 'romandom': ['monodram', 'romandom'], + 'romane': ['enamor', 'monera', 'oreman', 'romane'], + 'romanes': ['masoner', 'romanes'], + 'romanian': ['maronian', 'romanian'], + 'romanic': ['amicron', 'marconi', 'minorca', 'romanic'], + 'romanist': ['maronist', 'romanist'], + 'romanistic': ['marcionist', 'romanistic'], + 'romanite': ['maronite', 'martinoe', 'minorate', 'morenita', 'romanite'], + 'romanity': ['minatory', 'romanity'], + 'romanly': ['almonry', 'romanly'], + 'romantic': ['macrotin', 'romantic'], + 'romanticly': ['matrocliny', 'romanticly'], + 'romantism': ['matronism', 'romantism'], + 'rome': ['mero', 'more', 'omer', 'rome'], + 'romeite': ['moieter', 'romeite'], + 'romeo': ['moore', 'romeo'], + 'romero': ['romero', 'roomer'], + 'romeshot': ['resmooth', 'romeshot', 'smoother'], + 'romeward': ['marrowed', 'romeward'], + 'romic': ['micro', 'moric', 'romic'], + 'romish': ['hirmos', 'romish'], + 'rompish': ['orphism', 'rompish'], + 'ron': ['nor', 'ron'], + 'ronald': ['androl', 'arnold', 'lardon', 'roland', 'ronald'], + 'roncet': ['conter', 'cornet', 'cronet', 'roncet'], + 'ronco': ['conor', 'croon', 'ronco'], + 'rond': ['dorn', 'rond'], + 'rondache': ['anchored', 'rondache'], + 'ronde': ['drone', 'ronde'], + 'rondeau': ['rondeau', 'unoared'], + 'rondel': ['rondel', 'rondle'], + 'rondelet': ['redolent', 'rondelet'], + 'rondeletia': ['delineator', 'rondeletia'], + 'rondelle': ['enrolled', 'rondelle'], + 'rondle': ['rondel', 'rondle'], + 'rondo': ['donor', 'rondo'], + 'rondure': ['rondure', 'rounder', 'unorder'], + 'rone': ['oner', 'rone'], + 'ronga': ['angor', + 'argon', + 'goran', + 'grano', + 'groan', + 'nagor', + 'orang', + 'organ', + 'rogan', + 'ronga'], + 'rood': ['door', 'odor', 'oord', 'rood'], + 'roodstone': ['doorstone', 'roodstone'], + 'roofer': ['reroof', 'roofer'], + 'rooflet': ['footler', 'rooflet'], + 'rook': ['kroo', 'rook'], + 'rooker': ['korero', 'rooker'], + 'rool': ['loro', 'olor', 'orlo', 'rool'], + 'room': ['moor', 'moro', 'room'], + 'roomage': ['moorage', 'roomage'], + 'roomed': ['doomer', 'mooder', 'redoom', 'roomed'], + 'roomer': ['romero', 'roomer'], + 'roomlet': ['roomlet', 'tremolo'], + 'roomstead': ['astrodome', 'roomstead'], + 'roomward': ['roomward', 'wardroom'], + 'roomy': ['moory', 'roomy'], + 'roost': ['roost', 'torso'], + 'root': ['root', 'roto', 'toro'], + 'rooter': ['reroot', 'rooter', 'torero'], + 'rootle': ['looter', 'retool', 'rootle', 'tooler'], + 'rootlet': ['rootlet', 'tootler'], + 'rootworm': ['moorwort', 'rootworm', 'tomorrow', 'wormroot'], + 'rope': ['pore', 'rope'], + 'ropeable': ['operable', 'ropeable'], + 'ropelike': ['porelike', 'ropelike'], + 'ropeman': ['manrope', 'ropeman'], + 'roper': ['porer', 'prore', 'roper'], + 'ropes': ['poser', 'prose', 'ropes', 'spore'], + 'ropiness': ['poriness', 'pression', 'ropiness'], + 'roping': ['poring', 'roping'], + 'ropp': ['prop', 'ropp'], + 'ropy': ['pory', 'pyro', 'ropy'], + 'roquet': ['quoter', 'roquet', 'torque'], + 'rosa': ['asor', 'rosa', 'soar', 'sora'], + 'rosabel': ['borlase', 'labrose', 'rosabel'], + 'rosal': ['rosal', 'solar', 'soral'], + 'rosales': ['lassoer', 'oarless', 'rosales'], + 'rosalie': ['rosalie', 'seriola'], + 'rosaniline': ['enaliornis', 'rosaniline'], + 'rosated': ['rosated', 'torsade'], + 'rose': ['eros', 'rose', 'sero', 'sore'], + 'roseal': ['roseal', 'solera'], + 'rosed': ['doser', 'rosed'], + 'rosehead': ['rosehead', 'sorehead'], + 'roseine': ['erinose', 'roseine'], + 'rosel': ['loser', 'orsel', 'rosel', 'soler'], + 'roselite': ['literose', 'roselite', 'tirolese'], + 'roselle': ['orselle', 'roselle'], + 'roseola': ['aerosol', 'roseola'], + 'roset': ['roset', 'rotse', 'soter', 'stero', 'store', 'torse'], + 'rosetan': ['noreast', 'rosetan', 'seatron', 'senator', 'treason'], + 'rosetime': ['rosetime', 'timorese', 'tiresome'], + 'rosetta': ['retoast', 'rosetta', 'stoater', 'toaster'], + 'rosette': ['rosette', 'tetrose'], + 'rosetum': ['oestrum', 'rosetum'], + 'rosety': ['oyster', 'rosety'], + 'rosin': ['ornis', 'rosin'], + 'rosinate': ['arsonite', 'asterion', 'oestrian', 'rosinate', 'serotina'], + 'rosine': ['rosine', 'senior', 'soneri'], + 'rosiness': ['insessor', 'rosiness'], + 'rosmarine': ['morrisean', 'rosmarine'], + 'rosolite': ['oestriol', 'rosolite'], + 'rosorial': ['rosorial', 'sororial'], + 'rossite': ['rossite', 'sorites'], + 'rostel': ['relost', 'reslot', 'rostel', 'sterol', 'torsel'], + 'roster': ['resort', 'roster', 'sorter', 'storer'], + 'rostra': ['rostra', 'sartor'], + 'rostrate': ['rostrate', 'trostera'], + 'rosulate': ['oestrual', 'rosulate'], + 'rosy': ['rosy', 'sory'], + 'rot': ['ort', 'rot', 'tor'], + 'rota': ['rota', 'taro', 'tora'], + 'rotacism': ['acrotism', 'rotacism'], + 'rotal': ['latro', 'rotal', 'toral'], + 'rotala': ['aortal', 'rotala'], + 'rotalian': ['notarial', 'rational', 'rotalian'], + 'rotan': ['orant', 'rotan', 'toran', 'trona'], + 'rotanev': ['rotanev', 'venator'], + 'rotarian': ['rotarian', 'tornaria'], + 'rotate': ['rotate', 'tetrao'], + 'rotch': ['chort', 'rotch', 'torch'], + 'rote': ['rote', 'tore'], + 'rotella': ['reallot', 'rotella', 'tallero'], + 'rotge': ['ergot', 'rotge'], + 'rother': ['rhetor', 'rother'], + 'roto': ['root', 'roto', 'toro'], + 'rotse': ['roset', 'rotse', 'soter', 'stero', 'store', 'torse'], + 'rottan': ['attorn', 'ratton', 'rottan'], + 'rotten': ['rotten', 'terton'], + 'rotter': ['retort', 'retrot', 'rotter'], + 'rottle': ['lotter', 'rottle', 'tolter'], + 'rotula': ['rotula', 'torula'], + 'rotulian': ['rotulian', 'uranotil'], + 'rotuliform': ['rotuliform', 'toruliform'], + 'rotulus': ['rotulus', 'torulus'], + 'rotund': ['rotund', 'untrod'], + 'rotunda': ['rotunda', 'tandour'], + 'rotundate': ['rotundate', 'unrotated'], + 'rotundifoliate': ['rotundifoliate', 'titanofluoride'], + 'rotundo': ['orotund', 'rotundo'], + 'roub': ['buro', 'roub'], + 'roud': ['dour', 'duro', 'ordu', 'roud'], + 'rouge': ['orgue', 'rogue', 'rouge'], + 'rougeot': ['outgoer', 'rougeot'], + 'roughen': ['enrough', 'roughen'], + 'roughie': ['higuero', 'roughie'], + 'rouky': ['rouky', 'yurok'], + 'roulade': ['roulade', 'urodela'], + 'rounce': ['conure', 'rounce', 'uncore'], + 'rounded': ['redound', 'rounded', 'underdo'], + 'roundel': ['durenol', 'lounder', 'roundel'], + 'rounder': ['rondure', 'rounder', 'unorder'], + 'roundhead': ['roundhead', 'unhoarded'], + 'roundseam': ['meandrous', 'roundseam'], + 'roundup': ['roundup', 'unproud'], + 'roup': ['pour', 'roup'], + 'rouper': ['pourer', 'repour', 'rouper'], + 'roupet': ['pouter', 'roupet', 'troupe'], + 'rousedness': ['rousedness', 'souredness'], + 'rouser': ['rouser', 'sourer'], + 'rousing': ['nigrous', 'rousing', 'souring'], + 'rousseau': ['eosaurus', 'rousseau'], + 'roust': ['roust', 'rusot', 'stour', 'sutor', 'torus'], + 'rouster': ['rouster', 'trouser'], + 'rousting': ['rousting', 'stouring'], + 'rout': ['rout', 'toru', 'tour'], + 'route': ['outer', 'outre', 'route'], + 'router': ['retour', 'router', 'tourer'], + 'routh': ['routh', 'throu'], + 'routhie': ['outhire', 'routhie'], + 'routine': ['routine', 'tueiron'], + 'routing': ['outgrin', 'outring', 'routing', 'touring'], + 'routinist': ['introitus', 'routinist'], + 'rove': ['over', 'rove'], + 'rovet': ['overt', 'rovet', 'torve', 'trove', 'voter'], + 'row': ['row', 'wro'], + 'rowdily': ['rowdily', 'wordily'], + 'rowdiness': ['rowdiness', 'wordiness'], + 'rowdy': ['dowry', 'rowdy', 'wordy'], + 'rowed': ['dower', 'rowed'], + 'rowel': ['lower', 'owler', 'rowel'], + 'rowelhead': ['rowelhead', 'wheelroad'], + 'rowen': ['owner', 'reown', 'rowen'], + 'rower': ['rerow', 'rower'], + 'rowet': ['rowet', 'tower', 'wrote'], + 'rowing': ['ingrow', 'rowing'], + 'rowlet': ['rowlet', 'trowel', 'wolter'], + 'rowley': ['lowery', 'owlery', 'rowley', 'yowler'], + 'roxy': ['oryx', 'roxy'], + 'roy': ['ory', 'roy', 'yor'], + 'royalist': ['royalist', 'solitary'], + 'royet': ['royet', 'toyer'], + 'royt': ['royt', 'ryot', 'tory', 'troy', 'tyro'], + 'rua': ['aru', 'rua', 'ura'], + 'ruana': ['anura', 'ruana'], + 'rub': ['bur', 'rub'], + 'rubasse': ['rubasse', 'surbase'], + 'rubato': ['outbar', 'rubato', 'tabour'], + 'rubbed': ['dubber', 'rubbed'], + 'rubble': ['burble', 'lubber', 'rubble'], + 'rubbler': ['burbler', 'rubbler'], + 'rubbly': ['burbly', 'rubbly'], + 'rube': ['bure', 'reub', 'rube'], + 'rubella': ['rubella', 'rulable'], + 'rubescent': ['rubescent', 'subcenter'], + 'rubiate': ['abiuret', 'aubrite', 'biurate', 'rubiate'], + 'rubiator': ['rubiator', 'torrubia'], + 'rubican': ['brucina', 'rubican'], + 'rubied': ['burdie', 'buried', 'rubied'], + 'rubification': ['rubification', 'urbification'], + 'rubify': ['rubify', 'urbify'], + 'rubine': ['burnie', 'rubine'], + 'ruble': ['bluer', 'brule', 'burel', 'ruble'], + 'rubor': ['burro', 'robur', 'rubor'], + 'rubrical': ['bicrural', 'rubrical'], + 'ruby': ['bury', 'ruby'], + 'ructation': ['anticourt', 'curtation', 'ructation'], + 'ruction': ['courtin', 'ruction'], + 'rud': ['rud', 'urd'], + 'rudas': ['rudas', 'sudra'], + 'ruddle': ['dudler', 'ruddle'], + 'rude': ['duer', 'dure', 'rude', 'urde'], + 'rudish': ['hurdis', 'rudish'], + 'rudista': ['dasturi', 'rudista'], + 'rudity': ['durity', 'rudity'], + 'rue': ['rue', 'ure'], + 'ruen': ['renu', 'ruen', 'rune'], + 'ruffed': ['duffer', 'ruffed'], + 'rufter': ['returf', 'rufter'], + 'rug': ['gur', 'rug'], + 'ruga': ['gaur', 'guar', 'ruga'], + 'rugate': ['argute', 'guetar', 'rugate', 'tuareg'], + 'rugged': ['grudge', 'rugged'], + 'ruggle': ['gurgle', 'lugger', 'ruggle'], + 'rugose': ['grouse', 'rugose'], + 'ruinate': ['ruinate', 'taurine', 'uranite', 'urinate'], + 'ruination': ['ruination', 'urination'], + 'ruinator': ['ruinator', 'urinator'], + 'ruined': ['diurne', 'inured', 'ruined', 'unride'], + 'ruing': ['irgun', 'ruing', 'unrig'], + 'ruinous': ['ruinous', 'urinous'], + 'ruinousness': ['ruinousness', 'urinousness'], + 'rulable': ['rubella', 'rulable'], + 'rule': ['lure', 'rule'], + 'ruledom': ['remould', 'ruledom'], + 'ruler': ['lurer', 'ruler'], + 'ruling': ['ruling', 'urling'], + 'rulingly': ['luringly', 'rulingly'], + 'rum': ['mru', 'rum'], + 'rumal': ['mural', 'rumal'], + 'ruman': ['muran', 'ruman', 'unarm', 'unram', 'urman'], + 'rumble': ['lumber', 'rumble', 'umbrel'], + 'rumelian': ['lemurian', 'malurine', 'rumelian'], + 'rumex': ['murex', 'rumex'], + 'ruminant': ['nutramin', 'ruminant'], + 'ruminator': ['antirumor', 'ruminator'], + 'rumly': ['murly', 'rumly'], + 'rumple': ['lumper', 'plumer', 'replum', 'rumple'], + 'run': ['run', 'urn'], + 'runback': ['backrun', 'runback'], + 'runby': ['burny', 'runby'], + 'runch': ['churn', 'runch'], + 'runcinate': ['encurtain', 'runcinate', 'uncertain'], + 'rundale': ['launder', 'rundale'], + 'rundi': ['rundi', 'unrid'], + 'rundlet': ['rundlet', 'trundle'], + 'rune': ['renu', 'ruen', 'rune'], + 'runed': ['runed', 'under', 'unred'], + 'runer': ['rerun', 'runer'], + 'runfish': ['furnish', 'runfish'], + 'rung': ['grun', 'rung'], + 'runic': ['curin', 'incur', 'runic'], + 'runically': ['runically', 'unlyrical'], + 'runite': ['runite', 'triune', 'uniter', 'untire'], + 'runkly': ['knurly', 'runkly'], + 'runlet': ['runlet', 'turnel'], + 'runnet': ['runnet', 'tunner', 'unrent'], + 'runout': ['outrun', 'runout'], + 'runover': ['overrun', 'runover'], + 'runt': ['runt', 'trun', 'turn'], + 'runted': ['runted', 'tunder', 'turned'], + 'runtee': ['neuter', 'retune', 'runtee', 'tenure', 'tureen'], + 'runway': ['runway', 'unwary'], + 'rupa': ['prau', 'rupa'], + 'rupee': ['puree', 'rupee'], + 'rupestrian': ['rupestrian', 'supertrain'], + 'rupiah': ['hairup', 'rupiah'], + 'rural': ['rural', 'urlar'], + 'rus': ['rus', 'sur', 'urs'], + 'rusa': ['rusa', 'saur', 'sura', 'ursa', 'usar'], + 'ruscus': ['cursus', 'ruscus'], + 'ruse': ['ruse', 'suer', 'sure', 'user'], + 'rush': ['rhus', 'rush'], + 'rushen': ['reshun', 'rushen'], + 'rusine': ['insure', 'rusine', 'ursine'], + 'rusma': ['musar', 'ramus', 'rusma', 'surma'], + 'rusot': ['roust', 'rusot', 'stour', 'sutor', 'torus'], + 'russelia': ['russelia', 'siruelas'], + 'russet': ['russet', 'tusser'], + 'russify': ['fissury', 'russify'], + 'russine': ['russine', 'serinus', 'sunrise'], + 'rustable': ['baluster', 'rustable'], + 'rustic': ['citrus', 'curtis', 'rictus', 'rustic'], + 'rusticial': ['curialist', 'rusticial'], + 'rusticly': ['crustily', 'rusticly'], + 'rusticness': ['crustiness', 'rusticness'], + 'rustle': ['luster', 'result', 'rustle', 'sutler', 'ulster'], + 'rustling': ['lustring', 'rustling'], + 'rustly': ['rustly', 'sultry'], + 'rut': ['rut', 'tur'], + 'ruta': ['ruta', 'taur'], + 'rutch': ['cruth', 'rutch'], + 'rutelian': ['lutrinae', 'retinula', 'rutelian', 'tenurial'], + 'rutelinae': ['lineature', 'rutelinae'], + 'ruth': ['hurt', 'ruth'], + 'ruthenian': ['hunterian', 'ruthenian'], + 'ruther': ['hurter', 'ruther'], + 'ruthful': ['hurtful', 'ruthful'], + 'ruthfully': ['hurtfully', 'ruthfully'], + 'ruthfulness': ['hurtfulness', 'ruthfulness'], + 'ruthless': ['hurtless', 'ruthless'], + 'ruthlessly': ['hurtlessly', 'ruthlessly'], + 'ruthlessness': ['hurtlessness', 'ruthlessness'], + 'rutilant': ['rutilant', 'turntail'], + 'rutinose': ['rutinose', 'tursenoi'], + 'rutter': ['rutter', 'turret'], + 'rutyl': ['rutyl', 'truly'], + 'rutylene': ['neuterly', 'rutylene'], + 'ryal': ['aryl', 'lyra', 'ryal', 'yarl'], + 'ryder': ['derry', 'redry', 'ryder'], + 'rye': ['rye', 'yer'], + 'ryen': ['ryen', 'yern'], + 'ryot': ['royt', 'ryot', 'tory', 'troy', 'tyro'], + 'rype': ['prey', 'pyre', 'rype'], + 'rytina': ['rytina', 'trainy', 'tyrian'], + 'sa': ['as', 'sa'], + 'saa': ['asa', 'saa'], + 'saan': ['anas', 'ansa', 'saan'], + 'sab': ['bas', 'sab'], + 'saba': ['abas', 'saba'], + 'sabal': ['balas', 'balsa', 'basal', 'sabal'], + 'saban': ['nasab', 'saban'], + 'sabanut': ['sabanut', 'sabutan', 'tabanus'], + 'sabe': ['base', 'besa', 'sabe', 'seba'], + 'sabeca': ['casabe', 'sabeca'], + 'sabella': ['basella', 'sabella', 'salable'], + 'sabelli': ['sabelli', 'sebilla'], + 'sabellid': ['sabellid', 'slidable'], + 'saber': ['barse', 'besra', 'saber', 'serab'], + 'sabered': ['debaser', 'sabered'], + 'sabian': ['sabian', 'sabina'], + 'sabina': ['sabian', 'sabina'], + 'sabino': ['basion', 'bonsai', 'sabino'], + 'sabir': ['baris', 'sabir'], + 'sable': ['blase', 'sable'], + 'saboraim': ['ambrosia', 'saboraim'], + 'sabot': ['basto', 'boast', 'sabot'], + 'sabotine': ['obeisant', 'sabotine'], + 'sabromin': ['ambrosin', 'barosmin', 'sabromin'], + 'sabulite': ['sabulite', 'suitable'], + 'sabutan': ['sabanut', 'sabutan', 'tabanus'], + 'sacalait': ['castalia', 'sacalait'], + 'saccade': ['cascade', 'saccade'], + 'saccomyian': ['saccomyian', 'saccomyina'], + 'saccomyina': ['saccomyian', 'saccomyina'], + 'sacculoutricular': ['sacculoutricular', 'utriculosaccular'], + 'sacellum': ['camellus', 'sacellum'], + 'sachem': ['sachem', 'schema'], + 'sachet': ['chaste', 'sachet', 'scathe', 'scheat'], + 'sacian': ['ascian', 'sacian', 'scania', 'sicana'], + 'sack': ['cask', 'sack'], + 'sackbut': ['sackbut', 'subtack'], + 'sacken': ['sacken', 'skance'], + 'sacker': ['resack', 'sacker', 'screak'], + 'sacking': ['casking', 'sacking'], + 'sacklike': ['casklike', 'sacklike'], + 'sacque': ['casque', 'sacque'], + 'sacral': ['lascar', 'rascal', 'sacral', 'scalar'], + 'sacrification': ['sacrification', 'scarification'], + 'sacrificator': ['sacrificator', 'scarificator'], + 'sacripant': ['sacripant', 'spartanic'], + 'sacro': ['arcos', 'crosa', 'oscar', 'sacro'], + 'sacrodorsal': ['dorsosacral', 'sacrodorsal'], + 'sacroischiac': ['isosaccharic', 'sacroischiac'], + 'sacrolumbal': ['lumbosacral', 'sacrolumbal'], + 'sacrovertebral': ['sacrovertebral', 'vertebrosacral'], + 'sad': ['das', 'sad'], + 'sadden': ['desand', 'sadden', 'sanded'], + 'saddling': ['addlings', 'saddling'], + 'sadh': ['dash', 'sadh', 'shad'], + 'sadhe': ['deash', 'hades', 'sadhe', 'shade'], + 'sadic': ['asdic', 'sadic'], + 'sadie': ['aides', 'aside', 'sadie'], + 'sadiron': ['sadiron', 'sardoin'], + 'sado': ['dosa', 'sado', 'soda'], + 'sadr': ['sadr', 'sard'], + 'saeima': ['asemia', 'saeima'], + 'saernaite': ['arseniate', 'saernaite'], + 'saeter': ['asteer', + 'easter', + 'eastre', + 'reseat', + 'saeter', + 'seater', + 'staree', + 'teaser', + 'teresa'], + 'saeume': ['amusee', 'saeume'], + 'safar': ['safar', 'saraf'], + 'safely': ['fayles', 'safely'], + 'saft': ['fast', 'saft'], + 'sag': ['gas', 'sag'], + 'sagai': ['sagai', 'saiga'], + 'sagene': ['sagene', 'senega'], + 'sagger': ['sagger', 'seggar'], + 'sagless': ['gasless', 'glasses', 'sagless'], + 'sago': ['sago', 'soga'], + 'sagoin': ['gosain', 'isagon', 'sagoin'], + 'sagra': ['argas', 'sagra'], + 'sah': ['ash', 'sah', 'sha'], + 'saharic': ['arachis', 'asiarch', 'saharic'], + 'sahh': ['hash', 'sahh', 'shah'], + 'sahidic': ['hasidic', 'sahidic'], + 'sahme': ['sahme', 'shame'], + 'saho': ['saho', 'shoa'], + 'sai': ['sai', 'sia'], + 'saic': ['acis', 'asci', 'saic'], + 'said': ['dais', 'dasi', 'disa', 'said', 'sida'], + 'saidi': ['saidi', 'saiid'], + 'saiga': ['sagai', 'saiga'], + 'saiid': ['saidi', 'saiid'], + 'sail': ['lasi', 'lias', 'lisa', 'sail', 'sial'], + 'sailable': ['isabella', 'sailable'], + 'sailage': ['algesia', 'sailage'], + 'sailed': ['aisled', 'deasil', 'ladies', 'sailed'], + 'sailer': ['israel', 'relais', 'resail', 'sailer', 'serail', 'serial'], + 'sailing': ['aisling', 'sailing'], + 'sailoring': ['sailoring', 'signorial'], + 'sailsman': ['nasalism', 'sailsman'], + 'saily': ['islay', 'saily'], + 'saim': ['mias', 'saim', 'siam', 'sima'], + 'sain': ['anis', 'nais', 'nasi', 'nias', 'sain', 'sina'], + 'sainfoin': ['sainfoin', 'sinfonia'], + 'saint': ['saint', 'satin', 'stain'], + 'saintdom': ['donatism', 'saintdom'], + 'sainted': ['destain', 'instead', 'sainted', 'satined'], + 'saintless': ['saintless', 'saltiness', 'slatiness', 'stainless'], + 'saintlike': ['kleistian', 'saintlike', 'satinlike'], + 'saintly': ['nastily', 'saintly', 'staynil'], + 'saintship': ['hispanist', 'saintship'], + 'saip': ['apis', 'pais', 'pasi', 'saip'], + 'saiph': ['aphis', 'apish', 'hispa', 'saiph', 'spahi'], + 'sair': ['rais', 'sair', 'sari'], + 'saite': ['saite', 'taise'], + 'saithe': ['saithe', 'tashie', 'teaish'], + 'saitic': ['isatic', 'saitic'], + 'saivism': ['saivism', 'sivaism'], + 'sak': ['ask', 'sak'], + 'saka': ['asak', 'kasa', 'saka'], + 'sake': ['sake', 'seak'], + 'sakeen': ['sakeen', 'sekane'], + 'sakel': ['alkes', 'sakel', 'slake'], + 'saker': ['asker', 'reask', 'saker', 'sekar'], + 'sakeret': ['restake', 'sakeret'], + 'sakha': ['kasha', 'khasa', 'sakha', 'shaka'], + 'saki': ['saki', 'siak', 'sika'], + 'sal': ['las', 'sal', 'sla'], + 'salable': ['basella', 'sabella', 'salable'], + 'salably': ['basally', 'salably'], + 'salaceta': ['catalase', 'salaceta'], + 'salacot': ['coastal', 'salacot'], + 'salading': ['salading', 'salangid'], + 'salago': ['aglaos', 'salago'], + 'salamandarin': ['salamandarin', 'salamandrian', 'salamandrina'], + 'salamandrian': ['salamandarin', 'salamandrian', 'salamandrina'], + 'salamandrina': ['salamandarin', 'salamandrian', 'salamandrina'], + 'salangid': ['salading', 'salangid'], + 'salariat': ['alastair', 'salariat'], + 'salat': ['atlas', 'salat', 'salta'], + 'salay': ['asyla', 'salay', 'sayal'], + 'sale': ['elsa', 'sale', 'seal', 'slae'], + 'salele': ['salele', 'sallee'], + 'salep': ['elaps', + 'lapse', + 'lepas', + 'pales', + 'salep', + 'saple', + 'sepal', + 'slape', + 'spale', + 'speal'], + 'saleratus': ['assaulter', 'reassault', 'saleratus'], + 'salian': ['anisal', 'nasial', 'salian', 'salina'], + 'salic': ['lacis', 'salic'], + 'salicin': ['incisal', 'salicin'], + 'salicylide': ['salicylide', 'scylliidae'], + 'salience': ['salience', 'secaline'], + 'salient': ['elastin', 'salient', 'saltine', 'slainte'], + 'salimeter': ['misrelate', 'salimeter'], + 'salimetry': ['mysterial', 'salimetry'], + 'salina': ['anisal', 'nasial', 'salian', 'salina'], + 'saline': ['alsine', 'neslia', 'saline', 'selina', 'silane'], + 'salinoterreous': ['salinoterreous', 'soliterraneous'], + 'salite': ['isleta', 'litsea', 'salite', 'stelai'], + 'salited': ['distale', 'salited'], + 'saliva': ['saliva', 'salvia'], + 'salivan': ['salivan', 'slavian'], + 'salivant': ['navalist', 'salivant'], + 'salivate': ['salivate', 'vestalia'], + 'salle': ['salle', 'sella'], + 'sallee': ['salele', 'sallee'], + 'sallet': ['sallet', 'stella', 'talles'], + 'sallow': ['sallow', 'swallo'], + 'salm': ['alms', 'salm', 'slam'], + 'salma': ['salma', 'samal'], + 'salmine': ['malines', 'salmine', 'selamin', 'seminal'], + 'salmis': ['missal', 'salmis'], + 'salmo': ['salmo', 'somal'], + 'salmonsite': ['assoilment', 'salmonsite'], + 'salome': ['melosa', 'salome', 'semola'], + 'salometer': ['elastomer', 'salometer'], + 'salon': ['salon', 'sloan', 'solan'], + 'saloon': ['alonso', 'alsoon', 'saloon'], + 'salp': ['salp', 'slap'], + 'salpa': ['palas', 'salpa'], + 'salpidae': ['palisade', 'salpidae'], + 'salpoid': ['psaloid', 'salpoid'], + 'salt': ['last', 'salt', 'slat'], + 'salta': ['atlas', 'salat', 'salta'], + 'saltary': ['astylar', 'saltary'], + 'saltation': ['saltation', 'stational'], + 'salted': ['desalt', 'salted'], + 'saltee': ['ateles', 'saltee', 'sealet', 'stelae', 'teasel'], + 'salter': ['laster', + 'lastre', + 'rastle', + 'relast', + 'resalt', + 'salter', + 'slater', + 'stelar'], + 'saltern': ['saltern', 'starnel', 'sternal'], + 'saltery': ['saltery', 'stearyl'], + 'saltier': ['aletris', 'alister', 'listera', 'realist', 'saltier'], + 'saltine': ['elastin', 'salient', 'saltine', 'slainte'], + 'saltiness': ['saintless', 'saltiness', 'slatiness', 'stainless'], + 'salting': ['anglist', 'lasting', 'salting', 'slating', 'staling'], + 'saltish': ['saltish', 'slatish'], + 'saltly': ['lastly', 'saltly'], + 'saltness': ['lastness', 'saltness'], + 'saltometer': ['rattlesome', 'saltometer'], + 'saltus': ['saltus', 'tussal'], + 'saltwife': ['flatwise', 'saltwife'], + 'salty': ['lasty', 'salty', 'slaty'], + 'salung': ['lugnas', 'salung'], + 'salute': ['salute', 'setula'], + 'saluter': ['arustle', 'estrual', 'saluter', 'saulter'], + 'salva': ['salva', 'valsa', 'vasal'], + 'salve': ['salve', 'selva', 'slave', 'valse'], + 'salver': ['salver', 'serval', 'slaver', 'versal'], + 'salvia': ['saliva', 'salvia'], + 'salvy': ['salvy', 'sylva'], + 'sam': ['mas', 'sam', 'sma'], + 'samal': ['salma', 'samal'], + 'saman': ['manas', 'saman'], + 'samani': ['samani', 'samian'], + 'samaritan': ['samaritan', 'sarmatian'], + 'samas': ['amass', 'assam', 'massa', 'samas'], + 'sambal': ['balsam', 'sambal'], + 'sambo': ['ambos', 'sambo'], + 'same': ['asem', 'mesa', 'same', 'seam'], + 'samel': ['amsel', 'melas', 'mesal', 'samel'], + 'samely': ['measly', 'samely'], + 'samen': ['manes', 'manse', 'mensa', 'samen', 'senam'], + 'samh': ['mash', 'samh', 'sham'], + 'samian': ['samani', 'samian'], + 'samiel': ['amiles', 'asmile', 'mesail', 'mesial', 'samiel'], + 'samir': ['maris', 'marsi', 'samir', 'simar'], + 'samisen': ['samisen', 'samsien'], + 'samish': ['samish', 'sisham'], + 'samite': ['samite', 'semita', 'tamise', 'teaism'], + 'sammer': ['mamers', 'sammer'], + 'sammier': ['amerism', 'asimmer', 'sammier'], + 'samnani': ['ananism', 'samnani'], + 'samnite': ['atenism', 'inmeats', 'insteam', 'samnite'], + 'samoan': ['monasa', 'samoan'], + 'samothere': ['heartsome', 'samothere'], + 'samoyed': ['samoyed', 'someday'], + 'samphire': ['samphire', 'seraphim'], + 'sampi': ['apism', 'sampi'], + 'sampler': ['lampers', 'sampler'], + 'samsien': ['samisen', 'samsien'], + 'samskara': ['makassar', 'samskara'], + 'samucan': ['manacus', 'samucan'], + 'samuel': ['amelus', 'samuel'], + 'sanability': ['insatiably', 'sanability'], + 'sanai': ['asian', 'naias', 'sanai'], + 'sanand': ['sanand', 'sandan'], + 'sanche': ['encash', 'sanche'], + 'sanct': ['sanct', 'scant'], + 'sanction': ['canonist', 'sanction', 'sonantic'], + 'sanctioner': ['resanction', 'sanctioner'], + 'sanctity': ['sanctity', 'scantity'], + 'sandak': ['sandak', 'skanda'], + 'sandan': ['sanand', 'sandan'], + 'sandarac': ['carandas', 'sandarac'], + 'sandawe': ['sandawe', 'weasand'], + 'sanded': ['desand', 'sadden', 'sanded'], + 'sanderling': ['sanderling', 'slandering'], + 'sandflower': ['flandowser', 'sandflower'], + 'sandhi': ['danish', 'sandhi'], + 'sandra': ['nasard', 'sandra'], + 'sandworm': ['sandworm', 'swordman', 'wordsman'], + 'sane': ['anes', 'sane', 'sean'], + 'sanetch': ['chasten', 'sanetch'], + 'sang': ['sang', 'snag'], + 'sanga': ['gasan', 'sanga'], + 'sangar': ['argans', 'sangar'], + 'sangei': ['easing', 'sangei'], + 'sanger': ['angers', 'sanger', 'serang'], + 'sangrel': ['sangrel', 'snagrel'], + 'sanhita': ['ashanti', 'sanhita', 'shaitan', 'thasian'], + 'sanicle': ['celsian', 'escalin', 'sanicle', 'secalin'], + 'sanies': ['anesis', 'anseis', 'sanies', 'sansei', 'sasine'], + 'sanious': ['sanious', 'suasion'], + 'sanitate': ['astatine', 'sanitate'], + 'sanitize': ['sanitize', 'satinize'], + 'sanity': ['sanity', 'satiny'], + 'sank': ['kans', 'sank'], + 'sankha': ['kashan', 'sankha'], + 'sannup': ['pannus', 'sannup', 'unsnap', 'unspan'], + 'sanpoil': ['sanpoil', 'spaniol'], + 'sansei': ['anesis', 'anseis', 'sanies', 'sansei', 'sasine'], + 'sansi': ['sansi', 'sasin'], + 'sant': ['nast', 'sant', 'stan'], + 'santa': ['santa', 'satan'], + 'santal': ['aslant', 'lansat', 'natals', 'santal'], + 'santali': ['lanista', 'santali'], + 'santalin': ['annalist', 'santalin'], + 'santee': ['ensate', 'enseat', 'santee', 'sateen', 'senate'], + 'santiago': ['agonista', 'santiago'], + 'santimi': ['animist', 'santimi'], + 'santir': ['instar', 'santir', 'strain'], + 'santon': ['santon', 'sonant', 'stanno'], + 'santorinite': ['reinstation', 'santorinite'], + 'sap': ['asp', 'sap', 'spa'], + 'sapan': ['pasan', 'sapan'], + 'sapek': ['sapek', 'speak'], + 'saperda': ['aspread', 'saperda'], + 'saphena': ['aphanes', 'saphena'], + 'sapid': ['sapid', 'spaid'], + 'sapient': ['panties', 'sapient', 'spinate'], + 'sapiential': ['antilipase', 'sapiential'], + 'sapin': ['pisan', 'sapin', 'spina'], + 'sapinda': ['anapsid', 'sapinda'], + 'saple': ['elaps', + 'lapse', + 'lepas', + 'pales', + 'salep', + 'saple', + 'sepal', + 'slape', + 'spale', + 'speal'], + 'sapling': ['lapsing', 'sapling'], + 'sapo': ['asop', 'sapo', 'soap'], + 'sapor': ['psora', 'sapor', 'sarpo'], + 'saporous': ['asporous', 'saporous'], + 'sapota': ['sapota', 'taposa'], + 'sapotilha': ['hapalotis', 'sapotilha'], + 'sapphire': ['papisher', 'sapphire'], + 'sapples': ['papless', 'sapples'], + 'sapremia': ['aspermia', 'sapremia'], + 'sapremic': ['aspermic', 'sapremic'], + 'saprine': ['persian', 'prasine', 'saprine'], + 'saprolite': ['posterial', 'saprolite'], + 'saprolitic': ['polaristic', 'poristical', 'saprolitic'], + 'sapropel': ['prolapse', 'sapropel'], + 'sapropelic': ['periscopal', 'sapropelic'], + 'saprophagous': ['prasophagous', 'saprophagous'], + 'sapwort': ['postwar', 'sapwort'], + 'sar': ['ras', 'sar'], + 'sara': ['rasa', 'sara'], + 'saraad': ['saraad', 'sarada'], + 'sarada': ['saraad', 'sarada'], + 'saraf': ['safar', 'saraf'], + 'sarah': ['asarh', 'raash', 'sarah'], + 'saran': ['ansar', 'saran', 'sarna'], + 'sarangi': ['giansar', 'sarangi'], + 'sarcenet': ['reascent', 'sarcenet'], + 'sarcine': ['arsenic', 'cerasin', 'sarcine'], + 'sarcitis': ['sarcitis', 'triassic'], + 'sarcle': ['sarcle', 'scaler', 'sclera'], + 'sarcoadenoma': ['adenosarcoma', 'sarcoadenoma'], + 'sarcocarcinoma': ['carcinosarcoma', 'sarcocarcinoma'], + 'sarcoid': ['sarcoid', 'scaroid'], + 'sarcoline': ['censorial', 'sarcoline'], + 'sarcolite': ['alectoris', 'sarcolite', 'sclerotia', 'sectorial'], + 'sarcoplast': ['postsacral', 'sarcoplast'], + 'sarcotic': ['acrostic', 'sarcotic', 'socratic'], + 'sard': ['sadr', 'sard'], + 'sardian': ['andrias', 'sardian', 'sarinda'], + 'sardine': ['andries', 'isander', 'sardine'], + 'sardoin': ['sadiron', 'sardoin'], + 'sardonic': ['draconis', 'sardonic'], + 'sare': ['arse', 'rase', 'sare', 'sear', 'sera'], + 'sargonide': ['grandiose', 'sargonide'], + 'sari': ['rais', 'sair', 'sari'], + 'sarif': ['farsi', 'sarif'], + 'sarigue': ['ergusia', 'gerusia', 'sarigue'], + 'sarinda': ['andrias', 'sardian', 'sarinda'], + 'sarip': ['paris', 'parsi', 'sarip'], + 'sark': ['askr', 'kras', 'sark'], + 'sarkine': ['kerasin', 'sarkine'], + 'sarkit': ['rastik', 'sarkit', 'straik'], + 'sarmatian': ['samaritan', 'sarmatian'], + 'sarment': ['sarment', 'smarten'], + 'sarmentous': ['sarmentous', 'tarsonemus'], + 'sarna': ['ansar', 'saran', 'sarna'], + 'sarod': ['sarod', 'sorda'], + 'saron': ['arson', 'saron', 'sonar'], + 'saronic': ['arsonic', 'saronic'], + 'sarpo': ['psora', 'sapor', 'sarpo'], + 'sarra': ['arras', 'sarra'], + 'sarsenet': ['assenter', 'reassent', 'sarsenet'], + 'sarsi': ['arsis', 'sarsi'], + 'sart': ['sart', 'star', 'stra', 'tars', 'tsar'], + 'sartain': ['artisan', 'astrain', 'sartain', 'tsarina'], + 'sartish': ['sartish', 'shastri'], + 'sartor': ['rostra', 'sartor'], + 'sasan': ['nassa', 'sasan'], + 'sasin': ['sansi', 'sasin'], + 'sasine': ['anesis', 'anseis', 'sanies', 'sansei', 'sasine'], + 'sat': ['ast', 'sat'], + 'satan': ['santa', 'satan'], + 'satanical': ['castalian', 'satanical'], + 'satanism': ['mantissa', 'satanism'], + 'sate': ['ates', 'east', 'eats', 'sate', 'seat', 'seta'], + 'sateen': ['ensate', 'enseat', 'santee', 'sateen', 'senate'], + 'sateless': ['sateless', 'seatless'], + 'satelles': ['satelles', 'tessella'], + 'satellite': ['satellite', 'telestial'], + 'satiable': ['bisaltae', 'satiable'], + 'satiate': ['isatate', 'satiate', 'taetsia'], + 'satieno': ['aeonist', 'asiento', 'satieno'], + 'satient': ['atenist', 'instate', 'satient', 'steatin'], + 'satin': ['saint', 'satin', 'stain'], + 'satine': ['satine', 'tisane'], + 'satined': ['destain', 'instead', 'sainted', 'satined'], + 'satinette': ['enstatite', 'intestate', 'satinette'], + 'satinite': ['satinite', 'sittinae'], + 'satinize': ['sanitize', 'satinize'], + 'satinlike': ['kleistian', 'saintlike', 'satinlike'], + 'satiny': ['sanity', 'satiny'], + 'satire': ['satire', 'striae'], + 'satirical': ['racialist', 'satirical'], + 'satirist': ['satirist', 'tarsitis'], + 'satrae': ['astare', 'satrae'], + 'satrapic': ['aspartic', 'satrapic'], + 'satron': ['asnort', 'satron'], + 'sattle': ['latest', 'sattle', 'taslet'], + 'sattva': ['sattva', 'tavast'], + 'saturable': ['balaustre', 'saturable'], + 'saturation': ['saturation', 'titanosaur'], + 'saturator': ['saturator', 'tartarous'], + 'saturn': ['saturn', 'unstar'], + 'saturnale': ['alaternus', 'saturnale'], + 'saturnalia': ['australian', 'saturnalia'], + 'saturnia': ['asturian', 'austrian', 'saturnia'], + 'saturnine': ['neustrian', 'saturnine', 'sturninae'], + 'saturnism': ['saturnism', 'surmisant'], + 'satyr': ['satyr', 'stary', 'stray', 'trasy'], + 'satyrlike': ['satyrlike', 'streakily'], + 'sauce': ['cause', 'sauce'], + 'sauceless': ['causeless', 'sauceless'], + 'sauceline': ['sauceline', 'seleucian'], + 'saucer': ['causer', 'saucer'], + 'sauger': ['sauger', 'usager'], + 'saugh': ['agush', 'saugh'], + 'saul': ['saul', 'sula'], + 'sauld': ['aldus', 'sauld'], + 'sault': ['latus', 'sault', 'talus'], + 'saulter': ['arustle', 'estrual', 'saluter', 'saulter'], + 'saum': ['masu', 'musa', 'saum'], + 'sauna': ['nasua', 'sauna'], + 'saur': ['rusa', 'saur', 'sura', 'ursa', 'usar'], + 'saura': ['arusa', 'saura', 'usara'], + 'saurian': ['saurian', 'suriana'], + 'saury': ['saury', 'surya'], + 'sausage': ['assuage', 'sausage'], + 'saut': ['saut', 'tasu', 'utas'], + 'sauve': ['sauve', 'suave'], + 'save': ['aves', 'save', 'vase'], + 'savin': ['savin', 'sivan'], + 'saviour': ['saviour', 'various'], + 'savor': ['savor', 'sorva'], + 'savored': ['oversad', 'savored'], + 'saw': ['saw', 'swa', 'was'], + 'sawah': ['awash', 'sawah'], + 'sawali': ['aswail', 'sawali'], + 'sawback': ['backsaw', 'sawback'], + 'sawbuck': ['bucksaw', 'sawbuck'], + 'sawer': ['resaw', 'sawer', 'seraw', 'sware', 'swear', 'warse'], + 'sawing': ['aswing', 'sawing'], + 'sawish': ['sawish', 'siwash'], + 'sawn': ['sawn', 'snaw', 'swan'], + 'sawt': ['sawt', 'staw', 'swat', 'taws', 'twas', 'wast'], + 'sawyer': ['sawyer', 'swayer'], + 'saxe': ['axes', 'saxe', 'seax'], + 'saxten': ['saxten', 'sextan'], + 'say': ['say', 'yas'], + 'sayal': ['asyla', 'salay', 'sayal'], + 'sayer': ['reasy', 'resay', 'sayer', 'seary'], + 'sayid': ['daisy', 'sayid'], + 'scabbler': ['scabbler', 'scrabble'], + 'scabies': ['abscise', 'scabies'], + 'scaddle': ['scaddle', 'scalded'], + 'scaean': ['anaces', 'scaean'], + 'scala': ['calas', 'casal', 'scala'], + 'scalar': ['lascar', 'rascal', 'sacral', 'scalar'], + 'scalded': ['scaddle', 'scalded'], + 'scale': ['alces', 'casel', 'scale'], + 'scalena': ['escalan', 'scalena'], + 'scalene': ['cleanse', 'scalene'], + 'scaler': ['sarcle', 'scaler', 'sclera'], + 'scallola': ['callosal', 'scallola'], + 'scalloper': ['procellas', 'scalloper'], + 'scaloni': ['nicolas', 'scaloni'], + 'scalp': ['clasp', 'scalp'], + 'scalper': ['clasper', 'reclasp', 'scalper'], + 'scalping': ['clasping', 'scalping'], + 'scalpture': ['prescutal', 'scalpture'], + 'scaly': ['aclys', 'scaly'], + 'scambler': ['scambler', 'scramble'], + 'scampish': ['scampish', 'scaphism'], + 'scania': ['ascian', 'sacian', 'scania', 'sicana'], + 'scant': ['sanct', 'scant'], + 'scantity': ['sanctity', 'scantity'], + 'scantle': ['asclent', 'scantle'], + 'scape': ['capes', 'scape', 'space'], + 'scapeless': ['scapeless', 'spaceless'], + 'scapha': ['pascha', 'scapha'], + 'scaphander': ['handscrape', 'scaphander'], + 'scaphism': ['scampish', 'scaphism'], + 'scaphite': ['paschite', 'pastiche', 'pistache', 'scaphite'], + 'scaphopod': ['podoscaph', 'scaphopod'], + 'scapoid': ['psoadic', 'scapoid', 'sciapod'], + 'scapolite': ['alopecist', 'altiscope', 'epicostal', 'scapolite'], + 'scappler': ['scappler', 'scrapple'], + 'scapula': ['capsula', 'pascual', 'scapula'], + 'scapular': ['capsular', 'scapular'], + 'scapulated': ['capsulated', 'scapulated'], + 'scapulectomy': ['capsulectomy', 'scapulectomy'], + 'scarab': ['barsac', 'scarab'], + 'scarcement': ['marcescent', 'scarcement'], + 'scare': ['carse', 'caser', 'ceras', 'scare', 'scrae'], + 'scarification': ['sacrification', 'scarification'], + 'scarificator': ['sacrificator', 'scarificator'], + 'scarily': ['scarily', 'scraily'], + 'scarlet': ['scarlet', 'sclater'], + 'scarn': ['scarn', 'scran'], + 'scaroid': ['sarcoid', 'scaroid'], + 'scarp': ['craps', 'scarp', 'scrap'], + 'scarping': ['scarping', 'scraping'], + 'scart': ['scart', 'scrat'], + 'scarth': ['scarth', 'scrath', 'starch'], + 'scary': ['ascry', 'scary', 'scray'], + 'scase': ['casse', 'scase'], + 'scat': ['acts', 'cast', 'scat'], + 'scathe': ['chaste', 'sachet', 'scathe', 'scheat'], + 'scatterer': ['scatterer', 'streetcar'], + 'scaturient': ['incrustate', 'scaturient', 'scrutinate'], + 'scaum': ['camus', 'musca', 'scaum', 'sumac'], + 'scaur': ['cursa', 'scaur'], + 'scaut': ['scaut', 'scuta'], + 'scavel': ['calves', 'scavel'], + 'scawl': ['scawl', 'sclaw'], + 'sceat': ['caste', 'sceat'], + 'scene': ['cense', 'scene', 'sence'], + 'scenery': ['scenery', 'screeny'], + 'scented': ['descent', 'scented'], + 'scepter': ['respect', 'scepter', 'specter'], + 'sceptered': ['sceptered', 'spectered'], + 'scepterless': ['respectless', 'scepterless'], + 'sceptral': ['sceptral', 'scraplet', 'spectral'], + 'sceptry': ['precyst', 'sceptry', 'spectry'], + 'scerne': ['censer', 'scerne', 'screen', 'secern'], + 'schalmei': ['camelish', 'schalmei'], + 'scheat': ['chaste', 'sachet', 'scathe', 'scheat'], + 'schema': ['sachem', 'schema'], + 'schematic': ['catechism', 'schematic'], + 'scheme': ['scheme', 'smeech'], + 'schemer': ['chermes', 'schemer'], + 'scho': ['cosh', 'scho'], + 'scholae': ['oscheal', 'scholae'], + 'schone': ['cheson', 'chosen', 'schone'], + 'schooltime': ['chilostome', 'schooltime'], + 'schout': ['schout', 'scouth'], + 'schute': ['schute', 'tusche'], + 'sciaenoid': ['oniscidae', 'oscinidae', 'sciaenoid'], + 'scian': ['canis', 'scian'], + 'sciapod': ['psoadic', 'scapoid', 'sciapod'], + 'sciara': ['carisa', 'sciara'], + 'sciarid': ['cidaris', 'sciarid'], + 'sciatic': ['ascitic', 'sciatic'], + 'sciatical': ['ascitical', 'sciatical'], + 'scient': ['encist', 'incest', 'insect', 'scient'], + 'sciential': ['elasticin', 'inelastic', 'sciential'], + 'scillitan': ['scillitan', 'scintilla'], + 'scintilla': ['scillitan', 'scintilla'], + 'scintle': ['lentisc', 'scintle', 'stencil'], + 'scion': ['oscin', 'scion', 'sonic'], + 'sciot': ['ostic', 'sciot', 'stoic'], + 'sciotherical': ['ischiorectal', 'sciotherical'], + 'scious': ['scious', 'socius'], + 'scirenga': ['creasing', 'scirenga'], + 'scirpus': ['prussic', 'scirpus'], + 'scissortail': ['scissortail', 'solaristics'], + 'sciurine': ['incisure', 'sciurine'], + 'sciuroid': ['dioscuri', 'sciuroid'], + 'sclate': ['castle', 'sclate'], + 'sclater': ['scarlet', 'sclater'], + 'sclaw': ['scawl', 'sclaw'], + 'sclera': ['sarcle', 'scaler', 'sclera'], + 'sclere': ['sclere', 'screel'], + 'scleria': ['scleria', 'sercial'], + 'sclerite': ['sclerite', 'silcrete'], + 'sclerodermite': ['dermosclerite', 'sclerodermite'], + 'scleromata': ['clamatores', 'scleromata'], + 'sclerose': ['coreless', 'sclerose'], + 'sclerospora': ['prolacrosse', 'sclerospora'], + 'sclerote': ['corselet', 'sclerote', 'selector'], + 'sclerotia': ['alectoris', 'sarcolite', 'sclerotia', 'sectorial'], + 'sclerotial': ['cloisteral', 'sclerotial'], + 'sclerotinia': ['intersocial', 'orleanistic', 'sclerotinia'], + 'sclerotium': ['closterium', 'sclerotium'], + 'sclerotomy': ['mycosterol', 'sclerotomy'], + 'scoad': ['cados', 'scoad'], + 'scob': ['bosc', 'scob'], + 'scobicular': ['scobicular', 'scrobicula'], + 'scolia': ['colias', 'scolia', 'social'], + 'scolion': ['scolion', 'solonic'], + 'scombrine': ['becrimson', 'scombrine'], + 'scone': ['cones', 'scone'], + 'scooper': ['coprose', 'scooper'], + 'scoot': ['coost', 'scoot'], + 'scopa': ['posca', 'scopa'], + 'scoparin': ['parsonic', 'scoparin'], + 'scope': ['copse', 'pecos', 'scope'], + 'scopidae': ['diascope', 'psocidae', 'scopidae'], + 'scopine': ['psocine', 'scopine'], + 'scopiped': ['podiceps', 'scopiped'], + 'scopoline': ['niloscope', 'scopoline'], + 'scorbutical': ['scorbutical', 'subcortical'], + 'scorbutically': ['scorbutically', 'subcortically'], + 'score': ['corse', 'score'], + 'scorer': ['scorer', 'sorcer'], + 'scoriae': ['coraise', 'scoriae'], + 'scorpidae': ['carpiodes', 'scorpidae'], + 'scorpiones': ['procession', 'scorpiones'], + 'scorpionic': ['orniscopic', 'scorpionic'], + 'scorse': ['cessor', 'crosse', 'scorse'], + 'scortation': ['cartoonist', 'scortation'], + 'scot': ['cost', 'scot'], + 'scotale': ['alecost', 'lactose', 'scotale', 'talcose'], + 'scote': ['coset', 'estoc', 'scote'], + 'scoter': ['corset', 'cortes', 'coster', 'escort', 'scoter', 'sector'], + 'scotia': ['isotac', 'scotia'], + 'scotism': ['cosmist', 'scotism'], + 'scotomatic': ['osmotactic', 'scotomatic'], + 'scotty': ['cytost', 'scotty'], + 'scoup': ['copus', 'scoup'], + 'scour': ['cours', 'scour'], + 'scoured': ['coursed', 'scoured'], + 'scourer': ['courser', 'scourer'], + 'scourge': ['scourge', 'scrouge'], + 'scourger': ['scourger', 'scrouger'], + 'scouring': ['coursing', 'scouring'], + 'scouth': ['schout', 'scouth'], + 'scrabble': ['scabbler', 'scrabble'], + 'scrabe': ['braces', 'scrabe'], + 'scrae': ['carse', 'caser', 'ceras', 'scare', 'scrae'], + 'scraily': ['scarily', 'scraily'], + 'scramble': ['scambler', 'scramble'], + 'scran': ['scarn', 'scran'], + 'scrap': ['craps', 'scarp', 'scrap'], + 'scrape': ['casper', 'escarp', 'parsec', 'scrape', 'secpar', 'spacer'], + 'scrapie': ['epacris', 'scrapie', 'serapic'], + 'scraping': ['scarping', 'scraping'], + 'scraplet': ['sceptral', 'scraplet', 'spectral'], + 'scrapple': ['scappler', 'scrapple'], + 'scrat': ['scart', 'scrat'], + 'scratcher': ['rescratch', 'scratcher'], + 'scrath': ['scarth', 'scrath', 'starch'], + 'scray': ['ascry', 'scary', 'scray'], + 'screak': ['resack', 'sacker', 'screak'], + 'screaming': ['germanics', 'screaming'], + 'screamy': ['armscye', 'screamy'], + 'scree': ['scree', 'secre'], + 'screel': ['sclere', 'screel'], + 'screen': ['censer', 'scerne', 'screen', 'secern'], + 'screenless': ['censerless', 'screenless'], + 'screeny': ['scenery', 'screeny'], + 'screet': ['resect', 'screet', 'secret'], + 'screwdrive': ['drivescrew', 'screwdrive'], + 'scrieve': ['cerevis', 'scrieve', 'service'], + 'scrike': ['scrike', 'sicker'], + 'scrip': ['crisp', 'scrip'], + 'scripee': ['precise', 'scripee'], + 'scripula': ['scripula', 'spicular'], + 'scrobicula': ['scobicular', 'scrobicula'], + 'scrota': ['arctos', 'castor', 'costar', 'scrota'], + 'scrouge': ['scourge', 'scrouge'], + 'scrouger': ['scourger', 'scrouger'], + 'scrout': ['scrout', 'scruto'], + 'scroyle': ['cryosel', 'scroyle'], + 'scruf': ['scruf', 'scurf'], + 'scruffle': ['scruffle', 'scuffler'], + 'scruple': ['scruple', 'sculper'], + 'scrutate': ['crustate', 'scrutate'], + 'scrutation': ['crustation', 'scrutation'], + 'scrutinant': ['incrustant', 'scrutinant'], + 'scrutinate': ['incrustate', 'scaturient', 'scrutinate'], + 'scruto': ['scrout', 'scruto'], + 'scudi': ['scudi', 'sudic'], + 'scuffler': ['scruffle', 'scuffler'], + 'sculper': ['scruple', 'sculper'], + 'sculpin': ['insculp', 'sculpin'], + 'scup': ['cusp', 'scup'], + 'scur': ['crus', 'scur'], + 'scurf': ['scruf', 'scurf'], + 'scusation': ['cosustain', 'scusation'], + 'scuta': ['scaut', 'scuta'], + 'scutal': ['scutal', 'suclat'], + 'scute': ['cetus', 'scute'], + 'scutifer': ['fusteric', 'scutifer'], + 'scutigeral': ['gesticular', 'scutigeral'], + 'scutula': ['auscult', 'scutula'], + 'scye': ['scye', 'syce'], + 'scylliidae': ['salicylide', 'scylliidae'], + 'scyllium': ['clumsily', 'scyllium'], + 'scyphi': ['physic', 'scyphi'], + 'scyphomancy': ['psychomancy', 'scyphomancy'], + 'scyt': ['cyst', 'scyt'], + 'scythe': ['chesty', 'scythe'], + 'scytitis': ['cystitis', 'scytitis'], + 'se': ['es', 'se'], + 'sea': ['aes', 'ase', 'sea'], + 'seadog': ['dosage', 'seadog'], + 'seagirt': ['seagirt', 'strigae'], + 'seah': ['seah', 'shea'], + 'seak': ['sake', 'seak'], + 'seal': ['elsa', 'sale', 'seal', 'slae'], + 'sealable': ['leasable', 'sealable'], + 'sealch': ['cashel', 'laches', 'sealch'], + 'sealer': ['alerse', 'leaser', 'reales', 'resale', 'reseal', 'sealer'], + 'sealet': ['ateles', 'saltee', 'sealet', 'stelae', 'teasel'], + 'sealing': ['leasing', 'sealing'], + 'sealwort': ['restowal', 'sealwort'], + 'seam': ['asem', 'mesa', 'same', 'seam'], + 'seamanite': ['anamesite', 'seamanite'], + 'seamark': ['kamares', 'seamark'], + 'seamer': ['reseam', 'seamer'], + 'seamlet': ['maltese', 'seamlet'], + 'seamlike': ['mesalike', 'seamlike'], + 'seamrend': ['redesman', 'seamrend'], + 'seamster': ['masseter', 'seamster'], + 'seamus': ['assume', 'seamus'], + 'sean': ['anes', 'sane', 'sean'], + 'seance': ['encase', 'seance', 'seneca'], + 'seaplane': ['seaplane', 'spelaean'], + 'seaport': ['esparto', 'petrosa', 'seaport'], + 'sear': ['arse', 'rase', 'sare', 'sear', 'sera'], + 'searce': ['cesare', 'crease', 'recase', 'searce'], + 'searcer': ['creaser', 'searcer'], + 'search': ['arches', 'chaser', 'eschar', 'recash', 'search'], + 'searcher': ['rechaser', 'research', 'searcher'], + 'searchment': ['manchester', 'searchment'], + 'searcloth': ['clathrose', 'searcloth'], + 'seared': ['erased', 'reseda', 'seared'], + 'searer': ['eraser', 'searer'], + 'searing': ['searing', 'seringa'], + 'seary': ['reasy', 'resay', 'sayer', 'seary'], + 'seaside': ['disease', 'seaside'], + 'seat': ['ates', 'east', 'eats', 'sate', 'seat', 'seta'], + 'seated': ['seated', 'sedate'], + 'seater': ['asteer', + 'easter', + 'eastre', + 'reseat', + 'saeter', + 'seater', + 'staree', + 'teaser', + 'teresa'], + 'seating': ['easting', + 'gainset', + 'genista', + 'ingesta', + 'seating', + 'signate', + 'teasing'], + 'seatless': ['sateless', 'seatless'], + 'seatrain': ['artesian', 'asterina', 'asternia', 'erastian', 'seatrain'], + 'seatron': ['noreast', 'rosetan', 'seatron', 'senator', 'treason'], + 'seave': ['eaves', 'evase', 'seave'], + 'seax': ['axes', 'saxe', 'seax'], + 'seba': ['base', 'besa', 'sabe', 'seba'], + 'sebastian': ['bassanite', 'sebastian'], + 'sebilla': ['sabelli', 'sebilla'], + 'sebum': ['embus', 'sebum'], + 'secalin': ['celsian', 'escalin', 'sanicle', 'secalin'], + 'secaline': ['salience', 'secaline'], + 'secant': ['ascent', 'secant', 'stance'], + 'secern': ['censer', 'scerne', 'screen', 'secern'], + 'secernent': ['secernent', 'sentencer'], + 'secondar': ['endosarc', 'secondar'], + 'secos': ['cosse', 'secos'], + 'secpar': ['casper', 'escarp', 'parsec', 'scrape', 'secpar', 'spacer'], + 'secre': ['scree', 'secre'], + 'secret': ['resect', 'screet', 'secret'], + 'secretarian': ['ascertainer', 'reascertain', 'secretarian'], + 'secretion': ['resection', 'secretion'], + 'secretional': ['resectional', 'secretional'], + 'sect': ['cest', 'sect'], + 'sectarian': ['ascertain', 'cartesian', 'cartisane', 'sectarian'], + 'sectarianism': ['cartesianism', 'sectarianism'], + 'section': ['contise', 'noetics', 'section'], + 'sectism': ['sectism', 'smectis'], + 'sector': ['corset', 'cortes', 'coster', 'escort', 'scoter', 'sector'], + 'sectorial': ['alectoris', 'sarcolite', 'sclerotia', 'sectorial'], + 'sectroid': ['decorist', 'sectroid'], + 'securable': ['rescuable', 'securable'], + 'securance': ['recusance', 'securance'], + 'secure': ['cereus', 'ceruse', 'recuse', 'rescue', 'secure'], + 'securer': ['recurse', 'rescuer', 'securer'], + 'sedan': ['sedan', 'snead'], + 'sedanier': ['arsedine', 'arsenide', 'sedanier', 'siderean'], + 'sedat': ['sedat', 'stade', 'stead'], + 'sedate': ['seated', 'sedate'], + 'sedation': ['astonied', 'sedation'], + 'sederunt': ['sederunt', 'underset', 'undesert', 'unrested'], + 'sedile': ['diesel', 'sedile', 'seidel'], + 'sedimetric': ['sedimetric', 'semidirect'], + 'sedimetrical': ['decimestrial', 'sedimetrical'], + 'sedition': ['desition', 'sedition'], + 'sedulity': ['dysluite', 'sedulity'], + 'sedum': ['mused', 'sedum'], + 'seedbird': ['birdseed', 'seedbird'], + 'seeded': ['deseed', 'seeded'], + 'seeder': ['reseed', 'seeder'], + 'seedlip': ['pelides', 'seedlip'], + 'seeing': ['seeing', 'signee'], + 'seek': ['kees', 'seek', 'skee'], + 'seeker': ['reseek', 'seeker'], + 'seel': ['else', 'lees', 'seel', 'sele', 'slee'], + 'seem': ['mese', 'seem', 'seme', 'smee'], + 'seemer': ['emerse', 'seemer'], + 'seen': ['ense', 'esne', 'nese', 'seen', 'snee'], + 'seenu': ['ensue', 'seenu', 'unsee'], + 'seer': ['erse', 'rees', 'seer', 'sere'], + 'seerband': ['seerband', 'serabend'], + 'seerhand': ['denshare', 'seerhand'], + 'seerhood': ['rhodeose', 'seerhood'], + 'seership': ['hesperis', 'seership'], + 'seething': ['seething', 'sheeting'], + 'seg': ['ges', 'seg'], + 'seggar': ['sagger', 'seggar'], + 'seggard': ['daggers', 'seggard'], + 'sego': ['goes', 'sego'], + 'segolate': ['gelatose', 'segolate'], + 'segreant': ['estrange', 'segreant', 'sergeant', 'sternage'], + 'seid': ['desi', 'ides', 'seid', 'side'], + 'seidel': ['diesel', 'sedile', 'seidel'], + 'seignioral': ['seignioral', 'seignorial'], + 'seignoral': ['gasoliner', 'seignoral'], + 'seignorial': ['seignioral', 'seignorial'], + 'seine': ['insee', 'seine'], + 'seiner': ['inseer', 'nereis', 'seiner', 'serine', 'sirene'], + 'seise': ['essie', 'seise'], + 'seism': ['seism', 'semis'], + 'seismal': ['aimless', 'melissa', 'seismal'], + 'seismotic': ['seismotic', 'societism'], + 'seit': ['seit', 'site'], + 'seizable': ['seizable', 'sizeable'], + 'seizer': ['resize', 'seizer'], + 'sekane': ['sakeen', 'sekane'], + 'sekani': ['kinase', 'sekani'], + 'sekar': ['asker', 'reask', 'saker', 'sekar'], + 'seker': ['esker', 'keres', 'reesk', 'seker', 'skeer', 'skere'], + 'selagite': ['elegiast', 'selagite'], + 'selah': ['halse', 'leash', 'selah', 'shale', 'sheal', 'shela'], + 'selamin': ['malines', 'salmine', 'selamin', 'seminal'], + 'selbergite': ['gilbertese', 'selbergite'], + 'seldor': ['dorsel', 'seldor', 'solder'], + 'seldseen': ['needless', 'seldseen'], + 'sele': ['else', 'lees', 'seel', 'sele', 'slee'], + 'selector': ['corselet', 'sclerote', 'selector'], + 'selenic': ['license', 'selenic', 'silence'], + 'selenion': ['leonines', 'selenion'], + 'selenitic': ['insectile', 'selenitic'], + 'selenium': ['selenium', 'semilune', 'seminule'], + 'selenosis': ['noiseless', 'selenosis'], + 'seleucian': ['sauceline', 'seleucian'], + 'self': ['fels', 'self'], + 'selfsame': ['fameless', 'selfsame'], + 'selfsameness': ['famelessness', 'selfsameness'], + 'selictar': ['altrices', 'selictar'], + 'selina': ['alsine', 'neslia', 'saline', 'selina', 'silane'], + 'selion': ['insole', 'leonis', 'lesion', 'selion'], + 'seljukian': ['januslike', 'seljukian'], + 'sella': ['salle', 'sella'], + 'sellably': ['sellably', 'syllable'], + 'sellate': ['estella', 'sellate'], + 'seller': ['resell', 'seller'], + 'selli': ['lisle', 'selli'], + 'sellie': ['leslie', 'sellie'], + 'sellout': ['outsell', 'sellout'], + 'selt': ['lest', 'selt'], + 'selter': ['lester', 'selter', 'streel'], + 'selung': ['gunsel', 'selung', 'slunge'], + 'selva': ['salve', 'selva', 'slave', 'valse'], + 'semang': ['magnes', 'semang'], + 'semantic': ['amnestic', 'semantic'], + 'semaphore': ['mesohepar', 'semaphore'], + 'sematic': ['cameist', 'etacism', 'sematic'], + 'sematrope': ['perosmate', 'sematrope'], + 'seme': ['mese', 'seem', 'seme', 'smee'], + 'semen': ['mense', 'mesne', 'semen'], + 'semeostoma': ['semeostoma', 'semostomae'], + 'semi': ['mise', 'semi', 'sime'], + 'semiarch': ['semiarch', 'smachrie'], + 'semibald': ['bedismal', 'semibald'], + 'semiball': ['mislabel', 'semiball'], + 'semic': ['mesic', 'semic'], + 'semicircle': ['semicircle', 'semicleric'], + 'semicleric': ['semicircle', 'semicleric'], + 'semicone': ['nicesome', 'semicone'], + 'semicoronet': ['oncosimeter', 'semicoronet'], + 'semicrome': ['mesomeric', 'microseme', 'semicrome'], + 'semidirect': ['sedimetric', 'semidirect'], + 'semidormant': ['memorandist', 'moderantism', 'semidormant'], + 'semihard': ['dreamish', 'semihard'], + 'semihiant': ['histamine', 'semihiant'], + 'semilimber': ['immersible', 'semilimber'], + 'semilunar': ['semilunar', 'unrealism'], + 'semilune': ['selenium', 'semilune', 'seminule'], + 'semiminor': ['immersion', 'semiminor'], + 'semimoron': ['monroeism', 'semimoron'], + 'seminal': ['malines', 'salmine', 'selamin', 'seminal'], + 'seminar': ['remains', 'seminar'], + 'seminasal': ['messalian', 'seminasal'], + 'seminomadic': ['demoniacism', 'seminomadic'], + 'seminomata': ['mastomenia', 'seminomata'], + 'seminule': ['selenium', 'semilune', 'seminule'], + 'semiopal': ['malpoise', 'semiopal'], + 'semiorb': ['boreism', 'semiorb'], + 'semiovaloid': ['semiovaloid', 'semiovoidal'], + 'semiovoidal': ['semiovaloid', 'semiovoidal'], + 'semipolar': ['perisomal', 'semipolar'], + 'semipro': ['imposer', 'promise', 'semipro'], + 'semipronation': ['impersonation', 'prosemination', 'semipronation'], + 'semiquote': ['quietsome', 'semiquote'], + 'semirotund': ['semirotund', 'unmortised'], + 'semis': ['seism', 'semis'], + 'semispan': ['menaspis', 'semispan'], + 'semisteel': ['messelite', 'semisteel', 'teleseism'], + 'semistill': ['limitless', 'semistill'], + 'semistriated': ['disastimeter', 'semistriated'], + 'semita': ['samite', 'semita', 'tamise', 'teaism'], + 'semitae': ['amesite', 'mesitae', 'semitae'], + 'semitour': ['moisture', 'semitour'], + 'semiurban': ['semiurban', 'submarine'], + 'semiurn': ['neurism', 'semiurn'], + 'semivector': ['semivector', 'viscometer'], + 'semnae': ['enseam', 'semnae'], + 'semola': ['melosa', 'salome', 'semola'], + 'semolella': ['lamellose', 'semolella'], + 'semolina': ['laminose', 'lemonias', 'semolina'], + 'semological': ['mesological', 'semological'], + 'semology': ['mesology', 'semology'], + 'semostomae': ['semeostoma', 'semostomae'], + 'sempiternous': ['sempiternous', 'supermoisten'], + 'semuncia': ['muscinae', 'semuncia'], + 'semuncial': ['masculine', 'semuncial', 'simulance'], + 'sen': ['ens', 'sen'], + 'senaite': ['etesian', 'senaite'], + 'senam': ['manes', 'manse', 'mensa', 'samen', 'senam'], + 'senarius': ['anuresis', 'senarius'], + 'senate': ['ensate', 'enseat', 'santee', 'sateen', 'senate'], + 'senator': ['noreast', 'rosetan', 'seatron', 'senator', 'treason'], + 'senatorian': ['arsenation', 'senatorian', 'sonneratia'], + 'senatrices': ['resistance', 'senatrices'], + 'sence': ['cense', 'scene', 'sence'], + 'senci': ['senci', 'since'], + 'send': ['send', 'sned'], + 'sender': ['resend', 'sender'], + 'seneca': ['encase', 'seance', 'seneca'], + 'senega': ['sagene', 'senega'], + 'senesce': ['essence', 'senesce'], + 'senile': ['enisle', 'ensile', 'senile', 'silene'], + 'senilism': ['liminess', 'senilism'], + 'senior': ['rosine', 'senior', 'soneri'], + 'senlac': ['lances', 'senlac'], + 'senna': ['nanes', 'senna'], + 'sennit': ['innest', 'sennit', 'sinnet', 'tennis'], + 'sennite': ['intense', 'sennite'], + 'senocular': ['larcenous', 'senocular'], + 'senones': ['oneness', 'senones'], + 'sensable': ['ableness', 'blaeness', 'sensable'], + 'sensatorial': ['assertional', 'sensatorial'], + 'sensical': ['laciness', 'sensical'], + 'sensilia': ['sensilia', 'silesian'], + 'sensilla': ['nailless', 'sensilla'], + 'sension': ['neossin', 'sension'], + 'sensuism': ['sensuism', 'senusism'], + 'sent': ['nest', 'sent', 'sten'], + 'sentencer': ['secernent', 'sentencer'], + 'sentition': ['sentition', 'tenonitis'], + 'senusism': ['sensuism', 'senusism'], + 'sepad': ['depas', 'sepad', 'spade'], + 'sepal': ['elaps', + 'lapse', + 'lepas', + 'pales', + 'salep', + 'saple', + 'sepal', + 'slape', + 'spale', + 'speal'], + 'sepaled': ['delapse', 'sepaled'], + 'sepaloid': ['episodal', 'lapidose', 'sepaloid'], + 'separable': ['separable', 'spareable'], + 'separate': ['asperate', 'separate'], + 'separation': ['anisoptera', 'asperation', 'separation'], + 'sephardi': ['diphaser', 'parished', 'raphides', 'sephardi'], + 'sephen': ['sephen', 'sphene'], + 'sepian': ['sepian', 'spinae'], + 'sepic': ['sepic', 'spice'], + 'sepion': ['espino', 'sepion'], + 'sepoy': ['poesy', 'posey', 'sepoy'], + 'seps': ['pess', 'seps'], + 'sepsis': ['sepsis', 'speiss'], + 'sept': ['pest', 'sept', 'spet', 'step'], + 'septa': ['paste', 'septa', 'spate'], + 'septal': ['pastel', 'septal', 'staple'], + 'septane': ['penates', 'septane'], + 'septarium': ['impasture', 'septarium'], + 'septenar': ['entrepas', 'septenar'], + 'septennium': ['pennisetum', 'septennium'], + 'septentrio': ['septentrio', 'tripestone'], + 'septerium': ['misrepute', 'septerium'], + 'septi': ['septi', 'spite', 'stipe'], + 'septicemia': ['episematic', 'septicemia'], + 'septicidal': ['pesticidal', 'septicidal'], + 'septicopyemia': ['pyosepticemia', 'septicopyemia'], + 'septicopyemic': ['pyosepticemic', 'septicopyemic'], + 'septier': ['respite', 'septier'], + 'septiferous': ['pestiferous', 'septiferous'], + 'septile': ['epistle', 'septile'], + 'septimal': ['petalism', 'septimal'], + 'septocosta': ['septocosta', 'statoscope'], + 'septoic': ['poetics', 'septoic'], + 'septonasal': ['nasoseptal', 'septonasal'], + 'septoria': ['isoptera', 'septoria'], + 'septum': ['septum', 'upstem'], + 'septuor': ['petrous', 'posture', 'proetus', 'proteus', 'septuor', 'spouter'], + 'sequential': ['latinesque', 'sequential'], + 'sequin': ['quinse', 'sequin'], + 'ser': ['ers', 'ser'], + 'sera': ['arse', 'rase', 'sare', 'sear', 'sera'], + 'serab': ['barse', 'besra', 'saber', 'serab'], + 'serabend': ['seerband', 'serabend'], + 'seraglio': ['girasole', 'seraglio'], + 'serai': ['aries', 'arise', 'raise', 'serai'], + 'serail': ['israel', 'relais', 'resail', 'sailer', 'serail', 'serial'], + 'seral': ['arles', 'arsle', 'laser', 'seral', 'slare'], + 'serang': ['angers', 'sanger', 'serang'], + 'serape': ['parsee', 'persae', 'persea', 'serape'], + 'seraph': ['phrase', 'seraph', 'shaper', 'sherpa'], + 'seraphic': ['parchesi', 'seraphic'], + 'seraphim': ['samphire', 'seraphim'], + 'seraphina': ['pharisean', 'seraphina'], + 'seraphine': ['hesperian', 'phrenesia', 'seraphine'], + 'seraphism': ['misphrase', 'seraphism'], + 'serapic': ['epacris', 'scrapie', 'serapic'], + 'serapis': ['paresis', 'serapis'], + 'serapist': ['piratess', 'serapist', 'tarsipes'], + 'serau': ['serau', 'urase'], + 'seraw': ['resaw', 'sawer', 'seraw', 'sware', 'swear', 'warse'], + 'sercial': ['scleria', 'sercial'], + 'sere': ['erse', 'rees', 'seer', 'sere'], + 'serean': ['serean', 'serena'], + 'sereh': ['herse', 'sereh', 'sheer', 'shree'], + 'serena': ['serean', 'serena'], + 'serenata': ['arsenate', 'serenata'], + 'serene': ['resene', 'serene'], + 'serenoa': ['arenose', 'serenoa'], + 'serge': ['reges', 'serge'], + 'sergeant': ['estrange', 'segreant', 'sergeant', 'sternage'], + 'sergei': ['sergei', 'sieger'], + 'serger': ['gerres', 'serger'], + 'serging': ['serging', 'snigger'], + 'sergiu': ['guiser', 'sergiu'], + 'seri': ['reis', 'rise', 'seri', 'sier', 'sire'], + 'serial': ['israel', 'relais', 'resail', 'sailer', 'serail', 'serial'], + 'serialist': ['eristalis', 'serialist'], + 'serian': ['arisen', 'arsine', 'resina', 'serian'], + 'sericate': ['ecrasite', 'sericate'], + 'sericated': ['discreate', 'sericated'], + 'sericin': ['irenics', 'resinic', 'sericin', 'sirenic'], + 'serific': ['friesic', 'serific'], + 'serin': ['reins', 'resin', 'rinse', 'risen', 'serin', 'siren'], + 'serine': ['inseer', 'nereis', 'seiner', 'serine', 'sirene'], + 'serinette': ['retistene', 'serinette'], + 'seringa': ['searing', 'seringa'], + 'seringal': ['resignal', 'seringal', 'signaler'], + 'serinus': ['russine', 'serinus', 'sunrise'], + 'serio': ['osier', 'serio'], + 'seriola': ['rosalie', 'seriola'], + 'serioludicrous': ['ludicroserious', 'serioludicrous'], + 'sermo': ['meros', 'mores', 'morse', 'sermo', 'smore'], + 'sermonist': ['monitress', 'sermonist'], + 'sero': ['eros', 'rose', 'sero', 'sore'], + 'serofibrous': ['fibroserous', 'serofibrous'], + 'serolin': ['resinol', 'serolin'], + 'seromucous': ['mucoserous', 'seromucous'], + 'seron': ['norse', 'noser', 'seron', 'snore'], + 'seroon': ['nooser', 'seroon', 'sooner'], + 'seroot': ['seroot', 'sooter', 'torose'], + 'serotina': ['arsonite', 'asterion', 'oestrian', 'rosinate', 'serotina'], + 'serotinal': ['lairstone', 'orleanist', 'serotinal'], + 'serotine': ['serotine', 'torinese'], + 'serous': ['serous', 'souser'], + 'serow': ['owser', 'resow', 'serow', 'sower', 'swore', 'worse'], + 'serpari': ['aspirer', 'praiser', 'serpari'], + 'serpent': ['penster', 'present', 'serpent', 'strepen'], + 'serpentian': ['serpentian', 'serpentina'], + 'serpentid': ['president', 'serpentid'], + 'serpentina': ['serpentian', 'serpentina'], + 'serpentinous': ['serpentinous', 'supertension'], + 'serpently': ['presently', 'serpently'], + 'serpiginous': ['serpiginous', 'spinigerous'], + 'serpolet': ['proteles', 'serpolet'], + 'serpula': ['perusal', 'serpula'], + 'serpulae': ['pleasure', 'serpulae'], + 'serpulan': ['purslane', 'serpulan', 'supernal'], + 'serpulidae': ['serpulidae', 'superideal'], + 'serpuline': ['serpuline', 'superline'], + 'serra': ['ersar', 'raser', 'serra'], + 'serrage': ['argeers', 'greaser', 'serrage'], + 'serran': ['serran', 'snarer'], + 'serrano': ['serrano', 'sornare'], + 'serratic': ['crateris', 'serratic'], + 'serratodentate': ['dentatoserrate', 'serratodentate'], + 'serrature': ['serrature', 'treasurer'], + 'serried': ['derries', 'desirer', 'resider', 'serried'], + 'serriped': ['presider', 'serriped'], + 'sert': ['rest', 'sert', 'stre'], + 'serta': ['aster', 'serta', 'stare', 'strae', 'tarse', 'teras'], + 'sertum': ['muster', 'sertum', 'stumer'], + 'serum': ['muser', 'remus', 'serum'], + 'serut': ['serut', 'strue', 'turse', 'uster'], + 'servable': ['beslaver', 'servable', 'versable'], + 'servage': ['gervase', 'greaves', 'servage'], + 'serval': ['salver', 'serval', 'slaver', 'versal'], + 'servant': ['servant', 'versant'], + 'servation': ['overstain', 'servation', 'versation'], + 'serve': ['serve', 'sever', 'verse'], + 'server': ['revers', 'server', 'verser'], + 'servet': ['revest', 'servet', 'sterve', 'verset', 'vester'], + 'servetian': ['invertase', 'servetian'], + 'servian': ['servian', 'vansire'], + 'service': ['cerevis', 'scrieve', 'service'], + 'serviceable': ['receivables', 'serviceable'], + 'servient': ['reinvest', 'servient'], + 'serviential': ['inversatile', 'serviential'], + 'servilize': ['servilize', 'silverize'], + 'servite': ['restive', 'servite'], + 'servitor': ['overstir', 'servitor'], + 'servitude': ['detrusive', 'divesture', 'servitude'], + 'servo': ['servo', 'verso'], + 'sesma': ['masse', 'sesma'], + 'sestertium': ['sestertium', 'trusteeism'], + 'sestet': ['sestet', 'testes', 'tsetse'], + 'sestiad': ['disseat', 'sestiad'], + 'sestian': ['entasis', 'sestian', 'sestina'], + 'sestina': ['entasis', 'sestian', 'sestina'], + 'sestole': ['osselet', 'sestole', 'toeless'], + 'sestuor': ['estrous', 'oestrus', 'sestuor', 'tussore'], + 'sesuto': ['sesuto', 'setous'], + 'seta': ['ates', 'east', 'eats', 'sate', 'seat', 'seta'], + 'setae': ['setae', 'tease'], + 'setal': ['least', 'setal', 'slate', 'stale', 'steal', 'stela', 'tales'], + 'setaria': ['asarite', 'asteria', 'atresia', 'setaria'], + 'setback': ['backset', 'setback'], + 'setdown': ['downset', 'setdown'], + 'seth': ['esth', 'hest', 'seth'], + 'sethead': ['headset', 'sethead'], + 'sethian': ['sethian', 'sthenia'], + 'sethic': ['ethics', 'sethic'], + 'setibo': ['setibo', 'sobeit'], + 'setirostral': ['latirostres', 'setirostral'], + 'setline': ['leisten', 'setline', 'tensile'], + 'setoff': ['offset', 'setoff'], + 'seton': ['onset', 'seton', 'steno', 'stone'], + 'setous': ['sesuto', 'setous'], + 'setout': ['outset', 'setout'], + 'setover': ['overset', 'setover'], + 'sett': ['sett', 'stet', 'test'], + 'settable': ['settable', 'testable'], + 'settaine': ['anisette', 'atestine', 'settaine'], + 'settee': ['settee', 'testee'], + 'setter': ['retest', 'setter', 'street', 'tester'], + 'setting': ['setting', 'testing'], + 'settler': ['settler', 'sterlet', 'trestle'], + 'settlor': ['settlor', 'slotter'], + 'setula': ['salute', 'setula'], + 'setup': ['setup', 'stupe', 'upset'], + 'setwall': ['setwall', 'swallet'], + 'seven': ['evens', 'seven'], + 'sevener': ['sevener', 'veneres'], + 'sever': ['serve', 'sever', 'verse'], + 'severer': ['reserve', 'resever', 'reverse', 'severer'], + 'sew': ['sew', 'wes'], + 'sewed': ['sewed', 'swede'], + 'sewer': ['resew', 'sewer', 'sweer'], + 'sewered': ['sewered', 'sweered'], + 'sewing': ['sewing', 'swinge'], + 'sewn': ['news', 'sewn', 'snew'], + 'sewround': ['sewround', 'undersow'], + 'sexed': ['desex', 'sexed'], + 'sextan': ['saxten', 'sextan'], + 'sextipartition': ['extirpationist', 'sextipartition'], + 'sextodecimo': ['decimosexto', 'sextodecimo'], + 'sextry': ['sextry', 'xyster'], + 'sexuale': ['esexual', 'sexuale'], + 'sey': ['sey', 'sye', 'yes'], + 'seymour': ['mousery', 'seymour'], + 'sfoot': ['foots', 'sfoot', 'stoof'], + 'sgad': ['dags', 'sgad'], + 'sha': ['ash', 'sah', 'sha'], + 'shab': ['bash', 'shab'], + 'shabbily': ['babishly', 'shabbily'], + 'shabbiness': ['babishness', 'shabbiness'], + 'shabunder': ['husbander', 'shabunder'], + 'shad': ['dash', 'sadh', 'shad'], + 'shade': ['deash', 'hades', 'sadhe', 'shade'], + 'shaded': ['dashed', 'shaded'], + 'shader': ['dasher', 'shader', 'sheard'], + 'shadily': ['ladyish', 'shadily'], + 'shading': ['dashing', 'shading'], + 'shadkan': ['dashnak', 'shadkan'], + 'shady': ['dashy', 'shady'], + 'shafting': ['shafting', 'tangfish'], + 'shag': ['gash', 'shag'], + 'shagrag': ['ragshag', 'shagrag'], + 'shah': ['hash', 'sahh', 'shah'], + 'shahi': ['shahi', 'shiah'], + 'shaitan': ['ashanti', 'sanhita', 'shaitan', 'thasian'], + 'shaivism': ['shaivism', 'shivaism'], + 'shaka': ['kasha', 'khasa', 'sakha', 'shaka'], + 'shakeout': ['outshake', 'shakeout'], + 'shaker': ['kasher', 'shaker'], + 'shakil': ['lakish', 'shakil'], + 'shaku': ['kusha', 'shaku', 'ushak'], + 'shaky': ['hasky', 'shaky'], + 'shale': ['halse', 'leash', 'selah', 'shale', 'sheal', 'shela'], + 'shalt': ['shalt', 'slath'], + 'sham': ['mash', 'samh', 'sham'], + 'shama': ['hamsa', 'masha', 'shama'], + 'shamable': ['baalshem', 'shamable'], + 'shamal': ['mashal', 'shamal'], + 'shaman': ['ashman', 'shaman'], + 'shamba': ['ambash', 'shamba'], + 'shambrier': ['herbarism', 'shambrier'], + 'shambu': ['ambush', 'shambu'], + 'shame': ['sahme', 'shame'], + 'shamer': ['masher', 'ramesh', 'shamer'], + 'shamir': ['marish', 'shamir'], + 'shammish': ['mishmash', 'shammish'], + 'shan': ['hans', 'nash', 'shan'], + 'shane': ['ashen', 'hanse', 'shane', 'shean'], + 'shang': ['gnash', 'shang'], + 'shant': ['shant', 'snath'], + 'shap': ['hasp', 'pash', 'psha', 'shap'], + 'shape': ['heaps', 'pesah', 'phase', 'shape'], + 'shapeless': ['phaseless', 'shapeless'], + 'shaper': ['phrase', 'seraph', 'shaper', 'sherpa'], + 'shapometer': ['atmosphere', 'shapometer'], + 'shapy': ['physa', 'shapy'], + 'shardana': ['darshana', 'shardana'], + 'share': ['asher', 'share', 'shear'], + 'shareman': ['shareman', 'shearman'], + 'sharer': ['rasher', 'sharer'], + 'sharesman': ['sharesman', 'shearsman'], + 'shargar': ['shargar', 'sharrag'], + 'shari': ['ashir', 'shari'], + 'sharon': ['rhason', 'sharon', 'shoran'], + 'sharp': ['sharp', 'shrap'], + 'sharpener': ['resharpen', 'sharpener'], + 'sharper': ['phraser', 'sharper'], + 'sharpy': ['phrasy', 'sharpy'], + 'sharrag': ['shargar', 'sharrag'], + 'shasta': ['shasta', 'tassah'], + 'shaster': ['hatress', 'shaster'], + 'shastraik': ['katharsis', 'shastraik'], + 'shastri': ['sartish', 'shastri'], + 'shat': ['shat', 'tash'], + 'shatter': ['rathest', 'shatter'], + 'shatterer': ['ratherest', 'shatterer'], + 'shattering': ['shattering', 'straighten'], + 'shauri': ['shauri', 'surahi'], + 'shave': ['shave', 'sheva'], + 'shavee': ['shavee', 'sheave'], + 'shaver': ['havers', 'shaver', 'shrave'], + 'shavery': ['shavery', 'shravey'], + 'shaw': ['shaw', 'wash'], + 'shawano': ['shawano', 'washoan'], + 'shawl': ['shawl', 'walsh'], + 'shawy': ['shawy', 'washy'], + 'shay': ['ashy', 'shay'], + 'shea': ['seah', 'shea'], + 'sheal': ['halse', 'leash', 'selah', 'shale', 'sheal', 'shela'], + 'shean': ['ashen', 'hanse', 'shane', 'shean'], + 'shear': ['asher', 'share', 'shear'], + 'shearbill': ['shearbill', 'shillaber'], + 'sheard': ['dasher', 'shader', 'sheard'], + 'shearer': ['reshare', 'reshear', 'shearer'], + 'shearman': ['shareman', 'shearman'], + 'shearsman': ['sharesman', 'shearsman'], + 'sheat': ['ashet', 'haste', 'sheat'], + 'sheave': ['shavee', 'sheave'], + 'shebeen': ['benshee', 'shebeen'], + 'shechem': ['meshech', 'shechem'], + 'sheder': ['hersed', 'sheder'], + 'sheely': ['sheely', 'sheyle'], + 'sheer': ['herse', 'sereh', 'sheer', 'shree'], + 'sheering': ['greenish', 'sheering'], + 'sheet': ['sheet', 'these'], + 'sheeter': ['sheeter', 'therese'], + 'sheeting': ['seething', 'sheeting'], + 'sheila': ['elisha', 'hailse', 'sheila'], + 'shela': ['halse', 'leash', 'selah', 'shale', 'sheal', 'shela'], + 'shelf': ['flesh', 'shelf'], + 'shelfful': ['fleshful', 'shelfful'], + 'shelflist': ['filthless', 'shelflist'], + 'shelfy': ['fleshy', 'shelfy'], + 'shelta': ['haslet', 'lesath', 'shelta'], + 'shelty': ['shelty', 'thysel'], + 'shelve': ['shelve', 'shevel'], + 'shemitic': ['ethicism', 'shemitic'], + 'shen': ['nesh', 'shen'], + 'sheol': ['hosel', 'sheol', 'shole'], + 'sher': ['hers', 'resh', 'sher'], + 'sherani': ['arshine', 'nearish', 'rhesian', 'sherani'], + 'sheratan': ['hanaster', 'sheratan'], + 'sheriat': ['atheris', 'sheriat'], + 'sherif': ['fisher', 'sherif'], + 'sherifate': ['fisheater', 'sherifate'], + 'sherify': ['fishery', 'sherify'], + 'sheriyat': ['hysteria', 'sheriyat'], + 'sherpa': ['phrase', 'seraph', 'shaper', 'sherpa'], + 'sherri': ['hersir', 'sherri'], + 'sheugh': ['hughes', 'sheugh'], + 'sheva': ['shave', 'sheva'], + 'shevel': ['shelve', 'shevel'], + 'shevri': ['shevri', 'shiver', 'shrive'], + 'shewa': ['hawse', 'shewa', 'whase'], + 'sheyle': ['sheely', 'sheyle'], + 'shi': ['his', 'hsi', 'shi'], + 'shiah': ['shahi', 'shiah'], + 'shibar': ['barish', 'shibar'], + 'shice': ['echis', 'shice'], + 'shicer': ['riches', 'shicer'], + 'shide': ['shide', 'shied', 'sidhe'], + 'shied': ['shide', 'shied', 'sidhe'], + 'shiel': ['liesh', 'shiel'], + 'shieldable': ['deshabille', 'shieldable'], + 'shier': ['hirse', 'shier', 'shire'], + 'shiest': ['shiest', 'thesis'], + 'shifter': ['reshift', 'shifter'], + 'shih': ['hish', 'shih'], + 'shiite': ['histie', 'shiite'], + 'shik': ['kish', 'shik', 'sikh'], + 'shikar': ['rakish', 'riksha', 'shikar', 'shikra', 'sikhra'], + 'shikara': ['shikara', 'sikhara'], + 'shikari': ['rikisha', 'shikari'], + 'shikra': ['rakish', 'riksha', 'shikar', 'shikra', 'sikhra'], + 'shillaber': ['shearbill', 'shillaber'], + 'shimal': ['lamish', 'shimal'], + 'shimmery': ['misrhyme', 'shimmery'], + 'shin': ['hisn', 'shin', 'sinh'], + 'shina': ['naish', 'shina'], + 'shine': ['eshin', 'shine'], + 'shiner': ['renish', 'shiner', 'shrine'], + 'shingle': ['english', 'shingle'], + 'shinto': ['histon', 'shinto', 'tonish'], + 'shinty': ['shinty', 'snithy'], + 'ship': ['pish', 'ship'], + 'shipboy': ['boyship', 'shipboy'], + 'shipkeeper': ['keepership', 'shipkeeper'], + 'shiplap': ['lappish', 'shiplap'], + 'shipman': ['manship', 'shipman'], + 'shipmaster': ['mastership', 'shipmaster'], + 'shipmate': ['aphetism', 'mateship', 'shipmate', 'spithame'], + 'shipowner': ['ownership', 'shipowner'], + 'shippage': ['pageship', 'shippage'], + 'shipper': ['preship', 'shipper'], + 'shippo': ['popish', 'shippo'], + 'shipward': ['shipward', 'wardship'], + 'shipwork': ['shipwork', 'workship'], + 'shipworm': ['shipworm', 'wormship'], + 'shire': ['hirse', 'shier', 'shire'], + 'shirker': ['shirker', 'skirreh'], + 'shirley': ['relishy', 'shirley'], + 'shirty': ['shirty', 'thyris'], + 'shirvan': ['shirvan', 'varnish'], + 'shita': ['shita', 'thais'], + 'shivaism': ['shaivism', 'shivaism'], + 'shive': ['hives', 'shive'], + 'shiver': ['shevri', 'shiver', 'shrive'], + 'shlu': ['lush', 'shlu', 'shul'], + 'sho': ['sho', 'soh'], + 'shoa': ['saho', 'shoa'], + 'shoal': ['shoal', 'shola'], + 'shoat': ['hoast', 'hosta', 'shoat'], + 'shockable': ['shockable', 'shoeblack'], + 'shode': ['hosed', 'shode'], + 'shoder': ['dehors', 'rhodes', 'shoder', 'shored'], + 'shoe': ['hose', 'shoe'], + 'shoeblack': ['shockable', 'shoeblack'], + 'shoebrush': ['shoebrush', 'shorebush'], + 'shoeless': ['hoseless', 'shoeless'], + 'shoeman': ['hoseman', 'shoeman'], + 'shoer': ['horse', 'shoer', 'shore'], + 'shog': ['gosh', 'shog'], + 'shoji': ['joshi', 'shoji'], + 'shola': ['shoal', 'shola'], + 'shole': ['hosel', 'sheol', 'shole'], + 'shoo': ['shoo', 'soho'], + 'shoot': ['shoot', 'sooth', 'sotho', 'toosh'], + 'shooter': ['orthose', 'reshoot', 'shooter', 'soother'], + 'shooting': ['shooting', 'soothing'], + 'shop': ['phos', 'posh', 'shop', 'soph'], + 'shopbook': ['bookshop', 'shopbook'], + 'shopmaid': ['phasmoid', 'shopmaid'], + 'shopper': ['hoppers', 'shopper'], + 'shopwork': ['shopwork', 'workshop'], + 'shoran': ['rhason', 'sharon', 'shoran'], + 'shore': ['horse', 'shoer', 'shore'], + 'shorea': ['ahorse', 'ashore', 'hoarse', 'shorea'], + 'shorebush': ['shoebrush', 'shorebush'], + 'shored': ['dehors', 'rhodes', 'shoder', 'shored'], + 'shoreless': ['horseless', 'shoreless'], + 'shoreman': ['horseman', 'rhamnose', 'shoreman'], + 'shorer': ['horser', 'shorer'], + 'shoreward': ['drawhorse', 'shoreward'], + 'shoreweed': ['horseweed', 'shoreweed'], + 'shoring': ['horsing', 'shoring'], + 'short': ['horst', 'short'], + 'shortage': ['hostager', 'shortage'], + 'shorten': ['shorten', 'threnos'], + 'shot': ['host', 'shot', 'thos', 'tosh'], + 'shote': ['ethos', 'shote', 'those'], + 'shotgun': ['gunshot', 'shotgun', 'uhtsong'], + 'shotless': ['hostless', 'shotless'], + 'shotstar': ['shotstar', 'starshot'], + 'shou': ['huso', 'shou'], + 'shoulderer': ['reshoulder', 'shoulderer'], + 'shout': ['shout', 'south'], + 'shouter': ['shouter', 'souther'], + 'shouting': ['shouting', 'southing'], + 'shover': ['shover', 'shrove'], + 'showerer': ['reshower', 'showerer'], + 'shrab': ['brash', 'shrab'], + 'shram': ['marsh', 'shram'], + 'shrap': ['sharp', 'shrap'], + 'shrave': ['havers', 'shaver', 'shrave'], + 'shravey': ['shavery', 'shravey'], + 'shree': ['herse', 'sereh', 'sheer', 'shree'], + 'shrewly': ['shrewly', 'welshry'], + 'shriek': ['shriek', 'shrike'], + 'shrieval': ['lavisher', 'shrieval'], + 'shrike': ['shriek', 'shrike'], + 'shrine': ['renish', 'shiner', 'shrine'], + 'shrite': ['shrite', 'theirs'], + 'shrive': ['shevri', 'shiver', 'shrive'], + 'shriven': ['nervish', 'shriven'], + 'shroudy': ['hydrous', 'shroudy'], + 'shrove': ['shover', 'shrove'], + 'shrub': ['brush', 'shrub'], + 'shrubbery': ['berrybush', 'shrubbery'], + 'shrubland': ['brushland', 'shrubland'], + 'shrubless': ['brushless', 'shrubless'], + 'shrublet': ['brushlet', 'shrublet'], + 'shrublike': ['brushlike', 'shrublike'], + 'shrubwood': ['brushwood', 'shrubwood'], + 'shrug': ['grush', 'shrug'], + 'shu': ['shu', 'ush'], + 'shuba': ['shuba', 'subah'], + 'shug': ['gush', 'shug', 'sugh'], + 'shul': ['lush', 'shlu', 'shul'], + 'shulamite': ['hamulites', 'shulamite'], + 'shuler': ['lusher', 'shuler'], + 'shunless': ['lushness', 'shunless'], + 'shunter': ['reshunt', 'shunter'], + 'shure': ['shure', 'usher'], + 'shurf': ['frush', 'shurf'], + 'shut': ['shut', 'thus', 'tush'], + 'shutness': ['shutness', 'thusness'], + 'shutout': ['outshut', 'shutout'], + 'shuttering': ['hurtingest', 'shuttering'], + 'shyam': ['mashy', 'shyam'], + 'si': ['is', 'si'], + 'sia': ['sai', 'sia'], + 'siak': ['saki', 'siak', 'sika'], + 'sial': ['lasi', 'lias', 'lisa', 'sail', 'sial'], + 'sialagogic': ['isagogical', 'sialagogic'], + 'sialic': ['sialic', 'silica'], + 'sialid': ['asilid', 'sialid'], + 'sialidae': ['asilidae', 'sialidae'], + 'siam': ['mias', 'saim', 'siam', 'sima'], + 'siamese': ['misease', 'siamese'], + 'sib': ['bis', 'sib'], + 'sibyl': ['sibyl', 'sybil'], + 'sibylla': ['sibylla', 'syllabi'], + 'sicana': ['ascian', 'sacian', 'scania', 'sicana'], + 'sicani': ['anisic', 'sicani', 'sinaic'], + 'sicarius': ['acrisius', 'sicarius'], + 'siccate': ['ascetic', 'castice', 'siccate'], + 'siccation': ['cocainist', 'siccation'], + 'sice': ['cise', 'sice'], + 'sicel': ['sicel', 'slice'], + 'sicilian': ['anisilic', 'sicilian'], + 'sickbed': ['bedsick', 'sickbed'], + 'sicker': ['scrike', 'sicker'], + 'sickerly': ['sickerly', 'slickery'], + 'sickle': ['sickle', 'skelic'], + 'sickler': ['sickler', 'slicker'], + 'sicklied': ['disclike', 'sicklied'], + 'sickling': ['sickling', 'slicking'], + 'sicula': ['caulis', 'clusia', 'sicula'], + 'siculian': ['luscinia', 'siculian'], + 'sid': ['dis', 'sid'], + 'sida': ['dais', 'dasi', 'disa', 'said', 'sida'], + 'sidalcea': ['diaclase', 'sidalcea'], + 'side': ['desi', 'ides', 'seid', 'side'], + 'sidearm': ['misread', 'sidearm'], + 'sideboard': ['broadside', 'sideboard'], + 'sideburns': ['burnsides', 'sideburns'], + 'sidecar': ['diceras', 'radices', 'sidecar'], + 'sidehill': ['hillside', 'sidehill'], + 'siderean': ['arsedine', 'arsenide', 'sedanier', 'siderean'], + 'siderin': ['insider', 'siderin'], + 'sideronatrite': ['endoarteritis', 'sideronatrite'], + 'siderous': ['desirous', 'siderous'], + 'sidership': ['sidership', 'spiderish'], + 'sidesway': ['sidesway', 'sideways'], + 'sidetrack': ['sidetrack', 'trackside'], + 'sidewalk': ['sidewalk', 'walkside'], + 'sideway': ['sideway', 'wayside'], + 'sideways': ['sidesway', 'sideways'], + 'sidhe': ['shide', 'shied', 'sidhe'], + 'sidle': ['sidle', 'slide'], + 'sidler': ['sidler', 'slider'], + 'sidling': ['sidling', 'sliding'], + 'sidlingly': ['sidlingly', 'slidingly'], + 'sieger': ['sergei', 'sieger'], + 'siena': ['anise', 'insea', 'siena', 'sinae'], + 'sienna': ['insane', 'sienna'], + 'sier': ['reis', 'rise', 'seri', 'sier', 'sire'], + 'sierra': ['raiser', 'sierra'], + 'siesta': ['siesta', 'tassie'], + 'siever': ['revise', 'siever'], + 'sife': ['feis', 'fise', 'sife'], + 'sift': ['fist', 'sift'], + 'sifted': ['fisted', 'sifted'], + 'sifter': ['fister', 'resift', 'sifter', 'strife'], + 'sifting': ['fisting', 'sifting'], + 'sigh': ['gish', 'sigh'], + 'sigher': ['resigh', 'sigher'], + 'sighted': ['desight', 'sighted'], + 'sightlily': ['sightlily', 'slightily'], + 'sightliness': ['sightliness', 'slightiness'], + 'sightly': ['sightly', 'slighty'], + 'sigillated': ['distillage', 'sigillated'], + 'sigla': ['gisla', 'ligas', 'sigla'], + 'sigmatism': ['astigmism', 'sigmatism'], + 'sigmoidal': ['dialogism', 'sigmoidal'], + 'sign': ['sign', 'sing', 'snig'], + 'signable': ['signable', 'singable'], + 'signalee': ['ensilage', 'genesial', 'signalee'], + 'signaler': ['resignal', 'seringal', 'signaler'], + 'signalese': ['agileness', 'signalese'], + 'signally': ['signally', 'singally', 'slangily'], + 'signary': ['signary', 'syringa'], + 'signate': ['easting', + 'gainset', + 'genista', + 'ingesta', + 'seating', + 'signate', + 'teasing'], + 'signator': ['orangist', 'organist', 'roasting', 'signator'], + 'signee': ['seeing', 'signee'], + 'signer': ['resign', 'resing', 'signer', 'singer'], + 'signet': ['ingest', 'signet', 'stinge'], + 'signorial': ['sailoring', 'signorial'], + 'signpost': ['postsign', 'signpost'], + 'signum': ['musing', 'signum'], + 'sika': ['saki', 'siak', 'sika'], + 'sikar': ['kisra', 'sikar', 'skair'], + 'siket': ['siket', 'skite'], + 'sikh': ['kish', 'shik', 'sikh'], + 'sikhara': ['shikara', 'sikhara'], + 'sikhra': ['rakish', 'riksha', 'shikar', 'shikra', 'sikhra'], + 'sil': ['lis', 'sil'], + 'silane': ['alsine', 'neslia', 'saline', 'selina', 'silane'], + 'silas': ['silas', 'sisal'], + 'silcrete': ['sclerite', 'silcrete'], + 'sile': ['isle', 'lise', 'sile'], + 'silen': ['elsin', 'lenis', 'niels', 'silen', 'sline'], + 'silence': ['license', 'selenic', 'silence'], + 'silenced': ['licensed', 'silenced'], + 'silencer': ['licenser', 'silencer'], + 'silene': ['enisle', 'ensile', 'senile', 'silene'], + 'silent': ['enlist', 'listen', 'silent', 'tinsel'], + 'silently': ['silently', 'tinselly'], + 'silenus': ['insulse', 'silenus'], + 'silesian': ['sensilia', 'silesian'], + 'silica': ['sialic', 'silica'], + 'silicam': ['islamic', 'laicism', 'silicam'], + 'silicane': ['silicane', 'silicean'], + 'silicean': ['silicane', 'silicean'], + 'siliceocalcareous': ['calcareosiliceous', 'siliceocalcareous'], + 'silicoaluminate': ['aluminosilicate', 'silicoaluminate'], + 'silicone': ['isocline', 'silicone'], + 'silicotitanate': ['silicotitanate', 'titanosilicate'], + 'silicotungstate': ['silicotungstate', 'tungstosilicate'], + 'silicotungstic': ['silicotungstic', 'tungstosilicic'], + 'silk': ['lisk', 'silk', 'skil'], + 'silkaline': ['silkaline', 'snaillike'], + 'silkman': ['klanism', 'silkman'], + 'silkness': ['silkness', 'sinkless', 'skinless'], + 'silly': ['silly', 'silyl'], + 'sillyhow': ['lowishly', 'owlishly', 'sillyhow'], + 'silo': ['lois', 'silo', 'siol', 'soil', 'soli'], + 'silpha': ['palish', 'silpha'], + 'silt': ['list', 'silt', 'slit'], + 'silting': ['listing', 'silting'], + 'siltlike': ['siltlike', 'slitlike'], + 'silva': ['silva', 'slavi'], + 'silver': ['silver', 'sliver'], + 'silvered': ['desilver', 'silvered'], + 'silverer': ['resilver', 'silverer', 'sliverer'], + 'silverize': ['servilize', 'silverize'], + 'silverlike': ['silverlike', 'sliverlike'], + 'silverwood': ['silverwood', 'woodsilver'], + 'silvery': ['silvery', 'slivery'], + 'silvester': ['rivetless', 'silvester'], + 'silyl': ['silly', 'silyl'], + 'sim': ['ism', 'sim'], + 'sima': ['mias', 'saim', 'siam', 'sima'], + 'simal': ['islam', 'ismal', 'simal'], + 'simar': ['maris', 'marsi', 'samir', 'simar'], + 'sime': ['mise', 'semi', 'sime'], + 'simeon': ['eonism', 'mesion', 'oneism', 'simeon'], + 'simeonism': ['misoneism', 'simeonism'], + 'simiad': ['idiasm', 'simiad'], + 'simile': ['milsie', 'simile'], + 'simity': ['myitis', 'simity'], + 'simling': ['simling', 'smiling'], + 'simmer': ['merism', 'mermis', 'simmer'], + 'simmon': ['monism', 'nomism', 'simmon'], + 'simon': ['minos', 'osmin', 'simon'], + 'simonian': ['insomnia', 'simonian'], + 'simonist': ['simonist', 'sintoism'], + 'simony': ['isonym', 'myosin', 'simony'], + 'simple': ['mespil', 'simple'], + 'simpleton': ['simpleton', 'spoilment'], + 'simplicist': ['simplicist', 'simplistic'], + 'simplistic': ['simplicist', 'simplistic'], + 'simply': ['limpsy', 'simply'], + 'simson': ['nosism', 'simson'], + 'simulance': ['masculine', 'semuncial', 'simulance'], + 'simulcast': ['masculist', 'simulcast'], + 'simuler': ['misrule', 'simuler'], + 'sina': ['anis', 'nais', 'nasi', 'nias', 'sain', 'sina'], + 'sinae': ['anise', 'insea', 'siena', 'sinae'], + 'sinaean': ['nisaean', 'sinaean'], + 'sinaic': ['anisic', 'sicani', 'sinaic'], + 'sinaitic': ['isatinic', 'sinaitic'], + 'sinal': ['sinal', 'slain', 'snail'], + 'sinapic': ['panisic', 'piscian', 'piscina', 'sinapic'], + 'since': ['senci', 'since'], + 'sincere': ['ceresin', 'sincere'], + 'sinecure': ['insecure', 'sinecure'], + 'sinew': ['sinew', 'swine', 'wisen'], + 'sinewed': ['endwise', 'sinewed'], + 'sinewy': ['sinewy', 'swiney'], + 'sinfonia': ['sainfoin', 'sinfonia'], + 'sinfonietta': ['festination', 'infestation', 'sinfonietta'], + 'sing': ['sign', 'sing', 'snig'], + 'singable': ['signable', 'singable'], + 'singally': ['signally', 'singally', 'slangily'], + 'singarip': ['aspiring', 'praising', 'singarip'], + 'singed': ['design', 'singed'], + 'singer': ['resign', 'resing', 'signer', 'singer'], + 'single': ['single', 'slinge'], + 'singler': ['singler', 'slinger'], + 'singles': ['essling', 'singles'], + 'singlet': ['glisten', 'singlet'], + 'sinh': ['hisn', 'shin', 'sinh'], + 'sinico': ['inosic', 'sinico'], + 'sinister': ['insister', 'reinsist', 'sinister', 'sisterin'], + 'sinistrodextral': ['dextrosinistral', 'sinistrodextral'], + 'sink': ['inks', 'sink', 'skin'], + 'sinker': ['resink', 'reskin', 'sinker'], + 'sinkhead': ['headskin', 'nakedish', 'sinkhead'], + 'sinkless': ['silkness', 'sinkless', 'skinless'], + 'sinklike': ['sinklike', 'skinlike'], + 'sinnet': ['innest', 'sennit', 'sinnet', 'tennis'], + 'sinoatrial': ['sinoatrial', 'solitarian'], + 'sinogram': ['orangism', 'organism', 'sinogram'], + 'sinolog': ['loosing', 'sinolog'], + 'sinopia': ['pisonia', 'sinopia'], + 'sinople': ['epsilon', 'sinople'], + 'sinter': ['estrin', 'insert', 'sinter', 'sterin', 'triens'], + 'sinto': ['sinto', 'stion'], + 'sintoc': ['nostic', 'sintoc', 'tocsin'], + 'sintoism': ['simonist', 'sintoism'], + 'sintu': ['sintu', 'suint'], + 'sinuatodentate': ['dentatosinuate', 'sinuatodentate'], + 'sinuose': ['sinuose', 'suiones'], + 'sinus': ['nisus', 'sinus'], + 'sinward': ['inwards', 'sinward'], + 'siol': ['lois', 'silo', 'siol', 'soil', 'soli'], + 'sionite': ['inosite', 'sionite'], + 'sip': ['psi', 'sip'], + 'sipe': ['pise', 'sipe'], + 'siper': ['siper', 'spier', 'spire'], + 'siphonal': ['nailshop', 'siphonal'], + 'siphuncle': ['siphuncle', 'uncleship'], + 'sipling': ['sipling', 'spiling'], + 'sipylite': ['pyelitis', 'sipylite'], + 'sir': ['sir', 'sri'], + 'sire': ['reis', 'rise', 'seri', 'sier', 'sire'], + 'siredon': ['indorse', 'ordines', 'siredon', 'sordine'], + 'siren': ['reins', 'resin', 'rinse', 'risen', 'serin', 'siren'], + 'sirene': ['inseer', 'nereis', 'seiner', 'serine', 'sirene'], + 'sirenic': ['irenics', 'resinic', 'sericin', 'sirenic'], + 'sirenize': ['resinize', 'sirenize'], + 'sirenlike': ['resinlike', 'sirenlike'], + 'sirenoid': ['derision', 'ironside', 'resinoid', 'sirenoid'], + 'sireny': ['resiny', 'sireny'], + 'sirian': ['raisin', 'sirian'], + 'sirih': ['irish', 'rishi', 'sirih'], + 'sirky': ['risky', 'sirky'], + 'sirmian': ['iranism', 'sirmian'], + 'sirpea': ['aspire', 'paries', 'praise', 'sirpea', 'spirea'], + 'sirple': ['lisper', 'pliers', 'sirple', 'spiler'], + 'sirrah': ['arrish', 'harris', 'rarish', 'sirrah'], + 'sirree': ['rerise', 'sirree'], + 'siruelas': ['russelia', 'siruelas'], + 'sirup': ['prius', 'sirup'], + 'siruper': ['siruper', 'upriser'], + 'siryan': ['siryan', 'syrian'], + 'sis': ['sis', 'ssi'], + 'sisal': ['silas', 'sisal'], + 'sish': ['hiss', 'sish'], + 'sisham': ['samish', 'sisham'], + 'sisi': ['isis', 'sisi'], + 'sisseton': ['sisseton', 'stenosis'], + 'sistani': ['nasitis', 'sistani'], + 'sister': ['resist', 'restis', 'sister'], + 'sisterin': ['insister', 'reinsist', 'sinister', 'sisterin'], + 'sistering': ['resisting', 'sistering'], + 'sisterless': ['resistless', 'sisterless'], + 'sistrum': ['sistrum', 'trismus'], + 'sit': ['ist', 'its', 'sit'], + 'sita': ['atis', 'sita', 'tsia'], + 'sitao': ['sitao', 'staio'], + 'sitar': ['arist', + 'astir', + 'sitar', + 'stair', + 'stria', + 'tarsi', + 'tisar', + 'trias'], + 'sitch': ['sitch', 'stchi', 'stich'], + 'site': ['seit', 'site'], + 'sith': ['hist', 'sith', 'this', 'tshi'], + 'sithens': ['sithens', 'thissen'], + 'sitient': ['sitient', 'sittine'], + 'sitology': ['sitology', 'tsiology'], + 'sittinae': ['satinite', 'sittinae'], + 'sittine': ['sitient', 'sittine'], + 'situal': ['situal', 'situla', 'tulasi'], + 'situate': ['situate', 'usitate'], + 'situla': ['situal', 'situla', 'tulasi'], + 'situs': ['situs', 'suist'], + 'siva': ['avis', 'siva', 'visa'], + 'sivaism': ['saivism', 'sivaism'], + 'sivan': ['savin', 'sivan'], + 'siwan': ['siwan', 'swain'], + 'siwash': ['sawish', 'siwash'], + 'sixte': ['exist', 'sixte'], + 'sixty': ['sixty', 'xysti'], + 'sizeable': ['seizable', 'sizeable'], + 'sizeman': ['sizeman', 'zamenis'], + 'skair': ['kisra', 'sikar', 'skair'], + 'skal': ['lask', 'skal'], + 'skance': ['sacken', 'skance'], + 'skanda': ['sandak', 'skanda'], + 'skart': ['karst', 'skart', 'stark'], + 'skat': ['skat', 'task'], + 'skate': ['skate', 'stake', 'steak'], + 'skater': ['skater', 'staker', 'strake', 'streak', 'tasker'], + 'skating': ['gitksan', 'skating', 'takings'], + 'skean': ['skean', 'snake', 'sneak'], + 'skee': ['kees', 'seek', 'skee'], + 'skeel': ['skeel', 'sleek'], + 'skeeling': ['skeeling', 'sleeking'], + 'skeely': ['skeely', 'sleeky'], + 'skeen': ['skeen', 'skene'], + 'skeer': ['esker', 'keres', 'reesk', 'seker', 'skeer', 'skere'], + 'skeery': ['kersey', 'skeery'], + 'skeet': ['keest', 'skeet', 'skete', 'steek'], + 'skeeter': ['skeeter', 'teskere'], + 'skeletin': ['nestlike', 'skeletin'], + 'skelic': ['sickle', 'skelic'], + 'skelp': ['skelp', 'spelk'], + 'skelter': ['kestrel', 'skelter'], + 'skene': ['skeen', 'skene'], + 'skeo': ['skeo', 'soke'], + 'skeptic': ['skeptic', 'spicket'], + 'skere': ['esker', 'keres', 'reesk', 'seker', 'skeer', 'skere'], + 'sketcher': ['resketch', 'sketcher'], + 'skete': ['keest', 'skeet', 'skete', 'steek'], + 'skey': ['skey', 'skye'], + 'skid': ['disk', 'kids', 'skid'], + 'skier': ['kreis', 'skier'], + 'skil': ['lisk', 'silk', 'skil'], + 'skin': ['inks', 'sink', 'skin'], + 'skinch': ['chinks', 'skinch'], + 'skinless': ['silkness', 'sinkless', 'skinless'], + 'skinlike': ['sinklike', 'skinlike'], + 'skip': ['pisk', 'skip'], + 'skippel': ['skippel', 'skipple'], + 'skipple': ['skippel', 'skipple'], + 'skirmish': ['skirmish', 'smirkish'], + 'skirreh': ['shirker', 'skirreh'], + 'skirret': ['skirret', 'skirter', 'striker'], + 'skirt': ['skirt', 'stirk'], + 'skirter': ['skirret', 'skirter', 'striker'], + 'skirting': ['skirting', 'striking'], + 'skirtingly': ['skirtingly', 'strikingly'], + 'skirty': ['kirsty', 'skirty'], + 'skit': ['kist', 'skit'], + 'skite': ['siket', 'skite'], + 'skiter': ['skiter', 'strike'], + 'skittle': ['kittles', 'skittle'], + 'sklate': ['lasket', 'sklate'], + 'sklater': ['sklater', 'stalker'], + 'sklinter': ['sklinter', 'strinkle'], + 'skoal': ['skoal', 'sloka'], + 'skoo': ['koso', 'skoo', 'sook'], + 'skua': ['kusa', 'skua'], + 'skun': ['skun', 'sunk'], + 'skye': ['skey', 'skye'], + 'sla': ['las', 'sal', 'sla'], + 'slab': ['blas', 'slab'], + 'slacken': ['slacken', 'snackle'], + 'slade': ['leads', 'slade'], + 'slae': ['elsa', 'sale', 'seal', 'slae'], + 'slain': ['sinal', 'slain', 'snail'], + 'slainte': ['elastin', 'salient', 'saltine', 'slainte'], + 'slait': ['alist', 'litas', 'slait', 'talis'], + 'slake': ['alkes', 'sakel', 'slake'], + 'slam': ['alms', 'salm', 'slam'], + 'slamp': ['plasm', 'psalm', 'slamp'], + 'slandering': ['sanderling', 'slandering'], + 'slane': ['ansel', 'slane'], + 'slang': ['glans', 'slang'], + 'slangily': ['signally', 'singally', 'slangily'], + 'slangish': ['slangish', 'slashing'], + 'slangishly': ['slangishly', 'slashingly'], + 'slangster': ['slangster', 'strangles'], + 'slap': ['salp', 'slap'], + 'slape': ['elaps', + 'lapse', + 'lepas', + 'pales', + 'salep', + 'saple', + 'sepal', + 'slape', + 'spale', + 'speal'], + 'slare': ['arles', 'arsle', 'laser', 'seral', 'slare'], + 'slasher': ['reslash', 'slasher'], + 'slashing': ['slangish', 'slashing'], + 'slashingly': ['slangishly', 'slashingly'], + 'slat': ['last', 'salt', 'slat'], + 'slate': ['least', 'setal', 'slate', 'stale', 'steal', 'stela', 'tales'], + 'slater': ['laster', + 'lastre', + 'rastle', + 'relast', + 'resalt', + 'salter', + 'slater', + 'stelar'], + 'slath': ['shalt', 'slath'], + 'slather': ['hastler', 'slather'], + 'slatiness': ['saintless', 'saltiness', 'slatiness', 'stainless'], + 'slating': ['anglist', 'lasting', 'salting', 'slating', 'staling'], + 'slatish': ['saltish', 'slatish'], + 'slatter': ['rattles', 'slatter', 'starlet', 'startle'], + 'slaty': ['lasty', 'salty', 'slaty'], + 'slaughter': ['lethargus', 'slaughter'], + 'slaughterman': ['manslaughter', 'slaughterman'], + 'slaum': ['lamus', 'malus', 'musal', 'slaum'], + 'slave': ['salve', 'selva', 'slave', 'valse'], + 'slaver': ['salver', 'serval', 'slaver', 'versal'], + 'slaverer': ['reserval', 'reversal', 'slaverer'], + 'slavey': ['slavey', 'sylvae'], + 'slavi': ['silva', 'slavi'], + 'slavian': ['salivan', 'slavian'], + 'slavic': ['clavis', 'slavic'], + 'slavonic': ['slavonic', 'volscian'], + 'slay': ['lyas', 'slay'], + 'slayer': ['reslay', 'slayer'], + 'sleave': ['leaves', 'sleave'], + 'sledger': ['redlegs', 'sledger'], + 'slee': ['else', 'lees', 'seel', 'sele', 'slee'], + 'sleech': ['lesche', 'sleech'], + 'sleek': ['skeel', 'sleek'], + 'sleeking': ['skeeling', 'sleeking'], + 'sleeky': ['skeely', 'sleeky'], + 'sleep': ['sleep', 'speel'], + 'sleepless': ['sleepless', 'speelless'], + 'sleepry': ['presley', 'sleepry'], + 'sleet': ['sleet', 'slete', 'steel', 'stele'], + 'sleetiness': ['sleetiness', 'steeliness'], + 'sleeting': ['sleeting', 'steeling'], + 'sleetproof': ['sleetproof', 'steelproof'], + 'sleety': ['sleety', 'steely'], + 'slept': ['slept', 'spelt', 'splet'], + 'slete': ['sleet', 'slete', 'steel', 'stele'], + 'sleuth': ['hustle', 'sleuth'], + 'slew': ['slew', 'wels'], + 'slewing': ['slewing', 'swingle'], + 'sley': ['lyse', 'sley'], + 'slice': ['sicel', 'slice'], + 'slicht': ['slicht', 'slitch'], + 'slicken': ['slicken', 'snickle'], + 'slicker': ['sickler', 'slicker'], + 'slickery': ['sickerly', 'slickery'], + 'slicking': ['sickling', 'slicking'], + 'slidable': ['sabellid', 'slidable'], + 'slidden': ['slidden', 'sniddle'], + 'slide': ['sidle', 'slide'], + 'slider': ['sidler', 'slider'], + 'sliding': ['sidling', 'sliding'], + 'slidingly': ['sidlingly', 'slidingly'], + 'slifter': ['slifter', 'stifler'], + 'slightily': ['sightlily', 'slightily'], + 'slightiness': ['sightliness', 'slightiness'], + 'slighty': ['sightly', 'slighty'], + 'slime': ['limes', 'miles', 'slime', 'smile'], + 'slimeman': ['melanism', 'slimeman'], + 'slimer': ['slimer', 'smiler'], + 'slimy': ['limsy', 'slimy', 'smily'], + 'sline': ['elsin', 'lenis', 'niels', 'silen', 'sline'], + 'slinge': ['single', 'slinge'], + 'slinger': ['singler', 'slinger'], + 'slink': ['links', 'slink'], + 'slip': ['lisp', 'slip'], + 'slipcoat': ['postical', 'slipcoat'], + 'slipe': ['piles', 'plies', 'slipe', 'spiel', 'spile'], + 'slipover': ['overslip', 'slipover'], + 'slipway': ['slipway', 'waspily'], + 'slit': ['list', 'silt', 'slit'], + 'slitch': ['slicht', 'slitch'], + 'slite': ['islet', 'istle', 'slite', 'stile'], + 'slithy': ['hylist', 'slithy'], + 'slitless': ['listless', 'slitless'], + 'slitlike': ['siltlike', 'slitlike'], + 'slitted': ['slitted', 'stilted'], + 'slitter': ['litster', 'slitter', 'stilter', 'testril'], + 'slitty': ['slitty', 'stilty'], + 'slive': ['elvis', 'levis', 'slive'], + 'sliver': ['silver', 'sliver'], + 'sliverer': ['resilver', 'silverer', 'sliverer'], + 'sliverlike': ['silverlike', 'sliverlike'], + 'slivery': ['silvery', 'slivery'], + 'sloan': ['salon', 'sloan', 'solan'], + 'slod': ['slod', 'sold'], + 'sloe': ['lose', 'sloe', 'sole'], + 'sloka': ['skoal', 'sloka'], + 'slone': ['slone', 'solen'], + 'sloo': ['sloo', 'solo', 'sool'], + 'sloom': ['mools', 'sloom'], + 'sloop': ['polos', 'sloop', 'spool'], + 'slope': ['elops', 'slope', 'spole'], + 'sloper': ['sloper', 'splore'], + 'slot': ['lost', 'lots', 'slot'], + 'slote': ['slote', 'stole'], + 'sloted': ['sloted', 'stoled'], + 'slotter': ['settlor', 'slotter'], + 'slouch': ['holcus', 'lochus', 'slouch'], + 'slouchiness': ['cushionless', 'slouchiness'], + 'slouchy': ['chylous', 'slouchy'], + 'slovenian': ['slovenian', 'venosinal'], + 'slow': ['slow', 'sowl'], + 'slud': ['slud', 'suld'], + 'slue': ['lues', 'slue'], + 'sluit': ['litus', 'sluit', 'tulsi'], + 'slunge': ['gunsel', 'selung', 'slunge'], + 'slurp': ['slurp', 'spurl'], + 'slut': ['lust', 'slut'], + 'sluther': ['hulster', 'hustler', 'sluther'], + 'slutter': ['slutter', 'trustle'], + 'sly': ['lys', 'sly'], + 'sma': ['mas', 'sam', 'sma'], + 'smachrie': ['semiarch', 'smachrie'], + 'smallen': ['ensmall', 'smallen'], + 'smalltime': ['metallism', 'smalltime'], + 'smaltine': ['mentalis', 'smaltine', 'stileman'], + 'smaltite': ['metalist', 'smaltite'], + 'smart': ['smart', 'stram'], + 'smarten': ['sarment', 'smarten'], + 'smashage': ['gamashes', 'smashage'], + 'smeary': ['ramsey', 'smeary'], + 'smectis': ['sectism', 'smectis'], + 'smee': ['mese', 'seem', 'seme', 'smee'], + 'smeech': ['scheme', 'smeech'], + 'smeek': ['meeks', 'smeek'], + 'smeer': ['merse', 'smeer'], + 'smeeth': ['smeeth', 'smethe'], + 'smeller': ['resmell', 'smeller'], + 'smelly': ['mysell', 'smelly'], + 'smelter': ['melters', 'resmelt', 'smelter'], + 'smethe': ['smeeth', 'smethe'], + 'smilax': ['laxism', 'smilax'], + 'smile': ['limes', 'miles', 'slime', 'smile'], + 'smiler': ['slimer', 'smiler'], + 'smilet': ['mistle', 'smilet'], + 'smiling': ['simling', 'smiling'], + 'smily': ['limsy', 'slimy', 'smily'], + 'sminthian': ['mitannish', 'sminthian'], + 'smirch': ['chrism', 'smirch'], + 'smirkish': ['skirmish', 'smirkish'], + 'smit': ['mist', 'smit', 'stim'], + 'smite': ['metis', 'smite', 'stime', 'times'], + 'smiter': ['merist', 'mister', 'smiter'], + 'smither': ['rhemist', 'smither'], + 'smithian': ['isthmian', 'smithian'], + 'smoker': ['mosker', 'smoker'], + 'smoot': ['moost', 'smoot'], + 'smoother': ['resmooth', 'romeshot', 'smoother'], + 'smoothingly': ['hymnologist', 'smoothingly'], + 'smore': ['meros', 'mores', 'morse', 'sermo', 'smore'], + 'smote': ['moste', 'smote'], + 'smother': ['smother', 'thermos'], + 'smouse': ['mousse', 'smouse'], + 'smouser': ['osmerus', 'smouser'], + 'smuggle': ['muggles', 'smuggle'], + 'smut': ['must', 'smut', 'stum'], + 'smyrniot': ['smyrniot', 'tyronism'], + 'smyrniote': ['myristone', 'smyrniote'], + 'snab': ['nabs', 'snab'], + 'snackle': ['slacken', 'snackle'], + 'snag': ['sang', 'snag'], + 'snagrel': ['sangrel', 'snagrel'], + 'snail': ['sinal', 'slain', 'snail'], + 'snaillike': ['silkaline', 'snaillike'], + 'snaily': ['anisyl', 'snaily'], + 'snaith': ['snaith', 'tahsin'], + 'snake': ['skean', 'snake', 'sneak'], + 'snap': ['snap', 'span'], + 'snape': ['aspen', 'panse', 'snape', 'sneap', 'spane', 'spean'], + 'snaper': ['resnap', 'respan', 'snaper'], + 'snapless': ['snapless', 'spanless'], + 'snapy': ['pansy', 'snapy'], + 'snare': ['anser', 'nares', 'rasen', 'snare'], + 'snarer': ['serran', 'snarer'], + 'snaste': ['assent', 'snaste'], + 'snatch': ['chanst', 'snatch', 'stanch'], + 'snatchable': ['snatchable', 'stanchable'], + 'snatcher': ['resnatch', 'snatcher', 'stancher'], + 'snath': ['shant', 'snath'], + 'snathe': ['athens', 'hasten', 'snathe', 'sneath'], + 'snaw': ['sawn', 'snaw', 'swan'], + 'snead': ['sedan', 'snead'], + 'sneak': ['skean', 'snake', 'sneak'], + 'sneaker': ['keresan', 'sneaker'], + 'sneaksman': ['masskanne', 'sneaksman'], + 'sneap': ['aspen', 'panse', 'snape', 'sneap', 'spane', 'spean'], + 'sneath': ['athens', 'hasten', 'snathe', 'sneath'], + 'sneathe': ['sneathe', 'thesean'], + 'sned': ['send', 'sned'], + 'snee': ['ense', 'esne', 'nese', 'seen', 'snee'], + 'sneer': ['renes', 'sneer'], + 'snew': ['news', 'sewn', 'snew'], + 'snib': ['nibs', 'snib'], + 'snickle': ['slicken', 'snickle'], + 'sniddle': ['slidden', 'sniddle'], + 'snide': ['denis', 'snide'], + 'snig': ['sign', 'sing', 'snig'], + 'snigger': ['serging', 'snigger'], + 'snip': ['snip', 'spin'], + 'snipe': ['penis', 'snipe', 'spine'], + 'snipebill': ['snipebill', 'spinebill'], + 'snipelike': ['snipelike', 'spinelike'], + 'sniper': ['pernis', 'respin', 'sniper'], + 'snipocracy': ['conspiracy', 'snipocracy'], + 'snipper': ['nippers', 'snipper'], + 'snippet': ['snippet', 'stippen'], + 'snipy': ['snipy', 'spiny'], + 'snitcher': ['christen', 'snitcher'], + 'snite': ['inset', 'neist', 'snite', 'stein', 'stine', 'tsine'], + 'snithy': ['shinty', 'snithy'], + 'sniveler': ['ensilver', 'sniveler'], + 'snively': ['snively', 'sylvine'], + 'snob': ['bosn', 'nobs', 'snob'], + 'snocker': ['conkers', 'snocker'], + 'snod': ['snod', 'sond'], + 'snoek': ['snoek', 'snoke', 'soken'], + 'snog': ['snog', 'song'], + 'snoke': ['snoek', 'snoke', 'soken'], + 'snook': ['onkos', 'snook'], + 'snoop': ['snoop', 'spoon'], + 'snooper': ['snooper', 'spooner'], + 'snoopy': ['snoopy', 'spoony'], + 'snoot': ['snoot', 'stoon'], + 'snore': ['norse', 'noser', 'seron', 'snore'], + 'snorer': ['snorer', 'sorner'], + 'snoring': ['snoring', 'sorning'], + 'snork': ['norsk', 'snork'], + 'snotter': ['snotter', 'stentor', 'torsten'], + 'snout': ['notus', 'snout', 'stoun', 'tonus'], + 'snouter': ['snouter', 'tonsure', 'unstore'], + 'snow': ['snow', 'sown'], + 'snowie': ['nowise', 'snowie'], + 'snowish': ['snowish', 'whisson'], + 'snowy': ['snowy', 'wyson'], + 'snug': ['snug', 'sung'], + 'snup': ['snup', 'spun'], + 'snurp': ['snurp', 'spurn'], + 'snurt': ['snurt', 'turns'], + 'so': ['os', 'so'], + 'soak': ['asok', 'soak', 'soka'], + 'soaker': ['arkose', 'resoak', 'soaker'], + 'soally': ['soally', 'sollya'], + 'soam': ['amos', 'soam', 'soma'], + 'soap': ['asop', 'sapo', 'soap'], + 'soaper': ['resoap', 'soaper'], + 'soar': ['asor', 'rosa', 'soar', 'sora'], + 'sob': ['bos', 'sob'], + 'sobeit': ['setibo', 'sobeit'], + 'sober': ['boser', 'brose', 'sober'], + 'sobralite': ['sobralite', 'strobilae'], + 'soc': ['cos', 'osc', 'soc'], + 'socager': ['corsage', 'socager'], + 'social': ['colias', 'scolia', 'social'], + 'socialite': ['aeolistic', 'socialite'], + 'societal': ['cosalite', 'societal'], + 'societism': ['seismotic', 'societism'], + 'socinian': ['oscinian', 'socinian'], + 'sociobiological': ['biosociological', 'sociobiological'], + 'sociolegal': ['oligoclase', 'sociolegal'], + 'socius': ['scious', 'socius'], + 'socle': ['close', 'socle'], + 'soco': ['coos', 'soco'], + 'socotran': ['ostracon', 'socotran'], + 'socotrine': ['certosino', 'cortisone', 'socotrine'], + 'socratean': ['ostracean', 'socratean'], + 'socratic': ['acrostic', 'sarcotic', 'socratic'], + 'socratical': ['acrostical', 'socratical'], + 'socratically': ['acrostically', 'socratically'], + 'socraticism': ['acrosticism', 'socraticism'], + 'socratism': ['ostracism', 'socratism'], + 'socratize': ['ostracize', 'socratize'], + 'sod': ['dos', 'ods', 'sod'], + 'soda': ['dosa', 'sado', 'soda'], + 'sodalite': ['diastole', 'isolated', 'sodalite', 'solidate'], + 'sodium': ['modius', 'sodium'], + 'sodom': ['dooms', 'sodom'], + 'sodomitic': ['diosmotic', 'sodomitic'], + 'soe': ['oes', 'ose', 'soe'], + 'soft': ['soft', 'stof'], + 'soften': ['oftens', 'soften'], + 'softener': ['resoften', 'softener'], + 'sog': ['gos', 'sog'], + 'soga': ['sago', 'soga'], + 'soger': ['gorse', 'soger'], + 'soh': ['sho', 'soh'], + 'soho': ['shoo', 'soho'], + 'soil': ['lois', 'silo', 'siol', 'soil', 'soli'], + 'soiled': ['isolde', 'soiled'], + 'sojourner': ['resojourn', 'sojourner'], + 'sok': ['kos', 'sok'], + 'soka': ['asok', 'soak', 'soka'], + 'soke': ['skeo', 'soke'], + 'soken': ['snoek', 'snoke', 'soken'], + 'sola': ['also', 'sola'], + 'solacer': ['escolar', 'solacer'], + 'solan': ['salon', 'sloan', 'solan'], + 'solar': ['rosal', 'solar', 'soral'], + 'solaristics': ['scissortail', 'solaristics'], + 'solate': ['lotase', 'osteal', 'solate', 'stolae', 'talose'], + 'sold': ['slod', 'sold'], + 'solder': ['dorsel', 'seldor', 'solder'], + 'solderer': ['resolder', 'solderer'], + 'soldi': ['soldi', 'solid'], + 'soldo': ['soldo', 'solod'], + 'sole': ['lose', 'sloe', 'sole'], + 'solea': ['alose', 'osela', 'solea'], + 'solecist': ['solecist', 'solstice'], + 'solen': ['slone', 'solen'], + 'soleness': ['noseless', 'soleness'], + 'solenial': ['lesional', 'solenial'], + 'solenite': ['noselite', 'solenite'], + 'solenium': ['emulsion', 'solenium'], + 'solenopsis': ['poisonless', 'solenopsis'], + 'solent': ['solent', 'stolen', 'telson'], + 'solentine': ['nelsonite', 'solentine'], + 'soler': ['loser', 'orsel', 'rosel', 'soler'], + 'solera': ['roseal', 'solera'], + 'soles': ['loess', 'soles'], + 'soli': ['lois', 'silo', 'siol', 'soil', 'soli'], + 'soliative': ['isolative', 'soliative'], + 'solicit': ['colitis', 'solicit'], + 'solicitation': ['coalitionist', 'solicitation'], + 'soliciter': ['resolicit', 'soliciter'], + 'soliciting': ['ignicolist', 'soliciting'], + 'solicitude': ['isodulcite', 'solicitude'], + 'solid': ['soldi', 'solid'], + 'solidate': ['diastole', 'isolated', 'sodalite', 'solidate'], + 'solidus': ['dissoul', 'dulosis', 'solidus'], + 'solilunar': ['lunisolar', 'solilunar'], + 'soliped': ['despoil', 'soliped', 'spoiled'], + 'solitarian': ['sinoatrial', 'solitarian'], + 'solitary': ['royalist', 'solitary'], + 'soliterraneous': ['salinoterreous', 'soliterraneous'], + 'solitude': ['outslide', 'solitude'], + 'sollya': ['soally', 'sollya'], + 'solmizate': ['solmizate', 'zealotism'], + 'solo': ['sloo', 'solo', 'sool'], + 'solod': ['soldo', 'solod'], + 'solon': ['olson', 'solon'], + 'solonic': ['scolion', 'solonic'], + 'soloth': ['soloth', 'tholos'], + 'solotink': ['solotink', 'solotnik'], + 'solotnik': ['solotink', 'solotnik'], + 'solstice': ['solecist', 'solstice'], + 'solum': ['mosul', 'mouls', 'solum'], + 'solute': ['lutose', 'solute', 'tousle'], + 'solutioner': ['resolution', 'solutioner'], + 'soma': ['amos', 'soam', 'soma'], + 'somacule': ['maculose', 'somacule'], + 'somal': ['salmo', 'somal'], + 'somali': ['limosa', 'somali'], + 'somasthenia': ['anhematosis', 'somasthenia'], + 'somatic': ['atomics', 'catoism', 'cosmati', 'osmatic', 'somatic'], + 'somatics': ['acosmist', 'massicot', 'somatics'], + 'somatism': ['osmatism', 'somatism'], + 'somatophyte': ['hepatostomy', 'somatophyte'], + 'somatophytic': ['hypostomatic', 'somatophytic'], + 'somatopleuric': ['micropetalous', 'somatopleuric'], + 'somatopsychic': ['psychosomatic', 'somatopsychic'], + 'somatosplanchnic': ['somatosplanchnic', 'splanchnosomatic'], + 'somatous': ['astomous', 'somatous'], + 'somber': ['somber', 'sombre'], + 'sombre': ['somber', 'sombre'], + 'some': ['meso', 'mose', 'some'], + 'someday': ['samoyed', 'someday'], + 'somers': ['messor', 'mosser', 'somers'], + 'somnambule': ['somnambule', 'summonable'], + 'somnial': ['malison', 'manolis', 'osmanli', 'somnial'], + 'somnopathy': ['phytomonas', 'somnopathy'], + 'somnorific': ['onisciform', 'somnorific'], + 'son': ['ons', 'son'], + 'sonant': ['santon', 'sonant', 'stanno'], + 'sonantic': ['canonist', 'sanction', 'sonantic'], + 'sonar': ['arson', 'saron', 'sonar'], + 'sonatina': ['ansation', 'sonatina'], + 'sond': ['snod', 'sond'], + 'sondation': ['anisodont', 'sondation'], + 'sondeli': ['indoles', 'sondeli'], + 'soneri': ['rosine', 'senior', 'soneri'], + 'song': ['snog', 'song'], + 'songoi': ['isogon', 'songoi'], + 'songy': ['gonys', 'songy'], + 'sonic': ['oscin', 'scion', 'sonic'], + 'sonja': ['janos', 'jason', 'jonas', 'sonja'], + 'sonneratia': ['arsenation', 'senatorian', 'sonneratia'], + 'sonnet': ['sonnet', 'stonen', 'tenson'], + 'sonnetwise': ['sonnetwise', 'swinestone'], + 'sonrai': ['arsino', 'rasion', 'sonrai'], + 'sontag': ['sontag', 'tongas'], + 'soodle': ['dolose', 'oodles', 'soodle'], + 'sook': ['koso', 'skoo', 'sook'], + 'sool': ['sloo', 'solo', 'sool'], + 'soon': ['oons', 'soon'], + 'sooner': ['nooser', 'seroon', 'sooner'], + 'sooter': ['seroot', 'sooter', 'torose'], + 'sooth': ['shoot', 'sooth', 'sotho', 'toosh'], + 'soother': ['orthose', 'reshoot', 'shooter', 'soother'], + 'soothing': ['shooting', 'soothing'], + 'sootiness': ['enostosis', 'sootiness'], + 'sooty': ['sooty', 'soyot'], + 'sope': ['epos', 'peso', 'pose', 'sope'], + 'soph': ['phos', 'posh', 'shop', 'soph'], + 'sophister': ['posterish', 'prothesis', 'sophister', 'storeship', 'tephrosis'], + 'sophistical': ['postischial', 'sophistical'], + 'sophomore': ['osmophore', 'sophomore'], + 'sopition': ['position', 'sopition'], + 'sopor': ['poros', 'proso', 'sopor', 'spoor'], + 'soprani': ['parison', 'soprani'], + 'sopranist': ['postnaris', 'sopranist'], + 'soprano': ['pronaos', 'soprano'], + 'sora': ['asor', 'rosa', 'soar', 'sora'], + 'sorabian': ['abrasion', 'sorabian'], + 'soral': ['rosal', 'solar', 'soral'], + 'sorbate': ['barotse', 'boaster', 'reboast', 'sorbate'], + 'sorbin': ['insorb', 'sorbin'], + 'sorcer': ['scorer', 'sorcer'], + 'sorchin': ['cornish', 'cronish', 'sorchin'], + 'sorda': ['sarod', 'sorda'], + 'sordes': ['dosser', 'sordes'], + 'sordine': ['indorse', 'ordines', 'siredon', 'sordine'], + 'sordino': ['indoors', 'sordino'], + 'sore': ['eros', 'rose', 'sero', 'sore'], + 'soredia': ['ardoise', 'aroides', 'soredia'], + 'sorediate': ['oestridae', 'ostreidae', 'sorediate'], + 'soredium': ['dimerous', 'soredium'], + 'soree': ['erose', 'soree'], + 'sorefoot': ['footsore', 'sorefoot'], + 'sorehead': ['rosehead', 'sorehead'], + 'sorehon': ['onshore', 'sorehon'], + 'sorema': ['amores', 'ramose', 'sorema'], + 'soricid': ['cirsoid', 'soricid'], + 'soricident': ['discretion', 'soricident'], + 'soricine': ['recision', 'soricine'], + 'sorite': ['restio', 'sorite', 'sortie', 'triose'], + 'sorites': ['rossite', 'sorites'], + 'sornare': ['serrano', 'sornare'], + 'sorner': ['snorer', 'sorner'], + 'sorning': ['snoring', 'sorning'], + 'sororial': ['rosorial', 'sororial'], + 'sorption': ['notropis', 'positron', 'sorption'], + 'sortable': ['sortable', 'storable'], + 'sorted': ['sorted', 'strode'], + 'sorter': ['resort', 'roster', 'sorter', 'storer'], + 'sortie': ['restio', 'sorite', 'sortie', 'triose'], + 'sortilegus': ['sortilegus', 'strigulose'], + 'sortiment': ['sortiment', 'trimstone'], + 'sortly': ['sortly', 'styrol'], + 'sorty': ['sorty', 'story', 'stroy'], + 'sorva': ['savor', 'sorva'], + 'sory': ['rosy', 'sory'], + 'sosia': ['oasis', 'sosia'], + 'sostenuto': ['ostentous', 'sostenuto'], + 'soter': ['roset', 'rotse', 'soter', 'stero', 'store', 'torse'], + 'soterial': ['soterial', 'striolae'], + 'sotho': ['shoot', 'sooth', 'sotho', 'toosh'], + 'sotie': ['sotie', 'toise'], + 'sotnia': ['sotnia', 'tinosa'], + 'sotol': ['sotol', 'stool'], + 'sots': ['sots', 'toss'], + 'sotter': ['sotter', 'testor'], + 'soucar': ['acorus', 'soucar'], + 'souchet': ['souchet', 'techous', 'tousche'], + 'souly': ['lousy', 'souly'], + 'soum': ['soum', 'sumo'], + 'soumansite': ['soumansite', 'stamineous'], + 'sound': ['nodus', 'ounds', 'sound'], + 'sounder': ['resound', 'sounder', 'unrosed'], + 'soup': ['opus', 'soup'], + 'souper': ['poseur', 'pouser', 'souper', 'uprose'], + 'sour': ['ours', 'sour'], + 'source': ['cerous', 'course', 'crouse', 'source'], + 'soured': ['douser', 'soured'], + 'souredness': ['rousedness', 'souredness'], + 'souren': ['souren', 'unsore', 'ursone'], + 'sourer': ['rouser', 'sourer'], + 'souring': ['nigrous', 'rousing', 'souring'], + 'sourly': ['lusory', 'sourly'], + 'soursop': ['psorous', 'soursop', 'sporous'], + 'soury': ['soury', 'yours'], + 'souser': ['serous', 'souser'], + 'souter': ['ouster', 'souter', 'touser', 'trouse'], + 'souterrain': ['souterrain', 'ternarious', 'trouserian'], + 'south': ['shout', 'south'], + 'souther': ['shouter', 'souther'], + 'southerland': ['southerland', 'southlander'], + 'southing': ['shouting', 'southing'], + 'southlander': ['southerland', 'southlander'], + 'soviet': ['soviet', 'sovite'], + 'sovite': ['soviet', 'sovite'], + 'sowdones': ['sowdones', 'woodness'], + 'sowel': ['sowel', 'sowle'], + 'sower': ['owser', 'resow', 'serow', 'sower', 'swore', 'worse'], + 'sowl': ['slow', 'sowl'], + 'sowle': ['sowel', 'sowle'], + 'sown': ['snow', 'sown'], + 'sowt': ['sowt', 'stow', 'swot', 'wots'], + 'soyot': ['sooty', 'soyot'], + 'spa': ['asp', 'sap', 'spa'], + 'space': ['capes', 'scape', 'space'], + 'spaceless': ['scapeless', 'spaceless'], + 'spacer': ['casper', 'escarp', 'parsec', 'scrape', 'secpar', 'spacer'], + 'spade': ['depas', 'sepad', 'spade'], + 'spader': ['rasped', 'spader', 'spread'], + 'spadiceous': ['dipsaceous', 'spadiceous'], + 'spadone': ['espadon', 'spadone'], + 'spadonic': ['spadonic', 'spondaic', 'spondiac'], + 'spadrone': ['parsoned', 'spadrone'], + 'spae': ['apse', 'pesa', 'spae'], + 'spaer': ['asper', 'parse', 'prase', 'spaer', 'spare', 'spear'], + 'spahi': ['aphis', 'apish', 'hispa', 'saiph', 'spahi'], + 'spaid': ['sapid', 'spaid'], + 'spaik': ['askip', 'spaik'], + 'spairge': ['prisage', 'spairge'], + 'spalacine': ['asclepian', 'spalacine'], + 'spale': ['elaps', + 'lapse', + 'lepas', + 'pales', + 'salep', + 'saple', + 'sepal', + 'slape', + 'spale', + 'speal'], + 'spalt': ['spalt', 'splat'], + 'span': ['snap', 'span'], + 'spancel': ['enclasp', 'spancel'], + 'spane': ['aspen', 'panse', 'snape', 'sneap', 'spane', 'spean'], + 'spanemia': ['paeanism', 'spanemia'], + 'spangler': ['spangler', 'sprangle'], + 'spangolite': ['postgenial', 'spangolite'], + 'spaniel': ['espinal', 'pinales', 'spaniel'], + 'spaniol': ['sanpoil', 'spaniol'], + 'spanless': ['snapless', 'spanless'], + 'spar': ['rasp', 'spar'], + 'sparable': ['parsable', 'prebasal', 'sparable'], + 'spare': ['asper', 'parse', 'prase', 'spaer', 'spare', 'spear'], + 'spareable': ['separable', 'spareable'], + 'sparely': ['parsley', 'pyrales', 'sparely', 'splayer'], + 'sparer': ['parser', 'rasper', 'sparer'], + 'sparerib': ['ribspare', 'sparerib'], + 'sparge': ['gasper', 'sparge'], + 'sparger': ['grasper', 'regrasp', 'sparger'], + 'sparidae': ['paradise', 'sparidae'], + 'sparing': ['aspring', 'rasping', 'sparing'], + 'sparingly': ['raspingly', 'sparingly'], + 'sparingness': ['raspingness', 'sparingness'], + 'sparling': ['laspring', 'sparling', 'springal'], + 'sparoid': ['prasoid', 'sparoid'], + 'sparse': ['passer', 'repass', 'sparse'], + 'spart': ['spart', 'sprat', 'strap', 'traps'], + 'spartanic': ['sacripant', 'spartanic'], + 'sparteine': ['pistareen', 'sparteine'], + 'sparterie': ['periaster', 'sparterie'], + 'spartina': ['aspirant', 'partisan', 'spartina'], + 'spartle': ['palster', 'persalt', 'plaster', 'psalter', 'spartle', 'stapler'], + 'spary': ['raspy', 'spary', 'spray'], + 'spat': ['past', 'spat', 'stap', 'taps'], + 'spate': ['paste', 'septa', 'spate'], + 'spathal': ['asphalt', 'spathal', 'taplash'], + 'spathe': ['spathe', 'thapes'], + 'spathic': ['haptics', 'spathic'], + 'spatling': ['spatling', 'stapling'], + 'spatter': ['spatter', 'tapster'], + 'spattering': ['spattering', 'tapestring'], + 'spattle': ['peltast', 'spattle'], + 'spatular': ['pastural', 'spatular'], + 'spatule': ['pulsate', 'spatule', 'upsteal'], + 'spave': ['spave', 'vespa'], + 'speak': ['sapek', 'speak'], + 'speaker': ['respeak', 'speaker'], + 'speal': ['elaps', + 'lapse', + 'lepas', + 'pales', + 'salep', + 'saple', + 'sepal', + 'slape', + 'spale', + 'speal'], + 'spean': ['aspen', 'panse', 'snape', 'sneap', 'spane', 'spean'], + 'spear': ['asper', 'parse', 'prase', 'spaer', 'spare', 'spear'], + 'spearman': ['parmesan', 'spearman'], + 'spearmint': ['spearmint', 'spermatin'], + 'speary': ['presay', 'speary'], + 'spec': ['ceps', 'spec'], + 'spectatorial': ['poetastrical', 'spectatorial'], + 'specter': ['respect', 'scepter', 'specter'], + 'spectered': ['sceptered', 'spectered'], + 'spectra': ['precast', 'spectra'], + 'spectral': ['sceptral', 'scraplet', 'spectral'], + 'spectromicroscope': ['microspectroscope', 'spectromicroscope'], + 'spectrotelescope': ['spectrotelescope', 'telespectroscope'], + 'spectrous': ['spectrous', 'susceptor', 'suspector'], + 'spectry': ['precyst', 'sceptry', 'spectry'], + 'specula': ['capsule', 'specula', 'upscale'], + 'specular': ['capsuler', 'specular'], + 'speed': ['pedes', 'speed'], + 'speel': ['sleep', 'speel'], + 'speelless': ['sleepless', 'speelless'], + 'speer': ['peres', 'perse', 'speer', 'spree'], + 'speerity': ['perseity', 'speerity'], + 'speiss': ['sepsis', 'speiss'], + 'spelaean': ['seaplane', 'spelaean'], + 'spelk': ['skelp', 'spelk'], + 'speller': ['presell', 'respell', 'speller'], + 'spelt': ['slept', 'spelt', 'splet'], + 'spenerism': ['primeness', 'spenerism'], + 'speos': ['posse', 'speos'], + 'sperate': ['perates', 'repaste', 'sperate'], + 'sperity': ['pyrites', 'sperity'], + 'sperling': ['sperling', 'springle'], + 'spermalist': ['psalmister', 'spermalist'], + 'spermathecal': ['chapelmaster', 'spermathecal'], + 'spermatid': ['predatism', 'spermatid'], + 'spermatin': ['spearmint', 'spermatin'], + 'spermatogonium': ['protomagnesium', 'spermatogonium'], + 'spermatozoic': ['spermatozoic', 'zoospermatic'], + 'spermiogenesis': ['geissospermine', 'spermiogenesis'], + 'spermocarp': ['carposperm', 'spermocarp'], + 'spet': ['pest', 'sept', 'spet', 'step'], + 'spew': ['spew', 'swep'], + 'sphacelation': ['lipsanotheca', 'sphacelation'], + 'sphecidae': ['cheapside', 'sphecidae'], + 'sphene': ['sephen', 'sphene'], + 'sphenoethmoid': ['ethmosphenoid', 'sphenoethmoid'], + 'sphenoethmoidal': ['ethmosphenoidal', 'sphenoethmoidal'], + 'sphenotic': ['phonetics', 'sphenotic'], + 'spheral': ['plasher', 'spheral'], + 'spheration': ['opisthenar', 'spheration'], + 'sphere': ['herpes', 'hesper', 'sphere'], + 'sphery': ['sphery', 'sypher'], + 'sphyraenid': ['dysphrenia', 'sphyraenid', 'sphyrnidae'], + 'sphyrnidae': ['dysphrenia', 'sphyraenid', 'sphyrnidae'], + 'spica': ['aspic', 'spica'], + 'spicate': ['aseptic', 'spicate'], + 'spice': ['sepic', 'spice'], + 'spicer': ['crepis', 'cripes', 'persic', 'precis', 'spicer'], + 'spiciferous': ['pisciferous', 'spiciferous'], + 'spiciform': ['pisciform', 'spiciform'], + 'spicket': ['skeptic', 'spicket'], + 'spicular': ['scripula', 'spicular'], + 'spiculate': ['euplastic', 'spiculate'], + 'spiculated': ['disculpate', 'spiculated'], + 'spicule': ['clipeus', 'spicule'], + 'spider': ['spider', 'spired', 'spried'], + 'spiderish': ['sidership', 'spiderish'], + 'spiderlike': ['predislike', 'spiderlike'], + 'spiel': ['piles', 'plies', 'slipe', 'spiel', 'spile'], + 'spier': ['siper', 'spier', 'spire'], + 'spikelet': ['spikelet', 'steplike'], + 'spiking': ['pigskin', 'spiking'], + 'spiky': ['pisky', 'spiky'], + 'spile': ['piles', 'plies', 'slipe', 'spiel', 'spile'], + 'spiler': ['lisper', 'pliers', 'sirple', 'spiler'], + 'spiling': ['sipling', 'spiling'], + 'spiloma': ['imposal', 'spiloma'], + 'spilt': ['spilt', 'split'], + 'spin': ['snip', 'spin'], + 'spina': ['pisan', 'sapin', 'spina'], + 'spinae': ['sepian', 'spinae'], + 'spinales': ['painless', 'spinales'], + 'spinate': ['panties', 'sapient', 'spinate'], + 'spindled': ['spindled', 'splendid'], + 'spindler': ['spindler', 'splinder'], + 'spine': ['penis', 'snipe', 'spine'], + 'spinebill': ['snipebill', 'spinebill'], + 'spinel': ['spinel', 'spline'], + 'spinelike': ['snipelike', 'spinelike'], + 'spinet': ['instep', 'spinet'], + 'spinigerous': ['serpiginous', 'spinigerous'], + 'spinigrade': ['despairing', 'spinigrade'], + 'spinoid': ['spinoid', 'spionid'], + 'spinoneural': ['spinoneural', 'unipersonal'], + 'spinotectal': ['entoplastic', 'spinotectal', 'tectospinal', 'tenoplastic'], + 'spiny': ['snipy', 'spiny'], + 'spionid': ['spinoid', 'spionid'], + 'spiracle': ['calipers', 'spiracle'], + 'spiracula': ['auriscalp', 'spiracula'], + 'spiral': ['prisal', 'spiral'], + 'spiralism': ['misprisal', 'spiralism'], + 'spiraloid': ['spiraloid', 'sporidial'], + 'spiran': ['spiran', 'sprain'], + 'spirant': ['spirant', 'spraint'], + 'spirate': ['piaster', 'piastre', 'raspite', 'spirate', 'traipse'], + 'spire': ['siper', 'spier', 'spire'], + 'spirea': ['aspire', 'paries', 'praise', 'sirpea', 'spirea'], + 'spired': ['spider', 'spired', 'spried'], + 'spirelet': ['epistler', 'spirelet'], + 'spireme': ['emprise', 'imprese', 'premise', 'spireme'], + 'spiritally': ['pistillary', 'spiritally'], + 'spiriter': ['respirit', 'spiriter'], + 'spirometer': ['prisometer', 'spirometer'], + 'spironema': ['mesropian', 'promnesia', 'spironema'], + 'spirt': ['spirt', 'sprit', 'stirp', 'strip'], + 'spirula': ['parulis', 'spirula', 'uprisal'], + 'spit': ['pist', 'spit'], + 'spital': ['alpist', 'pastil', 'spital'], + 'spite': ['septi', 'spite', 'stipe'], + 'spithame': ['aphetism', 'mateship', 'shipmate', 'spithame'], + 'spitter': ['spitter', 'tipster'], + 'splairge': ['aspergil', 'splairge'], + 'splanchnosomatic': ['somatosplanchnic', 'splanchnosomatic'], + 'splasher': ['harpless', 'splasher'], + 'splat': ['spalt', 'splat'], + 'splay': ['palsy', 'splay'], + 'splayed': ['pylades', 'splayed'], + 'splayer': ['parsley', 'pyrales', 'sparely', 'splayer'], + 'spleet': ['pestle', 'spleet'], + 'splender': ['resplend', 'splender'], + 'splendid': ['spindled', 'splendid'], + 'splenium': ['splenium', 'unsimple'], + 'splenolaparotomy': ['laparosplenotomy', 'splenolaparotomy'], + 'splenoma': ['neoplasm', 'pleonasm', 'polesman', 'splenoma'], + 'splenomegalia': ['megalosplenia', 'splenomegalia'], + 'splenonephric': ['phrenosplenic', 'splenonephric', 'splenophrenic'], + 'splenophrenic': ['phrenosplenic', 'splenonephric', 'splenophrenic'], + 'splet': ['slept', 'spelt', 'splet'], + 'splice': ['clipse', 'splice'], + 'spliceable': ['eclipsable', 'spliceable'], + 'splinder': ['spindler', 'splinder'], + 'spline': ['spinel', 'spline'], + 'split': ['spilt', 'split'], + 'splitter': ['splitter', 'striplet'], + 'splore': ['sloper', 'splore'], + 'spogel': ['gospel', 'spogel'], + 'spoil': ['polis', 'spoil'], + 'spoilage': ['pelasgoi', 'spoilage'], + 'spoilation': ['positional', 'spoilation', 'spoliation'], + 'spoiled': ['despoil', 'soliped', 'spoiled'], + 'spoiler': ['leporis', 'spoiler'], + 'spoilment': ['simpleton', 'spoilment'], + 'spoilt': ['pistol', 'postil', 'spoilt'], + 'spole': ['elops', 'slope', 'spole'], + 'spoliation': ['positional', 'spoilation', 'spoliation'], + 'spondaic': ['spadonic', 'spondaic', 'spondiac'], + 'spondiac': ['spadonic', 'spondaic', 'spondiac'], + 'spongily': ['posingly', 'spongily'], + 'sponsal': ['plasson', 'sponsal'], + 'sponsalia': ['passional', 'sponsalia'], + 'spool': ['polos', 'sloop', 'spool'], + 'spoon': ['snoop', 'spoon'], + 'spooner': ['snooper', 'spooner'], + 'spoony': ['snoopy', 'spoony'], + 'spoonyism': ['spoonyism', 'symposion'], + 'spoor': ['poros', 'proso', 'sopor', 'spoor'], + 'spoot': ['spoot', 'stoop'], + 'sporangia': ['agapornis', 'sporangia'], + 'spore': ['poser', 'prose', 'ropes', 'spore'], + 'sporidial': ['spiraloid', 'sporidial'], + 'sporification': ['antisoporific', 'prosification', 'sporification'], + 'sporogeny': ['gynospore', 'sporogeny'], + 'sporoid': ['psoroid', 'sporoid'], + 'sporotrichum': ['sporotrichum', 'trichosporum'], + 'sporous': ['psorous', 'soursop', 'sporous'], + 'sporozoic': ['sporozoic', 'zoosporic'], + 'sport': ['sport', 'strop'], + 'sporter': ['sporter', 'strepor'], + 'sportula': ['postural', 'pulsator', 'sportula'], + 'sportulae': ['opulaster', 'sportulae', 'sporulate'], + 'sporulate': ['opulaster', 'sportulae', 'sporulate'], + 'sporule': ['leprous', 'pelorus', 'sporule'], + 'sposhy': ['hyssop', 'phossy', 'sposhy'], + 'spot': ['post', 'spot', 'stop', 'tops'], + 'spotless': ['postless', 'spotless', 'stopless'], + 'spotlessness': ['spotlessness', 'stoplessness'], + 'spotlike': ['postlike', 'spotlike'], + 'spottedly': ['spottedly', 'spotteldy'], + 'spotteldy': ['spottedly', 'spotteldy'], + 'spotter': ['protest', 'spotter'], + 'spouse': ['esopus', 'spouse'], + 'spout': ['spout', 'stoup'], + 'spouter': ['petrous', 'posture', 'proetus', 'proteus', 'septuor', 'spouter'], + 'sprag': ['grasp', 'sprag'], + 'sprain': ['spiran', 'sprain'], + 'spraint': ['spirant', 'spraint'], + 'sprangle': ['spangler', 'sprangle'], + 'sprat': ['spart', 'sprat', 'strap', 'traps'], + 'spray': ['raspy', 'spary', 'spray'], + 'sprayer': ['respray', 'sprayer'], + 'spread': ['rasped', 'spader', 'spread'], + 'spreadboard': ['broadspread', 'spreadboard'], + 'spreader': ['respread', 'spreader'], + 'spreadover': ['overspread', 'spreadover'], + 'spree': ['peres', 'perse', 'speer', 'spree'], + 'spret': ['prest', 'spret'], + 'spried': ['spider', 'spired', 'spried'], + 'sprier': ['risper', 'sprier'], + 'spriest': ['persist', 'spriest'], + 'springal': ['laspring', 'sparling', 'springal'], + 'springe': ['presign', 'springe'], + 'springer': ['respring', 'springer'], + 'springhead': ['headspring', 'springhead'], + 'springhouse': ['springhouse', 'surgeonship'], + 'springle': ['sperling', 'springle'], + 'sprit': ['spirt', 'sprit', 'stirp', 'strip'], + 'sprite': ['priest', 'pteris', 'sprite', 'stripe'], + 'spritehood': ['priesthood', 'spritehood'], + 'sproat': ['asport', 'pastor', 'sproat'], + 'sprocket': ['prestock', 'sprocket'], + 'sprout': ['sprout', 'stroup', 'stupor'], + 'sprouter': ['posturer', 'resprout', 'sprouter'], + 'sprouting': ['outspring', 'sprouting'], + 'sprue': ['purse', 'resup', 'sprue', 'super'], + 'spruer': ['purser', 'spruer'], + 'spruit': ['purist', 'spruit', 'uprist', 'upstir'], + 'spun': ['snup', 'spun'], + 'spunkie': ['spunkie', 'unspike'], + 'spuriae': ['spuriae', 'uparise', 'upraise'], + 'spurl': ['slurp', 'spurl'], + 'spurlet': ['purslet', 'spurlet', 'spurtle'], + 'spurn': ['snurp', 'spurn'], + 'spurt': ['spurt', 'turps'], + 'spurtive': ['spurtive', 'upstrive'], + 'spurtle': ['purslet', 'spurlet', 'spurtle'], + 'sputa': ['sputa', 'staup', 'stupa'], + 'sputumary': ['sputumary', 'sumptuary'], + 'sputumous': ['sputumous', 'sumptuous'], + 'spyer': ['pryse', 'spyer'], + 'spyros': ['prossy', 'spyros'], + 'squail': ['squail', 'squali'], + 'squali': ['squail', 'squali'], + 'squamatine': ['antimasque', 'squamatine'], + 'squame': ['masque', 'squame', 'squeam'], + 'squameous': ['squameous', 'squeamous'], + 'squamopetrosal': ['petrosquamosal', 'squamopetrosal'], + 'squamosoparietal': ['parietosquamosal', 'squamosoparietal'], + 'squareman': ['marquesan', 'squareman'], + 'squeaker': ['resqueak', 'squeaker'], + 'squeal': ['lasque', 'squeal'], + 'squeam': ['masque', 'squame', 'squeam'], + 'squeamous': ['squameous', 'squeamous'], + 'squillian': ['nisqualli', 'squillian'], + 'squire': ['risque', 'squire'], + 'squiret': ['querist', 'squiret'], + 'squit': ['quits', 'squit'], + 'sramana': ['ramanas', 'sramana'], + 'sri': ['sir', 'sri'], + 'srivatsan': ['ravissant', 'srivatsan'], + 'ssi': ['sis', 'ssi'], + 'ssu': ['ssu', 'sus'], + 'staab': ['basta', 'staab'], + 'stab': ['bast', 'bats', 'stab'], + 'stabile': ['astilbe', 'bestial', 'blastie', 'stabile'], + 'stable': ['ablest', 'stable', 'tables'], + 'stableful': ['bullfeast', 'stableful'], + 'stabler': ['blaster', 'reblast', 'stabler'], + 'stabling': ['blasting', 'stabling'], + 'stably': ['blasty', 'stably'], + 'staccato': ['staccato', 'stoccata'], + 'stacey': ['cytase', 'stacey'], + 'stacher': ['stacher', 'thraces'], + 'stacker': ['restack', 'stacker'], + 'stackman': ['stackman', 'tacksman'], + 'stacy': ['stacy', 'styca'], + 'stade': ['sedat', 'stade', 'stead'], + 'stadic': ['dicast', 'stadic'], + 'stadium': ['dumaist', 'stadium'], + 'staffer': ['restaff', 'staffer'], + 'stag': ['gast', 'stag'], + 'stager': ['gaster', 'stager'], + 'stagily': ['stagily', 'stygial'], + 'stagnation': ['antagonist', 'stagnation'], + 'stagnum': ['mustang', 'stagnum'], + 'stain': ['saint', 'satin', 'stain'], + 'stainable': ['balanites', 'basaltine', 'stainable'], + 'stainer': ['asterin', 'eranist', 'restain', 'stainer', 'starnie', 'stearin'], + 'stainful': ['inflatus', 'stainful'], + 'stainless': ['saintless', 'saltiness', 'slatiness', 'stainless'], + 'staio': ['sitao', 'staio'], + 'stair': ['arist', + 'astir', + 'sitar', + 'stair', + 'stria', + 'tarsi', + 'tisar', + 'trias'], + 'staircase': ['caesarist', 'staircase'], + 'staired': ['astride', 'diaster', 'disrate', 'restiad', 'staired'], + 'staithman': ['staithman', 'thanatism'], + 'staiver': ['staiver', 'taivers'], + 'stake': ['skate', 'stake', 'steak'], + 'staker': ['skater', 'staker', 'strake', 'streak', 'tasker'], + 'stalagmitic': ['stalagmitic', 'stigmatical'], + 'stale': ['least', 'setal', 'slate', 'stale', 'steal', 'stela', 'tales'], + 'staling': ['anglist', 'lasting', 'salting', 'slating', 'staling'], + 'stalker': ['sklater', 'stalker'], + 'staller': ['staller', 'stellar'], + 'stam': ['mast', 'mats', 'stam'], + 'stamen': ['mantes', 'stamen'], + 'stamin': ['manist', 'mantis', 'matins', 'stamin'], + 'stamina': ['amanist', 'stamina'], + 'staminal': ['staminal', 'tailsman', 'talisman'], + 'staminate': ['emanatist', 'staminate', 'tasmanite'], + 'stamineous': ['soumansite', 'stamineous'], + 'staminode': ['ademonist', 'demoniast', 'staminode'], + 'stammer': ['stammer', 'stremma'], + 'stampede': ['stampede', 'stepdame'], + 'stamper': ['restamp', 'stamper'], + 'stampian': ['mainpast', 'mantispa', 'panamist', 'stampian'], + 'stan': ['nast', 'sant', 'stan'], + 'stance': ['ascent', 'secant', 'stance'], + 'stanch': ['chanst', 'snatch', 'stanch'], + 'stanchable': ['snatchable', 'stanchable'], + 'stancher': ['resnatch', 'snatcher', 'stancher'], + 'stand': ['dasnt', 'stand'], + 'standage': ['dagestan', 'standage'], + 'standee': ['edestan', 'standee'], + 'stander': ['stander', 'sternad'], + 'standout': ['outstand', 'standout'], + 'standstill': ['standstill', 'stillstand'], + 'stane': ['antes', 'nates', 'stane', 'stean'], + 'stang': ['angst', 'stang', 'tangs'], + 'stangeria': ['agrestian', 'gerastian', 'stangeria'], + 'stanine': ['ensaint', 'stanine'], + 'stanly': ['nylast', 'stanly'], + 'stanno': ['santon', 'sonant', 'stanno'], + 'stap': ['past', 'spat', 'stap', 'taps'], + 'staple': ['pastel', 'septal', 'staple'], + 'stapler': ['palster', 'persalt', 'plaster', 'psalter', 'spartle', 'stapler'], + 'stapling': ['spatling', 'stapling'], + 'star': ['sart', 'star', 'stra', 'tars', 'tsar'], + 'starch': ['scarth', 'scrath', 'starch'], + 'stardom': ['stardom', 'tsardom'], + 'stare': ['aster', 'serta', 'stare', 'strae', 'tarse', 'teras'], + 'staree': ['asteer', + 'easter', + 'eastre', + 'reseat', + 'saeter', + 'seater', + 'staree', + 'teaser', + 'teresa'], + 'starer': ['arrest', 'astrer', 'raster', 'starer'], + 'starful': ['flustra', 'starful'], + 'staring': ['gastrin', 'staring'], + 'staringly': ['staringly', 'strayling'], + 'stark': ['karst', 'skart', 'stark'], + 'starky': ['starky', 'straky'], + 'starlet': ['rattles', 'slatter', 'starlet', 'startle'], + 'starlit': ['starlit', 'trisalt'], + 'starlite': ['starlite', 'taistrel'], + 'starnel': ['saltern', 'starnel', 'sternal'], + 'starnie': ['asterin', 'eranist', 'restain', 'stainer', 'starnie', 'stearin'], + 'starnose': ['assentor', 'essorant', 'starnose'], + 'starship': ['starship', 'tsarship'], + 'starshot': ['shotstar', 'starshot'], + 'starter': ['restart', 'starter'], + 'startle': ['rattles', 'slatter', 'starlet', 'startle'], + 'starve': ['starve', 'staver', 'strave', 'tavers', 'versta'], + 'starwise': ['starwise', 'waitress'], + 'stary': ['satyr', 'stary', 'stray', 'trasy'], + 'stases': ['assets', 'stases'], + 'stasis': ['assist', 'stasis'], + 'statable': ['statable', 'tastable'], + 'state': ['state', 'taste', 'tates', 'testa'], + 'stated': ['stated', 'tasted'], + 'stateful': ['stateful', 'tasteful'], + 'statefully': ['statefully', 'tastefully'], + 'statefulness': ['statefulness', 'tastefulness'], + 'stateless': ['stateless', 'tasteless'], + 'statelich': ['athletics', 'statelich'], + 'stately': ['stately', 'stylate'], + 'statement': ['statement', 'testament'], + 'stater': ['stater', 'taster', 'testar'], + 'statesider': ['dissertate', 'statesider'], + 'static': ['static', 'sticta'], + 'statice': ['etacist', 'statice'], + 'stational': ['saltation', 'stational'], + 'stationarily': ['antiroyalist', 'stationarily'], + 'stationer': ['nitrosate', 'stationer'], + 'statoscope': ['septocosta', 'statoscope'], + 'statue': ['astute', 'statue'], + 'stature': ['stature', 'stauter'], + 'staumer': ['staumer', 'strumae'], + 'staun': ['staun', 'suant'], + 'staunch': ['canthus', 'staunch'], + 'staup': ['sputa', 'staup', 'stupa'], + 'staurion': ['staurion', 'sutorian'], + 'stauter': ['stature', 'stauter'], + 'stave': ['stave', 'vesta'], + 'staver': ['starve', 'staver', 'strave', 'tavers', 'versta'], + 'staw': ['sawt', 'staw', 'swat', 'taws', 'twas', 'wast'], + 'stawn': ['stawn', 'wasnt'], + 'stayable': ['stayable', 'teasably'], + 'stayed': ['stayed', 'steady'], + 'stayer': ['atresy', 'estray', 'reasty', 'stayer'], + 'staynil': ['nastily', 'saintly', 'staynil'], + 'stchi': ['sitch', 'stchi', 'stich'], + 'stead': ['sedat', 'stade', 'stead'], + 'steady': ['stayed', 'steady'], + 'steak': ['skate', 'stake', 'steak'], + 'steal': ['least', 'setal', 'slate', 'stale', 'steal', 'stela', 'tales'], + 'stealer': ['realest', 'reslate', 'resteal', 'stealer', 'teasler'], + 'stealing': ['galenist', 'genitals', 'stealing'], + 'stealy': ['alytes', 'astely', 'lysate', 'stealy'], + 'steam': ['steam', 'stema'], + 'steaming': ['misagent', 'steaming'], + 'stean': ['antes', 'nates', 'stane', 'stean'], + 'stearic': ['atresic', 'stearic'], + 'stearin': ['asterin', 'eranist', 'restain', 'stainer', 'starnie', 'stearin'], + 'stearone': ['orestean', 'resonate', 'stearone'], + 'stearyl': ['saltery', 'stearyl'], + 'steatin': ['atenist', 'instate', 'satient', 'steatin'], + 'steatoma': ['atmostea', 'steatoma'], + 'steatornis': ['steatornis', 'treasonist'], + 'stech': ['chest', 'stech'], + 'steek': ['keest', 'skeet', 'skete', 'steek'], + 'steel': ['sleet', 'slete', 'steel', 'stele'], + 'steeler': ['reestle', 'resteel', 'steeler'], + 'steeliness': ['sleetiness', 'steeliness'], + 'steeling': ['sleeting', 'steeling'], + 'steelproof': ['sleetproof', 'steelproof'], + 'steely': ['sleety', 'steely'], + 'steen': ['steen', 'teens', 'tense'], + 'steep': ['peste', 'steep'], + 'steeper': ['estrepe', 'resteep', 'steeper'], + 'steepy': ['steepy', 'typees'], + 'steer': ['ester', + 'estre', + 'reest', + 'reset', + 'steer', + 'stere', + 'stree', + 'terse', + 'tsere'], + 'steerer': ['reester', 'steerer'], + 'steering': ['energist', 'steering'], + 'steerling': ['esterling', 'steerling'], + 'steeve': ['steeve', 'vestee'], + 'stefan': ['fasten', 'nefast', 'stefan'], + 'steg': ['gest', 'steg'], + 'stegodon': ['dogstone', 'stegodon'], + 'steid': ['deist', 'steid'], + 'steigh': ['gesith', 'steigh'], + 'stein': ['inset', 'neist', 'snite', 'stein', 'stine', 'tsine'], + 'stela': ['least', 'setal', 'slate', 'stale', 'steal', 'stela', 'tales'], + 'stelae': ['ateles', 'saltee', 'sealet', 'stelae', 'teasel'], + 'stelai': ['isleta', 'litsea', 'salite', 'stelai'], + 'stelar': ['laster', + 'lastre', + 'rastle', + 'relast', + 'resalt', + 'salter', + 'slater', + 'stelar'], + 'stele': ['sleet', 'slete', 'steel', 'stele'], + 'stella': ['sallet', 'stella', 'talles'], + 'stellar': ['staller', 'stellar'], + 'stellaria': ['lateralis', 'stellaria'], + 'stema': ['steam', 'stema'], + 'stemlike': ['meletski', 'stemlike'], + 'sten': ['nest', 'sent', 'sten'], + 'stenar': ['astern', 'enstar', 'stenar', 'sterna'], + 'stencil': ['lentisc', 'scintle', 'stencil'], + 'stenciler': ['crestline', 'stenciler'], + 'stenion': ['stenion', 'tension'], + 'steno': ['onset', 'seton', 'steno', 'stone'], + 'stenopaic': ['aspection', 'stenopaic'], + 'stenosis': ['sisseton', 'stenosis'], + 'stenotic': ['stenotic', 'tonetics'], + 'stentor': ['snotter', 'stentor', 'torsten'], + 'step': ['pest', 'sept', 'spet', 'step'], + 'stepaunt': ['nettapus', 'stepaunt'], + 'stepbairn': ['breastpin', 'stepbairn'], + 'stepdame': ['stampede', 'stepdame'], + 'stephana': ['pheasant', 'stephana'], + 'stephanic': ['cathepsin', 'stephanic'], + 'steplike': ['spikelet', 'steplike'], + 'sterculia': ['sterculia', 'urticales'], + 'stere': ['ester', + 'estre', + 'reest', + 'reset', + 'steer', + 'stere', + 'stree', + 'terse', + 'tsere'], + 'stereograph': ['preshortage', 'stereograph'], + 'stereometric': ['crestmoreite', 'stereometric'], + 'stereophotograph': ['photostereograph', 'stereophotograph'], + 'stereotelescope': ['stereotelescope', 'telestereoscope'], + 'stereotomic': ['osteometric', 'stereotomic'], + 'stereotomical': ['osteometrical', 'stereotomical'], + 'stereotomy': ['osteometry', 'stereotomy'], + 'steric': ['certis', 'steric'], + 'sterigma': ['gemarist', 'magister', 'sterigma'], + 'sterigmata': ['magistrate', 'sterigmata'], + 'sterile': ['leister', 'sterile'], + 'sterilize': ['listerize', 'sterilize'], + 'sterin': ['estrin', 'insert', 'sinter', 'sterin', 'triens'], + 'sterlet': ['settler', 'sterlet', 'trestle'], + 'stern': ['ernst', 'stern'], + 'sterna': ['astern', 'enstar', 'stenar', 'sterna'], + 'sternad': ['stander', 'sternad'], + 'sternage': ['estrange', 'segreant', 'sergeant', 'sternage'], + 'sternal': ['saltern', 'starnel', 'sternal'], + 'sternalis': ['sternalis', 'trainless'], + 'sternite': ['insetter', 'interest', 'interset', 'sternite'], + 'sterno': ['nestor', 'sterno', 'stoner', 'strone', 'tensor'], + 'sternocostal': ['costosternal', 'sternocostal'], + 'sternovertebral': ['sternovertebral', 'vertebrosternal'], + 'stero': ['roset', 'rotse', 'soter', 'stero', 'store', 'torse'], + 'steroid': ['oestrid', 'steroid', 'storied'], + 'sterol': ['relost', 'reslot', 'rostel', 'sterol', 'torsel'], + 'stert': ['stert', 'stret', 'trest'], + 'sterve': ['revest', 'servet', 'sterve', 'verset', 'vester'], + 'stet': ['sett', 'stet', 'test'], + 'stevan': ['stevan', 'svante'], + 'stevel': ['stevel', 'svelte'], + 'stevia': ['itaves', 'stevia'], + 'stew': ['stew', 'west'], + 'stewart': ['stewart', 'swatter'], + 'stewed': ['stewed', 'wedset'], + 'stewy': ['stewy', 'westy'], + 'stey': ['stey', 'yest'], + 'sthenia': ['sethian', 'sthenia'], + 'stich': ['sitch', 'stchi', 'stich'], + 'stichid': ['distich', 'stichid'], + 'sticker': ['rickets', 'sticker'], + 'stickler': ['stickler', 'strickle'], + 'sticta': ['static', 'sticta'], + 'stife': ['feist', 'stife'], + 'stiffener': ['restiffen', 'stiffener'], + 'stifle': ['itself', 'stifle'], + 'stifler': ['slifter', 'stifler'], + 'stigmai': ['imagist', 'stigmai'], + 'stigmatical': ['stalagmitic', 'stigmatical'], + 'stilbene': ['nebelist', 'stilbene', 'tensible'], + 'stile': ['islet', 'istle', 'slite', 'stile'], + 'stileman': ['mentalis', 'smaltine', 'stileman'], + 'stillage': ['legalist', 'stillage'], + 'stiller': ['stiller', 'trellis'], + 'stillstand': ['standstill', 'stillstand'], + 'stilted': ['slitted', 'stilted'], + 'stilter': ['litster', 'slitter', 'stilter', 'testril'], + 'stilty': ['slitty', 'stilty'], + 'stim': ['mist', 'smit', 'stim'], + 'stime': ['metis', 'smite', 'stime', 'times'], + 'stimulancy': ['stimulancy', 'unmystical'], + 'stimy': ['misty', 'stimy'], + 'stine': ['inset', 'neist', 'snite', 'stein', 'stine', 'tsine'], + 'stinge': ['ingest', 'signet', 'stinge'], + 'stinger': ['resting', 'stinger'], + 'stinker': ['kirsten', 'kristen', 'stinker'], + 'stinkstone': ['knottiness', 'stinkstone'], + 'stinted': ['dentist', 'distent', 'stinted'], + 'stion': ['sinto', 'stion'], + 'stipa': ['piast', 'stipa', 'tapis'], + 'stipe': ['septi', 'spite', 'stipe'], + 'stipel': ['pistle', 'stipel'], + 'stippen': ['snippet', 'stippen'], + 'stipula': ['paulist', 'stipula'], + 'stir': ['rist', 'stir'], + 'stirk': ['skirt', 'stirk'], + 'stirp': ['spirt', 'sprit', 'stirp', 'strip'], + 'stitcher': ['restitch', 'stitcher'], + 'stiver': ['stiver', 'strive', 'verist'], + 'stoa': ['oast', 'stoa', 'taos'], + 'stoach': ['stoach', 'stocah'], + 'stoat': ['stoat', 'toast'], + 'stoater': ['retoast', 'rosetta', 'stoater', 'toaster'], + 'stocah': ['stoach', 'stocah'], + 'stoccata': ['staccato', 'stoccata'], + 'stocker': ['restock', 'stocker'], + 'stoep': ['estop', 'stoep', 'stope'], + 'stof': ['soft', 'stof'], + 'stog': ['stog', 'togs'], + 'stogie': ['egoist', 'stogie'], + 'stoic': ['ostic', 'sciot', 'stoic'], + 'stoically': ['callosity', 'stoically'], + 'stoker': ['stoker', 'stroke'], + 'stolae': ['lotase', 'osteal', 'solate', 'stolae', 'talose'], + 'stole': ['slote', 'stole'], + 'stoled': ['sloted', 'stoled'], + 'stolen': ['solent', 'stolen', 'telson'], + 'stoma': ['atmos', 'stoma', 'tomas'], + 'stomatode': ['mootstead', 'stomatode'], + 'stomatomy': ['mastotomy', 'stomatomy'], + 'stomatopoda': ['podostomata', 'stomatopoda'], + 'stomatopodous': ['podostomatous', 'stomatopodous'], + 'stomper': ['pomster', 'stomper'], + 'stone': ['onset', 'seton', 'steno', 'stone'], + 'stonebird': ['birdstone', 'stonebird'], + 'stonebreak': ['breakstone', 'stonebreak'], + 'stoned': ['doesnt', 'stoned'], + 'stonegall': ['gallstone', 'stonegall'], + 'stonehand': ['handstone', 'stonehand'], + 'stonehead': ['headstone', 'stonehead'], + 'stonen': ['sonnet', 'stonen', 'tenson'], + 'stoner': ['nestor', 'sterno', 'stoner', 'strone', 'tensor'], + 'stonewood': ['stonewood', 'woodstone'], + 'stong': ['stong', 'tongs'], + 'stonker': ['stonker', 'storken'], + 'stoof': ['foots', 'sfoot', 'stoof'], + 'stool': ['sotol', 'stool'], + 'stoon': ['snoot', 'stoon'], + 'stoop': ['spoot', 'stoop'], + 'stop': ['post', 'spot', 'stop', 'tops'], + 'stopback': ['backstop', 'stopback'], + 'stope': ['estop', 'stoep', 'stope'], + 'stoper': ['poster', 'presto', 'repost', 'respot', 'stoper'], + 'stoping': ['posting', 'stoping'], + 'stopless': ['postless', 'spotless', 'stopless'], + 'stoplessness': ['spotlessness', 'stoplessness'], + 'stoppeur': ['pteropus', 'stoppeur'], + 'storable': ['sortable', 'storable'], + 'storage': ['storage', 'tagsore'], + 'store': ['roset', 'rotse', 'soter', 'stero', 'store', 'torse'], + 'storeen': ['enstore', 'estrone', 'storeen', 'tornese'], + 'storeman': ['monaster', 'monstera', 'nearmost', 'storeman'], + 'storer': ['resort', 'roster', 'sorter', 'storer'], + 'storeship': ['posterish', 'prothesis', 'sophister', 'storeship', 'tephrosis'], + 'storesman': ['nosesmart', 'storesman'], + 'storge': ['groset', 'storge'], + 'storiate': ['astroite', 'ostraite', 'storiate'], + 'storied': ['oestrid', 'steroid', 'storied'], + 'storier': ['roister', 'storier'], + 'stork': ['stork', 'torsk'], + 'storken': ['stonker', 'storken'], + 'storm': ['storm', 'strom'], + 'stormwind': ['stormwind', 'windstorm'], + 'story': ['sorty', 'story', 'stroy'], + 'stot': ['stot', 'tost'], + 'stotter': ['stotter', 'stretto'], + 'stoun': ['notus', 'snout', 'stoun', 'tonus'], + 'stoup': ['spout', 'stoup'], + 'stour': ['roust', 'rusot', 'stour', 'sutor', 'torus'], + 'stouring': ['rousting', 'stouring'], + 'stoutly': ['stoutly', 'tylotus'], + 'stove': ['ovest', 'stove'], + 'stover': ['stover', 'strove'], + 'stow': ['sowt', 'stow', 'swot', 'wots'], + 'stowable': ['bestowal', 'stowable'], + 'stower': ['restow', 'stower', 'towser', 'worset'], + 'stra': ['sart', 'star', 'stra', 'tars', 'tsar'], + 'strad': ['darst', 'darts', 'strad'], + 'stradine': ['stradine', 'strained', 'tarnside'], + 'strae': ['aster', 'serta', 'stare', 'strae', 'tarse', 'teras'], + 'strafe': ['farset', 'faster', 'strafe'], + 'stragular': ['gastrular', 'stragular'], + 'straighten': ['shattering', 'straighten'], + 'straightener': ['restraighten', 'straightener'], + 'straightup': ['straightup', 'upstraight'], + 'straik': ['rastik', 'sarkit', 'straik'], + 'strain': ['instar', 'santir', 'strain'], + 'strained': ['stradine', 'strained', 'tarnside'], + 'strainer': ['restrain', 'strainer', 'transire'], + 'strainerman': ['strainerman', 'transmarine'], + 'straint': ['straint', 'transit', 'tristan'], + 'strait': ['artist', 'strait', 'strati'], + 'strake': ['skater', 'staker', 'strake', 'streak', 'tasker'], + 'straky': ['starky', 'straky'], + 'stram': ['smart', 'stram'], + 'strange': ['angster', 'garnets', 'nagster', 'strange'], + 'strangles': ['slangster', 'strangles'], + 'strap': ['spart', 'sprat', 'strap', 'traps'], + 'strapless': ['psaltress', 'strapless'], + 'strata': ['astart', 'strata'], + 'strategi': ['strategi', 'strigate'], + 'strath': ['strath', 'thrast'], + 'strati': ['artist', 'strait', 'strati'], + 'stratic': ['astrict', 'cartist', 'stratic'], + 'stratonic': ['narcotist', 'stratonic'], + 'stratonical': ['intracostal', 'stratonical'], + 'strave': ['starve', 'staver', 'strave', 'tavers', 'versta'], + 'straw': ['straw', 'swart', 'warst'], + 'strawy': ['strawy', 'swarty'], + 'stray': ['satyr', 'stary', 'stray', 'trasy'], + 'strayling': ['staringly', 'strayling'], + 'stre': ['rest', 'sert', 'stre'], + 'streak': ['skater', 'staker', 'strake', 'streak', 'tasker'], + 'streakily': ['satyrlike', 'streakily'], + 'stream': ['martes', 'master', 'remast', 'stream'], + 'streamer': ['masterer', 'restream', 'streamer'], + 'streamful': ['masterful', 'streamful'], + 'streamhead': ['headmaster', 'headstream', 'streamhead'], + 'streaming': ['germanist', 'streaming'], + 'streamless': ['masterless', 'streamless'], + 'streamlike': ['masterlike', 'streamlike'], + 'streamline': ['eternalism', 'streamline'], + 'streamling': ['masterling', 'streamling'], + 'streamside': ['mediatress', 'streamside'], + 'streamwort': ['masterwort', 'streamwort'], + 'streamy': ['mastery', 'streamy'], + 'stree': ['ester', + 'estre', + 'reest', + 'reset', + 'steer', + 'stere', + 'stree', + 'terse', + 'tsere'], + 'streek': ['streek', 'streke'], + 'streel': ['lester', 'selter', 'streel'], + 'streen': ['ernest', 'nester', 'resent', 'streen'], + 'streep': ['pester', 'preset', 'restep', 'streep'], + 'street': ['retest', 'setter', 'street', 'tester'], + 'streetcar': ['scatterer', 'streetcar'], + 'streke': ['streek', 'streke'], + 'strelitz': ['strelitz', 'streltzi'], + 'streltzi': ['strelitz', 'streltzi'], + 'stremma': ['stammer', 'stremma'], + 'strengthener': ['restrengthen', 'strengthener'], + 'strepen': ['penster', 'present', 'serpent', 'strepen'], + 'strepera': ['pasterer', 'strepera'], + 'strepor': ['sporter', 'strepor'], + 'strepsinema': ['esperantism', 'strepsinema'], + 'streptothricosis': ['streptothricosis', 'streptotrichosis'], + 'streptotrichosis': ['streptothricosis', 'streptotrichosis'], + 'stresser': ['restress', 'stresser'], + 'stret': ['stert', 'stret', 'trest'], + 'stretcher': ['restretch', 'stretcher'], + 'stretcherman': ['stretcherman', 'trenchmaster'], + 'stretto': ['stotter', 'stretto'], + 'strew': ['strew', 'trews', 'wrest'], + 'strewer': ['strewer', 'wrester'], + 'strey': ['resty', 'strey'], + 'streyne': ['streyne', 'styrene', 'yestern'], + 'stria': ['arist', + 'astir', + 'sitar', + 'stair', + 'stria', + 'tarsi', + 'tisar', + 'trias'], + 'striae': ['satire', 'striae'], + 'strial': ['latris', 'strial'], + 'striatal': ['altarist', 'striatal'], + 'striate': ['artiste', 'striate'], + 'striated': ['distater', 'striated'], + 'strich': ['christ', 'strich'], + 'strickle': ['stickler', 'strickle'], + 'stride': ['driest', 'stride'], + 'strife': ['fister', 'resift', 'sifter', 'strife'], + 'strig': ['grist', 'grits', 'strig'], + 'striga': ['gratis', 'striga'], + 'strigae': ['seagirt', 'strigae'], + 'strigate': ['strategi', 'strigate'], + 'striges': ['striges', 'tigress'], + 'strigulose': ['sortilegus', 'strigulose'], + 'strike': ['skiter', 'strike'], + 'striker': ['skirret', 'skirter', 'striker'], + 'striking': ['skirting', 'striking'], + 'strikingly': ['skirtingly', 'strikingly'], + 'stringer': ['restring', 'ringster', 'stringer'], + 'strinkle': ['sklinter', 'strinkle'], + 'striola': ['aristol', 'oralist', 'ortalis', 'striola'], + 'striolae': ['soterial', 'striolae'], + 'strip': ['spirt', 'sprit', 'stirp', 'strip'], + 'stripe': ['priest', 'pteris', 'sprite', 'stripe'], + 'stripeless': ['priestless', 'stripeless'], + 'striper': ['restrip', 'striper'], + 'striplet': ['splitter', 'striplet'], + 'strippit': ['strippit', 'trippist'], + 'strit': ['strit', 'trist'], + 'strive': ['stiver', 'strive', 'verist'], + 'stroam': ['stroam', 'stroma'], + 'strobila': ['laborist', 'strobila'], + 'strobilae': ['sobralite', 'strobilae'], + 'strobilate': ['brasiletto', 'strobilate'], + 'strode': ['sorted', 'strode'], + 'stroke': ['stoker', 'stroke'], + 'strom': ['storm', 'strom'], + 'stroma': ['stroam', 'stroma'], + 'stromatic': ['microstat', 'stromatic'], + 'strone': ['nestor', 'sterno', 'stoner', 'strone', 'tensor'], + 'stronghead': ['headstrong', 'stronghead'], + 'strontian': ['strontian', 'trisonant'], + 'strontianite': ['interstation', 'strontianite'], + 'strop': ['sport', 'strop'], + 'strophaic': ['actorship', 'strophaic'], + 'strophiolate': ['strophiolate', 'theatropolis'], + 'strophomena': ['nephrostoma', 'strophomena'], + 'strounge': ['strounge', 'sturgeon'], + 'stroup': ['sprout', 'stroup', 'stupor'], + 'strove': ['stover', 'strove'], + 'strow': ['strow', 'worst'], + 'stroy': ['sorty', 'story', 'stroy'], + 'strub': ['burst', 'strub'], + 'struck': ['struck', 'trucks'], + 'strue': ['serut', 'strue', 'turse', 'uster'], + 'strumae': ['staumer', 'strumae'], + 'strut': ['strut', 'sturt', 'trust'], + 'struth': ['struth', 'thrust'], + 'struthian': ['struthian', 'unathirst'], + 'stu': ['stu', 'ust'], + 'stuart': ['astrut', 'rattus', 'stuart'], + 'stub': ['bust', 'stub'], + 'stuber': ['berust', 'buster', 'stuber'], + 'stud': ['dust', 'stud'], + 'studdie': ['studdie', 'studied'], + 'student': ['student', 'stunted'], + 'studia': ['aditus', 'studia'], + 'studied': ['studdie', 'studied'], + 'study': ['dusty', 'study'], + 'stue': ['stue', 'suet'], + 'stuffer': ['restuff', 'stuffer'], + 'stug': ['gust', 'stug'], + 'stuiver': ['revuist', 'stuiver'], + 'stum': ['must', 'smut', 'stum'], + 'stumer': ['muster', 'sertum', 'stumer'], + 'stumper': ['stumper', 'sumpter'], + 'stun': ['stun', 'sunt', 'tsun'], + 'stunner': ['stunner', 'unstern'], + 'stunted': ['student', 'stunted'], + 'stunter': ['entrust', 'stunter', 'trusten'], + 'stupa': ['sputa', 'staup', 'stupa'], + 'stupe': ['setup', 'stupe', 'upset'], + 'stupor': ['sprout', 'stroup', 'stupor'], + 'stuprate': ['stuprate', 'upstater'], + 'stupulose': ['pustulose', 'stupulose'], + 'sturdiness': ['sturdiness', 'undistress'], + 'sturgeon': ['strounge', 'sturgeon'], + 'sturine': ['intruse', 'sturine'], + 'sturionine': ['reunionist', 'sturionine'], + 'sturmian': ['naturism', 'sturmian', 'turanism'], + 'sturnidae': ['disnature', 'sturnidae', 'truandise'], + 'sturninae': ['neustrian', 'saturnine', 'sturninae'], + 'sturnus': ['sturnus', 'untruss'], + 'sturt': ['strut', 'sturt', 'trust'], + 'sturtin': ['intrust', 'sturtin'], + 'stut': ['stut', 'tuts'], + 'stutter': ['stutter', 'tutster'], + 'styan': ['nasty', 'styan', 'tansy'], + 'styca': ['stacy', 'styca'], + 'stycerin': ['nycteris', 'stycerin'], + 'stygial': ['stagily', 'stygial'], + 'stylate': ['stately', 'stylate'], + 'styledom': ['modestly', 'styledom'], + 'stylite': ['stylite', 'testily'], + 'styloid': ['odylist', 'styloid'], + 'stylometer': ['metrostyle', 'stylometer'], + 'stylopidae': ['ideoplasty', 'stylopidae'], + 'styphelia': ['physalite', 'styphelia'], + 'styrene': ['streyne', 'styrene', 'yestern'], + 'styrol': ['sortly', 'styrol'], + 'stythe': ['stythe', 'tethys'], + 'styx': ['styx', 'xyst'], + 'suability': ['suability', 'usability'], + 'suable': ['suable', 'usable'], + 'sualocin': ['sualocin', 'unsocial'], + 'suant': ['staun', 'suant'], + 'suasible': ['basileus', 'issuable', 'suasible'], + 'suasion': ['sanious', 'suasion'], + 'suasory': ['ossuary', 'suasory'], + 'suave': ['sauve', 'suave'], + 'sub': ['bus', 'sub'], + 'subah': ['shuba', 'subah'], + 'subalpine': ['subalpine', 'unspiable'], + 'subanal': ['balanus', 'nabalus', 'subanal'], + 'subcaecal': ['accusable', 'subcaecal'], + 'subcantor': ['obscurant', 'subcantor'], + 'subcapsular': ['subcapsular', 'subscapular'], + 'subcenter': ['rubescent', 'subcenter'], + 'subchela': ['chasuble', 'subchela'], + 'subcool': ['colobus', 'subcool'], + 'subcortical': ['scorbutical', 'subcortical'], + 'subcortically': ['scorbutically', 'subcortically'], + 'subdealer': ['subdealer', 'subleader'], + 'subdean': ['subdean', 'unbased'], + 'subdeltaic': ['discutable', 'subdeltaic', 'subdialect'], + 'subdialect': ['discutable', 'subdeltaic', 'subdialect'], + 'subdie': ['busied', 'subdie'], + 'suber': ['burse', 'rebus', 'suber'], + 'subessential': ['subessential', 'suitableness'], + 'subherd': ['brushed', 'subherd'], + 'subhero': ['herbous', 'subhero'], + 'subhuman': ['subhuman', 'unambush'], + 'subimago': ['bigamous', 'subimago'], + 'sublanate': ['sublanate', 'unsatable'], + 'sublate': ['balteus', 'sublate'], + 'sublative': ['sublative', 'vestibula'], + 'subleader': ['subdealer', 'subleader'], + 'sublet': ['bustle', 'sublet', 'subtle'], + 'sublinear': ['insurable', 'sublinear'], + 'sublumbar': ['sublumbar', 'subumbral'], + 'submaid': ['misdaub', 'submaid'], + 'subman': ['busman', 'subman'], + 'submarine': ['semiurban', 'submarine'], + 'subnarcotic': ['obscurantic', 'subnarcotic'], + 'subnitrate': ['subnitrate', 'subtertian'], + 'subnote': ['subnote', 'subtone', 'unbesot'], + 'suboval': ['suboval', 'subvola'], + 'subpeltate': ['subpeltate', 'upsettable'], + 'subplat': ['subplat', 'upblast'], + 'subra': ['abrus', 'bursa', 'subra'], + 'subscapular': ['subcapsular', 'subscapular'], + 'subserve': ['subserve', 'subverse'], + 'subsider': ['disburse', 'subsider'], + 'substernal': ['substernal', 'turbanless'], + 'substraction': ['obscurantist', 'substraction'], + 'subtack': ['sackbut', 'subtack'], + 'subterraneal': ['subterraneal', 'unarrestable'], + 'subtertian': ['subnitrate', 'subtertian'], + 'subtle': ['bustle', 'sublet', 'subtle'], + 'subtone': ['subnote', 'subtone', 'unbesot'], + 'subtread': ['daubster', 'subtread'], + 'subtutor': ['outburst', 'subtutor'], + 'subulate': ['baetulus', 'subulate'], + 'subumbral': ['sublumbar', 'subumbral'], + 'subverse': ['subserve', 'subverse'], + 'subvola': ['suboval', 'subvola'], + 'succade': ['accused', 'succade'], + 'succeeder': ['resucceed', 'succeeder'], + 'succin': ['cnicus', 'succin'], + 'succinate': ['encaustic', 'succinate'], + 'succor': ['crocus', 'succor'], + 'such': ['cush', 'such'], + 'suck': ['cusk', 'suck'], + 'sucker': ['resuck', 'sucker'], + 'suckling': ['lungsick', 'suckling'], + 'suclat': ['scutal', 'suclat'], + 'sucramine': ['muscarine', 'sucramine'], + 'sucre': ['cruse', 'curse', 'sucre'], + 'suction': ['cotinus', 'suction', 'unstoic'], + 'suctional': ['suctional', 'sulcation', 'unstoical'], + 'suctoria': ['cotarius', 'octarius', 'suctoria'], + 'suctorial': ['ocularist', 'suctorial'], + 'sud': ['sud', 'uds'], + 'sudamen': ['medusan', 'sudamen'], + 'sudan': ['sudan', 'unsad'], + 'sudanese': ['danseuse', 'sudanese'], + 'sudani': ['sudani', 'unsaid'], + 'sudation': ['adustion', 'sudation'], + 'sudic': ['scudi', 'sudic'], + 'sudra': ['rudas', 'sudra'], + 'sue': ['sue', 'use'], + 'suer': ['ruse', 'suer', 'sure', 'user'], + 'suet': ['stue', 'suet'], + 'sufferer': ['resuffer', 'sufferer'], + 'sufflate': ['feastful', 'sufflate'], + 'suffocate': ['offuscate', 'suffocate'], + 'suffocation': ['offuscation', 'suffocation'], + 'sugamo': ['amusgo', 'sugamo'], + 'sugan': ['agnus', 'angus', 'sugan'], + 'sugar': ['argus', 'sugar'], + 'sugared': ['desugar', 'sugared'], + 'sugarlike': ['arguslike', 'sugarlike'], + 'suggester': ['resuggest', 'suggester'], + 'suggestionism': ['missuggestion', 'suggestionism'], + 'sugh': ['gush', 'shug', 'sugh'], + 'suidae': ['asideu', 'suidae'], + 'suimate': ['metusia', 'suimate', 'timaeus'], + 'suina': ['ianus', 'suina'], + 'suint': ['sintu', 'suint'], + 'suiones': ['sinuose', 'suiones'], + 'suist': ['situs', 'suist'], + 'suitable': ['sabulite', 'suitable'], + 'suitableness': ['subessential', 'suitableness'], + 'suitor': ['suitor', 'tursio'], + 'sula': ['saul', 'sula'], + 'sulcal': ['callus', 'sulcal'], + 'sulcar': ['cursal', 'sulcar'], + 'sulcation': ['suctional', 'sulcation', 'unstoical'], + 'suld': ['slud', 'suld'], + 'sulfamide': ['feudalism', 'sulfamide'], + 'sulfonium': ['fulminous', 'sulfonium'], + 'sulfuret': ['frustule', 'sulfuret'], + 'sulk': ['lusk', 'sulk'], + 'sulka': ['klaus', 'lukas', 'sulka'], + 'sulky': ['lusky', 'sulky'], + 'sulphinide': ['delphinius', 'sulphinide'], + 'sulphohydrate': ['hydrosulphate', 'sulphohydrate'], + 'sulphoproteid': ['protosulphide', 'sulphoproteid'], + 'sulphurea': ['elaphurus', 'sulphurea'], + 'sultan': ['sultan', 'unsalt'], + 'sultane': ['sultane', 'unslate'], + 'sultanian': ['annualist', 'sultanian'], + 'sultanin': ['insulant', 'sultanin'], + 'sultone': ['lentous', 'sultone'], + 'sultry': ['rustly', 'sultry'], + 'sum': ['mus', 'sum'], + 'sumac': ['camus', 'musca', 'scaum', 'sumac'], + 'sumak': ['kusam', 'sumak'], + 'sumatra': ['artamus', 'sumatra'], + 'sumerian': ['aneurism', 'arsenium', 'sumerian'], + 'sumitro': ['sumitro', 'tourism'], + 'summit': ['mutism', 'summit'], + 'summonable': ['somnambule', 'summonable'], + 'summoner': ['resummon', 'summoner'], + 'sumo': ['soum', 'sumo'], + 'sumpit': ['misput', 'sumpit'], + 'sumpitan': ['putanism', 'sumpitan'], + 'sumpter': ['stumper', 'sumpter'], + 'sumptuary': ['sputumary', 'sumptuary'], + 'sumptuous': ['sputumous', 'sumptuous'], + 'sunbeamed': ['sunbeamed', 'unembased'], + 'sundar': ['nardus', 'sundar', 'sundra'], + 'sundek': ['dusken', 'sundek'], + 'sundra': ['nardus', 'sundar', 'sundra'], + 'sung': ['snug', 'sung'], + 'sunil': ['linus', 'sunil'], + 'sunk': ['skun', 'sunk'], + 'sunlighted': ['sunlighted', 'unslighted'], + 'sunlit': ['insult', 'sunlit', 'unlist', 'unslit'], + 'sunni': ['sunni', 'unsin'], + 'sunray': ['sunray', 'surnay', 'synura'], + 'sunrise': ['russine', 'serinus', 'sunrise'], + 'sunshade': ['sunshade', 'unsashed'], + 'sunt': ['stun', 'sunt', 'tsun'], + 'sunup': ['sunup', 'upsun'], + 'sunweed': ['sunweed', 'unsewed'], + 'suomic': ['musico', 'suomic'], + 'sup': ['pus', 'sup'], + 'supa': ['apus', 'supa', 'upas'], + 'super': ['purse', 'resup', 'sprue', 'super'], + 'superable': ['perusable', 'superable'], + 'supercarpal': ['prescapular', 'supercarpal'], + 'superclaim': ['premusical', 'superclaim'], + 'supercontrol': ['preconsultor', 'supercontrol'], + 'supercool': ['escropulo', 'supercool'], + 'superheater': ['resuperheat', 'superheater'], + 'superideal': ['serpulidae', 'superideal'], + 'superintender': ['superintender', 'unenterprised'], + 'superline': ['serpuline', 'superline'], + 'supermoisten': ['sempiternous', 'supermoisten'], + 'supernacular': ['supernacular', 'supranuclear'], + 'supernal': ['purslane', 'serpulan', 'supernal'], + 'superoanterior': ['anterosuperior', 'superoanterior'], + 'superoposterior': ['posterosuperior', 'superoposterior'], + 'superpose': ['resuppose', 'superpose'], + 'superposition': ['resupposition', 'superposition'], + 'supersaint': ['presustain', 'puritaness', 'supersaint'], + 'supersalt': ['pertussal', 'supersalt'], + 'superservice': ['repercussive', 'superservice'], + 'supersonic': ['croupiness', 'percussion', 'supersonic'], + 'supertare': ['repasture', 'supertare'], + 'supertension': ['serpentinous', 'supertension'], + 'supertotal': ['supertotal', 'tetraplous'], + 'supertrain': ['rupestrian', 'supertrain'], + 'supinator': ['rainspout', 'supinator'], + 'supine': ['puisne', 'supine'], + 'supper': ['supper', 'uppers'], + 'supple': ['peplus', 'supple'], + 'suppletory': ['polypterus', 'suppletory'], + 'supplier': ['periplus', 'supplier'], + 'supporter': ['resupport', 'supporter'], + 'suppresser': ['resuppress', 'suppresser'], + 'suprahyoid': ['hyporadius', 'suprahyoid'], + 'supranuclear': ['supernacular', 'supranuclear'], + 'supreme': ['presume', 'supreme'], + 'sur': ['rus', 'sur', 'urs'], + 'sura': ['rusa', 'saur', 'sura', 'ursa', 'usar'], + 'surah': ['ashur', 'surah'], + 'surahi': ['shauri', 'surahi'], + 'sural': ['larus', 'sural', 'ursal'], + 'surat': ['astur', 'surat', 'sutra'], + 'surbase': ['rubasse', 'surbase'], + 'surbate': ['bursate', 'surbate'], + 'surcrue': ['crureus', 'surcrue'], + 'sure': ['ruse', 'suer', 'sure', 'user'], + 'suresh': ['rhesus', 'suresh'], + 'surette': ['surette', 'trustee'], + 'surge': ['grues', 'surge'], + 'surgent': ['gunster', 'surgent'], + 'surgeonship': ['springhouse', 'surgeonship'], + 'surgy': ['gyrus', 'surgy'], + 'suriana': ['saurian', 'suriana'], + 'surinam': ['surinam', 'uranism'], + 'surma': ['musar', 'ramus', 'rusma', 'surma'], + 'surmisant': ['saturnism', 'surmisant'], + 'surmise': ['misuser', 'surmise'], + 'surnap': ['surnap', 'unspar'], + 'surnay': ['sunray', 'surnay', 'synura'], + 'surprisement': ['surprisement', 'trumperiness'], + 'surrenderer': ['resurrender', 'surrenderer'], + 'surrogate': ['surrogate', 'urogaster'], + 'surrounder': ['resurround', 'surrounder'], + 'surya': ['saury', 'surya'], + 'sus': ['ssu', 'sus'], + 'susan': ['nasus', 'susan'], + 'suscept': ['suscept', 'suspect'], + 'susceptible': ['susceptible', 'suspectible'], + 'susceptor': ['spectrous', 'susceptor', 'suspector'], + 'susie': ['issue', 'susie'], + 'suspect': ['suscept', 'suspect'], + 'suspecter': ['resuspect', 'suspecter'], + 'suspectible': ['susceptible', 'suspectible'], + 'suspector': ['spectrous', 'susceptor', 'suspector'], + 'suspender': ['resuspend', 'suspender', 'unpressed'], + 'sustain': ['issuant', 'sustain'], + 'suther': ['reshut', 'suther', 'thurse', 'tusher'], + 'sutler': ['luster', 'result', 'rustle', 'sutler', 'ulster'], + 'suto': ['otus', 'oust', 'suto'], + 'sutor': ['roust', 'rusot', 'stour', 'sutor', 'torus'], + 'sutorian': ['staurion', 'sutorian'], + 'sutorious': ['sutorious', 'ustorious'], + 'sutra': ['astur', 'surat', 'sutra'], + 'suttin': ['suttin', 'tunist'], + 'suture': ['suture', 'uterus'], + 'svante': ['stevan', 'svante'], + 'svelte': ['stevel', 'svelte'], + 'swa': ['saw', 'swa', 'was'], + 'swage': ['swage', 'wages'], + 'swain': ['siwan', 'swain'], + 'swale': ['swale', 'sweal', 'wasel'], + 'swaler': ['swaler', 'warsel', 'warsle'], + 'swallet': ['setwall', 'swallet'], + 'swallo': ['sallow', 'swallo'], + 'swallower': ['reswallow', 'swallower'], + 'swami': ['aswim', 'swami'], + 'swan': ['sawn', 'snaw', 'swan'], + 'swap': ['swap', 'wasp'], + 'swarbie': ['barwise', 'swarbie'], + 'sware': ['resaw', 'sawer', 'seraw', 'sware', 'swear', 'warse'], + 'swarmer': ['reswarm', 'swarmer'], + 'swart': ['straw', 'swart', 'warst'], + 'swarty': ['strawy', 'swarty'], + 'swarve': ['swarve', 'swaver'], + 'swat': ['sawt', 'staw', 'swat', 'taws', 'twas', 'wast'], + 'swath': ['swath', 'whats'], + 'swathe': ['swathe', 'sweath'], + 'swati': ['swati', 'waist'], + 'swatter': ['stewart', 'swatter'], + 'swaver': ['swarve', 'swaver'], + 'sway': ['sway', 'ways', 'yaws'], + 'swayer': ['sawyer', 'swayer'], + 'sweal': ['swale', 'sweal', 'wasel'], + 'swear': ['resaw', 'sawer', 'seraw', 'sware', 'swear', 'warse'], + 'swearer': ['resawer', 'reswear', 'swearer'], + 'sweat': ['awest', 'sweat', 'tawse', 'waste'], + 'sweater': ['resweat', 'sweater'], + 'sweatful': ['sweatful', 'wasteful'], + 'sweath': ['swathe', 'sweath'], + 'sweatily': ['sweatily', 'tileways'], + 'sweatless': ['sweatless', 'wasteless'], + 'sweatproof': ['sweatproof', 'wasteproof'], + 'swede': ['sewed', 'swede'], + 'sweep': ['sweep', 'weeps'], + 'sweeper': ['resweep', 'sweeper'], + 'sweer': ['resew', 'sewer', 'sweer'], + 'sweered': ['sewered', 'sweered'], + 'sweet': ['sweet', 'weste'], + 'sweetbread': ['breastweed', 'sweetbread'], + 'sweller': ['reswell', 'sweller'], + 'swelter': ['swelter', 'wrestle'], + 'swep': ['spew', 'swep'], + 'swertia': ['swertia', 'waister'], + 'swile': ['lewis', 'swile'], + 'swiller': ['reswill', 'swiller'], + 'swindle': ['swindle', 'windles'], + 'swine': ['sinew', 'swine', 'wisen'], + 'swinestone': ['sonnetwise', 'swinestone'], + 'swiney': ['sinewy', 'swiney'], + 'swingback': ['backswing', 'swingback'], + 'swinge': ['sewing', 'swinge'], + 'swingle': ['slewing', 'swingle'], + 'swingtree': ['swingtree', 'westering'], + 'swipy': ['swipy', 'wispy'], + 'swire': ['swire', 'wiser'], + 'swith': ['swith', 'whist', 'whits', 'wisht'], + 'swithe': ['swithe', 'whites'], + 'swither': ['swither', 'whister', 'withers'], + 'swoon': ['swoon', 'woons'], + 'swordman': ['sandworm', 'swordman', 'wordsman'], + 'swordmanship': ['swordmanship', 'wordsmanship'], + 'swore': ['owser', 'resow', 'serow', 'sower', 'swore', 'worse'], + 'swot': ['sowt', 'stow', 'swot', 'wots'], + 'sybarite': ['bestiary', 'sybarite'], + 'sybil': ['sibyl', 'sybil'], + 'syce': ['scye', 'syce'], + 'sycones': ['coyness', 'sycones'], + 'syconoid': ['syconoid', 'syodicon'], + 'sye': ['sey', 'sye', 'yes'], + 'syenitic': ['cytisine', 'syenitic'], + 'syllabi': ['sibylla', 'syllabi'], + 'syllable': ['sellably', 'syllable'], + 'sylva': ['salvy', 'sylva'], + 'sylvae': ['slavey', 'sylvae'], + 'sylvine': ['snively', 'sylvine'], + 'sylvite': ['levyist', 'sylvite'], + 'symbol': ['blosmy', 'symbol'], + 'symmetric': ['mycterism', 'symmetric'], + 'sympathy': ['sympathy', 'symphyta'], + 'symphonic': ['cyphonism', 'symphonic'], + 'symphyta': ['sympathy', 'symphyta'], + 'symposion': ['spoonyism', 'symposion'], + 'synapse': ['synapse', 'yapness'], + 'synaptera': ['peasantry', 'synaptera'], + 'syncopator': ['antroscopy', 'syncopator'], + 'syndicate': ['asyndetic', 'cystidean', 'syndicate'], + 'synedral': ['lysander', 'synedral'], + 'syngamic': ['gymnasic', 'syngamic'], + 'syngenic': ['ensigncy', 'syngenic'], + 'synura': ['sunray', 'surnay', 'synura'], + 'syodicon': ['syconoid', 'syodicon'], + 'sypher': ['sphery', 'sypher'], + 'syphiloid': ['hypsiloid', 'syphiloid'], + 'syrian': ['siryan', 'syrian'], + 'syringa': ['signary', 'syringa'], + 'syringeful': ['refusingly', 'syringeful'], + 'syrup': ['pursy', 'pyrus', 'syrup'], + 'system': ['mystes', 'system'], + 'systole': ['systole', 'toyless'], + 'ta': ['at', 'ta'], + 'taa': ['ata', 'taa'], + 'taal': ['lata', 'taal', 'tala'], + 'taar': ['rata', 'taar', 'tara'], + 'tab': ['bat', 'tab'], + 'tabanus': ['sabanut', 'sabutan', 'tabanus'], + 'tabaret': ['baretta', 'rabatte', 'tabaret'], + 'tabber': ['barbet', 'rabbet', 'tabber'], + 'tabella': ['ballate', 'tabella'], + 'tabes': ['baste', 'beast', 'tabes'], + 'tabet': ['betta', 'tabet'], + 'tabinet': ['bettina', 'tabinet', 'tibetan'], + 'tabira': ['arabit', 'tabira'], + 'tabitha': ['habitat', 'tabitha'], + 'tabitude': ['dubitate', 'tabitude'], + 'table': ['batel', 'blate', 'bleat', 'table'], + 'tabled': ['dablet', 'tabled'], + 'tablemaker': ['marketable', 'tablemaker'], + 'tabler': ['albert', 'balter', 'labret', 'tabler'], + 'tables': ['ablest', 'stable', 'tables'], + 'tablet': ['battel', 'battle', 'tablet'], + 'tabletary': ['tabletary', 'treatably'], + 'tabling': ['batling', 'tabling'], + 'tabophobia': ['batophobia', 'tabophobia'], + 'tabor': ['abort', 'tabor'], + 'taborer': ['arboret', 'roberta', 'taborer'], + 'taboret': ['abettor', 'taboret'], + 'taborin': ['abortin', 'taborin'], + 'tabour': ['outbar', 'rubato', 'tabour'], + 'tabouret': ['obturate', 'tabouret'], + 'tabret': ['batter', 'bertat', 'tabret', 'tarbet'], + 'tabu': ['abut', 'tabu', 'tuba'], + 'tabula': ['ablaut', 'tabula'], + 'tabulare': ['bataleur', 'tabulare'], + 'tabule': ['batule', 'betula', 'tabule'], + 'taccaceae': ['cactaceae', 'taccaceae'], + 'taccaceous': ['cactaceous', 'taccaceous'], + 'tach': ['chat', 'tach'], + 'tache': ['cheat', 'tache', 'teach', 'theca'], + 'tacheless': ['tacheless', 'teachless'], + 'tachina': ['ithacan', 'tachina'], + 'tachinidae': ['anthicidae', 'tachinidae'], + 'tachograph': ['cathograph', 'tachograph'], + 'tacit': ['attic', 'catti', 'tacit'], + 'tacitly': ['cattily', 'tacitly'], + 'tacitness': ['cattiness', 'tacitness'], + 'taciturn': ['taciturn', 'urticant'], + 'tacker': ['racket', 'retack', 'tacker'], + 'tacksman': ['stackman', 'tacksman'], + 'taconian': ['catonian', 'taconian'], + 'taconic': ['cantico', 'catonic', 'taconic'], + 'tacso': ['ascot', 'coast', 'costa', 'tacso', 'tasco'], + 'tacsonia': ['acontias', 'tacsonia'], + 'tactile': ['lattice', 'tactile'], + 'tade': ['adet', 'date', 'tade', 'tead', 'teda'], + 'tadpole': ['platode', 'tadpole'], + 'tae': ['ate', 'eat', 'eta', 'tae', 'tea'], + 'tael': ['atle', 'laet', 'late', 'leat', 'tael', 'tale', 'teal'], + 'taen': ['ante', 'aten', 'etna', 'nate', 'neat', 'taen', 'tane', 'tean'], + 'taenia': ['aetian', 'antiae', 'taenia'], + 'taeniada': ['anatidae', 'taeniada'], + 'taenial': ['laniate', 'natalie', 'taenial'], + 'taenian': ['ananite', 'anatine', 'taenian'], + 'taenicide': ['deciatine', 'diacetine', 'taenicide', 'teniacide'], + 'taeniform': ['forminate', 'fremontia', 'taeniform'], + 'taenioid': ['ideation', 'iodinate', 'taenioid'], + 'taetsia': ['isatate', 'satiate', 'taetsia'], + 'tag': ['gat', 'tag'], + 'tagetes': ['gestate', 'tagetes'], + 'tagetol': ['lagetto', 'tagetol'], + 'tagged': ['gadget', 'tagged'], + 'tagger': ['garget', 'tagger'], + 'tagilite': ['litigate', 'tagilite'], + 'tagish': ['ghaist', 'tagish'], + 'taglike': ['glaiket', 'taglike'], + 'tagrag': ['ragtag', 'tagrag'], + 'tagsore': ['storage', 'tagsore'], + 'taheen': ['ethane', 'taheen'], + 'tahil': ['ihlat', 'tahil'], + 'tahin': ['ahint', 'hiant', 'tahin'], + 'tahr': ['hart', 'rath', 'tahr', 'thar', 'trah'], + 'tahsil': ['latish', 'tahsil'], + 'tahsin': ['snaith', 'tahsin'], + 'tai': ['ait', 'ati', 'ita', 'tai'], + 'taich': ['aitch', 'chait', 'chati', 'chita', 'taich', 'tchai'], + 'taigle': ['aiglet', 'ligate', 'taigle', 'tailge'], + 'tail': ['alit', 'tail', 'tali'], + 'tailage': ['agalite', 'tailage', 'taliage'], + 'tailboard': ['broadtail', 'tailboard'], + 'tailed': ['detail', 'dietal', 'dilate', 'edital', 'tailed'], + 'tailer': ['lirate', 'retail', 'retial', 'tailer'], + 'tailet': ['latite', 'tailet', 'tailte', 'talite'], + 'tailge': ['aiglet', 'ligate', 'taigle', 'tailge'], + 'tailing': ['gitalin', 'tailing'], + 'taille': ['taille', 'telial'], + 'tailoring': ['gratiolin', 'largition', 'tailoring'], + 'tailorman': ['antimoral', 'tailorman'], + 'tailory': ['orality', 'tailory'], + 'tailpin': ['pintail', 'tailpin'], + 'tailsman': ['staminal', 'tailsman', 'talisman'], + 'tailte': ['latite', 'tailet', 'tailte', 'talite'], + 'taily': ['laity', 'taily'], + 'taimen': ['etamin', 'inmate', 'taimen', 'tamein'], + 'tain': ['aint', 'anti', 'tain', 'tina'], + 'tainan': ['naiant', 'tainan'], + 'taino': ['niota', 'taino'], + 'taint': ['taint', 'tanti', 'tinta', 'titan'], + 'tainture': ['tainture', 'unattire'], + 'taipan': ['aptian', 'patina', 'taipan'], + 'taipo': ['patio', 'taipo', 'topia'], + 'tairge': ['gaiter', 'tairge', 'triage'], + 'tairn': ['riant', 'tairn', 'tarin', 'train'], + 'taise': ['saite', 'taise'], + 'taistrel': ['starlite', 'taistrel'], + 'taistril': ['taistril', 'trialist'], + 'taivers': ['staiver', 'taivers'], + 'taj': ['jat', 'taj'], + 'tajik': ['jatki', 'tajik'], + 'takar': ['katar', 'takar'], + 'take': ['kate', 'keta', 'take', 'teak'], + 'takedown': ['downtake', 'takedown'], + 'taker': ['kerat', 'taker'], + 'takin': ['kitan', 'takin'], + 'takings': ['gitksan', 'skating', 'takings'], + 'taky': ['katy', 'kyat', 'taky'], + 'tal': ['alt', 'lat', 'tal'], + 'tala': ['lata', 'taal', 'tala'], + 'talapoin': ['palation', 'talapoin'], + 'talar': ['altar', 'artal', 'ratal', 'talar'], + 'talari': ['altair', 'atrail', 'atrial', 'lariat', 'latria', 'talari'], + 'talc': ['clat', 'talc'], + 'talcer': ['carlet', 'cartel', 'claret', 'rectal', 'talcer'], + 'talcher': ['clethra', 'latcher', 'ratchel', 'relatch', 'talcher', 'trachle'], + 'talcoid': ['cotidal', 'lactoid', 'talcoid'], + 'talcose': ['alecost', 'lactose', 'scotale', 'talcose'], + 'talcous': ['costula', 'locusta', 'talcous'], + 'tald': ['dalt', 'tald'], + 'tale': ['atle', 'laet', 'late', 'leat', 'tael', 'tale', 'teal'], + 'taled': ['adlet', 'dealt', 'delta', 'lated', 'taled'], + 'talent': ['latent', 'latten', 'nattle', 'talent', 'tantle'], + 'taler': ['alert', 'alter', 'artel', 'later', 'ratel', 'taler', 'telar'], + 'tales': ['least', 'setal', 'slate', 'stale', 'steal', 'stela', 'tales'], + 'tali': ['alit', 'tail', 'tali'], + 'taliage': ['agalite', 'tailage', 'taliage'], + 'taligrade': ['taligrade', 'tragedial'], + 'talinum': ['multani', 'talinum'], + 'talion': ['italon', 'lation', 'talion'], + 'taliped': ['plaited', 'taliped'], + 'talipedic': ['talipedic', 'talpicide'], + 'talipes': ['aliptes', 'pastile', 'talipes'], + 'talipot': ['ptilota', 'talipot', 'toptail'], + 'talis': ['alist', 'litas', 'slait', 'talis'], + 'talisman': ['staminal', 'tailsman', 'talisman'], + 'talite': ['latite', 'tailet', 'tailte', 'talite'], + 'talker': ['kartel', 'retalk', 'talker'], + 'tallage': ['gallate', 'tallage'], + 'tallero': ['reallot', 'rotella', 'tallero'], + 'talles': ['sallet', 'stella', 'talles'], + 'talliage': ['allagite', 'alligate', 'talliage'], + 'tallier': ['literal', 'tallier'], + 'tallyho': ['loathly', 'tallyho'], + 'talon': ['notal', 'ontal', 'talon', 'tolan', 'tonal'], + 'taloned': ['taloned', 'toledan'], + 'talonid': ['itoland', 'talonid', 'tindalo'], + 'talose': ['lotase', 'osteal', 'solate', 'stolae', 'talose'], + 'talpa': ['aptal', 'palta', 'talpa'], + 'talpicide': ['talipedic', 'talpicide'], + 'talpidae': ['lapidate', 'talpidae'], + 'talpine': ['pantile', 'pentail', 'platine', 'talpine'], + 'talpoid': ['platoid', 'talpoid'], + 'taluche': ['auchlet', 'cutheal', 'taluche'], + 'taluka': ['latuka', 'taluka'], + 'talus': ['latus', 'sault', 'talus'], + 'tam': ['amt', 'mat', 'tam'], + 'tama': ['atma', 'tama'], + 'tamale': ['malate', 'meatal', 'tamale'], + 'tamanac': ['matacan', 'tamanac'], + 'tamanaca': ['atacaman', 'tamanaca'], + 'tamanoir': ['animator', 'tamanoir'], + 'tamanu': ['anatum', 'mantua', 'tamanu'], + 'tamara': ['armata', 'matara', 'tamara'], + 'tamarao': ['tamarao', 'tamaroa'], + 'tamarin': ['martian', 'tamarin'], + 'tamaroa': ['tamarao', 'tamaroa'], + 'tambor': ['tambor', 'tromba'], + 'tamboura': ['marabout', 'marabuto', 'tamboura'], + 'tambourer': ['arboretum', 'tambourer'], + 'tambreet': ['ambrette', 'tambreet'], + 'tamburan': ['rambutan', 'tamburan'], + 'tame': ['mate', 'meat', 'meta', 'tame', 'team', 'tema'], + 'tamein': ['etamin', 'inmate', 'taimen', 'tamein'], + 'tameless': ['mateless', 'meatless', 'tameless', 'teamless'], + 'tamelessness': ['matelessness', 'tamelessness'], + 'tamely': ['mately', 'tamely'], + 'tamer': ['armet', + 'mater', + 'merat', + 'metra', + 'ramet', + 'tamer', + 'terma', + 'trame', + 'trema'], + 'tamise': ['samite', 'semita', 'tamise', 'teaism'], + 'tampin': ['pitman', 'tampin', 'tipman'], + 'tampion': ['maintop', 'ptomain', 'tampion', 'timpano'], + 'tampioned': ['ademption', 'tampioned'], + 'tampon': ['potman', 'tampon', 'topman'], + 'tamul': ['lamut', 'tamul'], + 'tamus': ['matsu', 'tamus', 'tsuma'], + 'tan': ['ant', 'nat', 'tan'], + 'tana': ['anat', 'anta', 'tana'], + 'tanach': ['acanth', 'anchat', 'tanach'], + 'tanager': ['argante', 'granate', 'tanager'], + 'tanagridae': ['tanagridae', 'tangaridae'], + 'tanagrine': ['argentina', 'tanagrine'], + 'tanagroid': ['gradation', 'indagator', 'tanagroid'], + 'tanak': ['kanat', 'tanak', 'tanka'], + 'tanaka': ['nataka', 'tanaka'], + 'tanala': ['atalan', 'tanala'], + 'tanan': ['annat', 'tanan'], + 'tanbur': ['tanbur', 'turban'], + 'tancel': ['cantle', 'cental', 'lancet', 'tancel'], + 'tanchoir': ['anorthic', 'anthroic', 'tanchoir'], + 'tandemist': ['misattend', 'tandemist'], + 'tandle': ['dental', 'tandle'], + 'tandour': ['rotunda', 'tandour'], + 'tane': ['ante', 'aten', 'etna', 'nate', 'neat', 'taen', 'tane', 'tean'], + 'tang': ['gant', 'gnat', 'tang'], + 'tanga': ['ganta', 'tanga'], + 'tangaridae': ['tanagridae', 'tangaridae'], + 'tangelo': ['angelot', 'tangelo'], + 'tanger': ['argent', 'garnet', 'garten', 'tanger'], + 'tangerine': ['argentine', 'tangerine'], + 'tangfish': ['shafting', 'tangfish'], + 'tangi': ['giant', 'tangi', 'tiang'], + 'tangibile': ['bigential', 'tangibile'], + 'tangible': ['bleating', 'tangible'], + 'tangie': ['eating', 'ingate', 'tangie'], + 'tangier': ['angrite', 'granite', 'ingrate', 'tangier', 'tearing', 'tigrean'], + 'tangle': ['tangle', 'telang'], + 'tangling': ['gnatling', 'tangling'], + 'tango': ['tango', 'tonga'], + 'tangs': ['angst', 'stang', 'tangs'], + 'tangue': ['gunate', 'tangue'], + 'tangum': ['tangum', 'tugman'], + 'tangun': ['tangun', 'tungan'], + 'tanh': ['hant', 'tanh', 'than'], + 'tanha': ['atnah', 'tanha', 'thana'], + 'tania': ['anita', 'niata', 'tania'], + 'tanica': ['actian', 'natica', 'tanica'], + 'tanier': ['nerita', 'ratine', 'retain', 'retina', 'tanier'], + 'tanist': ['astint', 'tanist'], + 'tanitic': ['tanitic', 'titanic'], + 'tanka': ['kanat', 'tanak', 'tanka'], + 'tankle': ['anklet', 'lanket', 'tankle'], + 'tanling': ['antling', 'tanling'], + 'tannaic': ['cantina', 'tannaic'], + 'tannase': ['annates', 'tannase'], + 'tannogallate': ['gallotannate', 'tannogallate'], + 'tannogallic': ['gallotannic', 'tannogallic'], + 'tannogen': ['nonagent', 'tannogen'], + 'tanproof': ['antproof', 'tanproof'], + 'tanquen': ['quannet', 'tanquen'], + 'tanrec': ['canter', + 'creant', + 'cretan', + 'nectar', + 'recant', + 'tanrec', + 'trance'], + 'tansy': ['nasty', 'styan', 'tansy'], + 'tantalean': ['antenatal', 'atlantean', 'tantalean'], + 'tantalic': ['atlantic', 'tantalic'], + 'tantalite': ['atlantite', 'tantalite'], + 'tantara': ['tantara', 'tartana'], + 'tantarara': ['tantarara', 'tarantara'], + 'tanti': ['taint', 'tanti', 'tinta', 'titan'], + 'tantle': ['latent', 'latten', 'nattle', 'talent', 'tantle'], + 'tantra': ['rattan', 'tantra', 'tartan'], + 'tantrism': ['tantrism', 'transmit'], + 'tantum': ['mutant', 'tantum', 'tutman'], + 'tanzeb': ['batzen', 'bezant', 'tanzeb'], + 'tao': ['oat', 'tao', 'toa'], + 'taoistic': ['iotacist', 'taoistic'], + 'taos': ['oast', 'stoa', 'taos'], + 'tap': ['apt', 'pat', 'tap'], + 'tapa': ['atap', 'pata', 'tapa'], + 'tapalo': ['patola', 'tapalo'], + 'tapas': ['patas', 'tapas'], + 'tape': ['pate', 'peat', 'tape', 'teap'], + 'tapeline': ['petaline', 'tapeline'], + 'tapeman': ['peatman', 'tapeman'], + 'tapen': ['enapt', 'paten', 'penta', 'tapen'], + 'taper': ['apert', 'pater', 'peart', 'prate', 'taper', 'terap'], + 'tapered': ['padtree', 'predate', 'tapered'], + 'tapering': ['partigen', 'tapering'], + 'taperly': ['apertly', 'peartly', 'platery', 'pteryla', 'taperly'], + 'taperness': ['apertness', 'peartness', 'taperness'], + 'tapestring': ['spattering', 'tapestring'], + 'tapestry': ['tapestry', 'tryptase'], + 'tapet': ['patte', 'tapet'], + 'tapete': ['pattee', 'tapete'], + 'taphouse': ['outshape', 'taphouse'], + 'taphria': ['pitarah', 'taphria'], + 'taphrina': ['parthian', 'taphrina'], + 'tapir': ['atrip', 'tapir'], + 'tapiro': ['portia', 'tapiro'], + 'tapirus': ['tapirus', 'upstair'], + 'tapis': ['piast', 'stipa', 'tapis'], + 'taplash': ['asphalt', 'spathal', 'taplash'], + 'tapmost': ['tapmost', 'topmast'], + 'tapnet': ['patent', 'patten', 'tapnet'], + 'tapoa': ['opata', 'patao', 'tapoa'], + 'taposa': ['sapota', 'taposa'], + 'taproom': ['protoma', 'taproom'], + 'taproot': ['potator', 'taproot'], + 'taps': ['past', 'spat', 'stap', 'taps'], + 'tapster': ['spatter', 'tapster'], + 'tapu': ['patu', 'paut', 'tapu'], + 'tapuyo': ['outpay', 'tapuyo'], + 'taqua': ['quata', 'taqua'], + 'tar': ['art', 'rat', 'tar', 'tra'], + 'tara': ['rata', 'taar', 'tara'], + 'taraf': ['taraf', 'tarfa'], + 'tarai': ['arati', 'atria', 'riata', 'tarai', 'tiara'], + 'taranchi': ['taranchi', 'thracian'], + 'tarantara': ['tantarara', 'tarantara'], + 'tarapin': ['patarin', 'tarapin'], + 'tarasc': ['castra', 'tarasc'], + 'tarbet': ['batter', 'bertat', 'tabret', 'tarbet'], + 'tardle': ['dartle', 'tardle'], + 'tardy': ['tardy', 'trady'], + 'tare': ['rate', 'tare', 'tear', 'tera'], + 'tarente': ['entreat', 'ratteen', 'tarente', 'ternate', 'tetrane'], + 'tarentine': ['entertain', 'tarentine', 'terentian'], + 'tarfa': ['taraf', 'tarfa'], + 'targe': ['gater', 'grate', 'great', 'greta', 'retag', 'targe'], + 'targeman': ['grateman', 'mangrate', 'mentagra', 'targeman'], + 'targer': ['garret', 'garter', 'grater', 'targer'], + 'target': ['gatter', 'target'], + 'targetman': ['targetman', 'termagant'], + 'targum': ['artgum', 'targum'], + 'tarheel': ['leather', 'tarheel'], + 'tarheeler': ['leatherer', 'releather', 'tarheeler'], + 'tari': ['airt', 'rita', 'tari', 'tiar'], + 'tarie': ['arite', 'artie', 'irate', 'retia', 'tarie'], + 'tarin': ['riant', 'tairn', 'tarin', 'train'], + 'tarish': ['rashti', 'tarish'], + 'tarletan': ['alterant', 'tarletan'], + 'tarlike': ['artlike', 'ratlike', 'tarlike'], + 'tarmac': ['mactra', 'tarmac'], + 'tarman': ['mantra', 'tarman'], + 'tarmi': ['mitra', 'tarmi', 'timar', 'tirma'], + 'tarn': ['natr', 'rant', 'tarn', 'tran'], + 'tarnal': ['antral', 'tarnal'], + 'tarnish': ['tarnish', 'trishna'], + 'tarnside': ['stradine', 'strained', 'tarnside'], + 'taro': ['rota', 'taro', 'tora'], + 'taroc': ['actor', 'corta', 'croat', 'rocta', 'taroc', 'troca'], + 'tarocco': ['coactor', 'tarocco'], + 'tarok': ['kotar', 'tarok'], + 'tarot': ['ottar', 'tarot', 'torta', 'troat'], + 'tarp': ['part', 'prat', 'rapt', 'tarp', 'trap'], + 'tarpan': ['partan', 'tarpan'], + 'tarpaulin': ['tarpaulin', 'unpartial'], + 'tarpeian': ['patarine', 'tarpeian'], + 'tarpon': ['patron', 'tarpon'], + 'tarquin': ['quatrin', 'tarquin'], + 'tarragon': ['arrogant', 'tarragon'], + 'tarred': ['darter', + 'dartre', + 'redart', + 'retard', + 'retrad', + 'tarred', + 'trader'], + 'tarrer': ['tarrer', 'terrar'], + 'tarriance': ['antiracer', 'tarriance'], + 'tarrie': ['arriet', 'tarrie'], + 'tars': ['sart', 'star', 'stra', 'tars', 'tsar'], + 'tarsal': ['astral', 'tarsal'], + 'tarsale': ['alaster', 'tarsale'], + 'tarsalgia': ['astragali', 'tarsalgia'], + 'tarse': ['aster', 'serta', 'stare', 'strae', 'tarse', 'teras'], + 'tarsi': ['arist', + 'astir', + 'sitar', + 'stair', + 'stria', + 'tarsi', + 'tisar', + 'trias'], + 'tarsia': ['arista', 'tarsia'], + 'tarsier': ['astrier', 'tarsier'], + 'tarsipes': ['piratess', 'serapist', 'tarsipes'], + 'tarsitis': ['satirist', 'tarsitis'], + 'tarsome': ['maestro', 'tarsome'], + 'tarsonemid': ['mosandrite', 'tarsonemid'], + 'tarsonemus': ['sarmentous', 'tarsonemus'], + 'tarsus': ['rastus', 'tarsus'], + 'tartan': ['rattan', 'tantra', 'tartan'], + 'tartana': ['tantara', 'tartana'], + 'tartaret': ['tartaret', 'tartrate'], + 'tartarin': ['tartarin', 'triratna'], + 'tartarous': ['saturator', 'tartarous'], + 'tarten': ['attern', 'natter', 'ratten', 'tarten'], + 'tartish': ['athirst', 'rattish', 'tartish'], + 'tartle': ['artlet', 'latter', 'rattle', 'tartle', 'tatler'], + 'tartlet': ['tartlet', 'tattler'], + 'tartly': ['rattly', 'tartly'], + 'tartrate': ['tartaret', 'tartrate'], + 'taruma': ['taruma', 'trauma'], + 'tarve': ['avert', 'tarve', 'taver', 'trave'], + 'tarweed': ['dewater', 'tarweed', 'watered'], + 'tarwood': ['ratwood', 'tarwood'], + 'taryba': ['baryta', 'taryba'], + 'tasco': ['ascot', 'coast', 'costa', 'tacso', 'tasco'], + 'tash': ['shat', 'tash'], + 'tasheriff': ['fireshaft', 'tasheriff'], + 'tashie': ['saithe', 'tashie', 'teaish'], + 'tashrif': ['ratfish', 'tashrif'], + 'tasian': ['astian', 'tasian'], + 'tasimetry': ['myristate', 'tasimetry'], + 'task': ['skat', 'task'], + 'tasker': ['skater', 'staker', 'strake', 'streak', 'tasker'], + 'taslet': ['latest', 'sattle', 'taslet'], + 'tasmanite': ['emanatist', 'staminate', 'tasmanite'], + 'tassah': ['shasta', 'tassah'], + 'tasse': ['asset', 'tasse'], + 'tassel': ['lasset', 'tassel'], + 'tasseler': ['rateless', 'tasseler', 'tearless', 'tesseral'], + 'tasser': ['assert', 'tasser'], + 'tassie': ['siesta', 'tassie'], + 'tastable': ['statable', 'tastable'], + 'taste': ['state', 'taste', 'tates', 'testa'], + 'tasted': ['stated', 'tasted'], + 'tasteful': ['stateful', 'tasteful'], + 'tastefully': ['statefully', 'tastefully'], + 'tastefulness': ['statefulness', 'tastefulness'], + 'tasteless': ['stateless', 'tasteless'], + 'taster': ['stater', 'taster', 'testar'], + 'tasu': ['saut', 'tasu', 'utas'], + 'tatar': ['attar', 'tatar'], + 'tatarize': ['tatarize', 'zaratite'], + 'tatchy': ['chatty', 'tatchy'], + 'tate': ['etta', 'tate', 'teat'], + 'tater': ['atter', 'tater', 'teart', 'tetra', 'treat'], + 'tates': ['state', 'taste', 'tates', 'testa'], + 'tath': ['hatt', 'tath', 'that'], + 'tatian': ['attain', 'tatian'], + 'tatler': ['artlet', 'latter', 'rattle', 'tartle', 'tatler'], + 'tatterly': ['tatterly', 'tattlery'], + 'tattler': ['tartlet', 'tattler'], + 'tattlery': ['tatterly', 'tattlery'], + 'tatu': ['tatu', 'taut'], + 'tau': ['tau', 'tua', 'uta'], + 'taube': ['butea', 'taube', 'tubae'], + 'taula': ['aluta', 'taula'], + 'taum': ['muta', 'taum'], + 'taun': ['antu', 'aunt', 'naut', 'taun', 'tuan', 'tuna'], + 'taungthu': ['taungthu', 'untaught'], + 'taupe': ['taupe', 'upeat'], + 'taupo': ['apout', 'taupo'], + 'taur': ['ruta', 'taur'], + 'taurean': ['taurean', 'uranate'], + 'tauric': ['tauric', 'uratic', 'urtica'], + 'taurine': ['ruinate', 'taurine', 'uranite', 'urinate'], + 'taurocol': ['outcarol', 'taurocol'], + 'taut': ['tatu', 'taut'], + 'tauten': ['attune', 'nutate', 'tauten'], + 'tautomeric': ['autometric', 'tautomeric'], + 'tautomery': ['autometry', 'tautomery'], + 'tav': ['tav', 'vat'], + 'tavast': ['sattva', 'tavast'], + 'tave': ['tave', 'veta'], + 'taver': ['avert', 'tarve', 'taver', 'trave'], + 'tavers': ['starve', 'staver', 'strave', 'tavers', 'versta'], + 'tavert': ['tavert', 'vatter'], + 'tavola': ['tavola', 'volata'], + 'taw': ['taw', 'twa', 'wat'], + 'tawa': ['awat', 'tawa'], + 'tawer': ['tawer', 'water', 'wreat'], + 'tawery': ['tawery', 'watery'], + 'tawite': ['tawite', 'tawtie', 'twaite'], + 'tawn': ['nawt', 'tawn', 'want'], + 'tawny': ['tawny', 'wanty'], + 'taws': ['sawt', 'staw', 'swat', 'taws', 'twas', 'wast'], + 'tawse': ['awest', 'sweat', 'tawse', 'waste'], + 'tawtie': ['tawite', 'tawtie', 'twaite'], + 'taxed': ['detax', 'taxed'], + 'taxer': ['extra', 'retax', 'taxer'], + 'tay': ['tay', 'yat'], + 'tayer': ['tayer', 'teary'], + 'tchai': ['aitch', 'chait', 'chati', 'chita', 'taich', 'tchai'], + 'tche': ['chet', 'etch', 'tche', 'tech'], + 'tchi': ['chit', 'itch', 'tchi'], + 'tchu': ['chut', 'tchu', 'utch'], + 'tchwi': ['tchwi', 'wicht', 'witch'], + 'tea': ['ate', 'eat', 'eta', 'tae', 'tea'], + 'teaberry': ['betrayer', 'eatberry', 'rebetray', 'teaberry'], + 'teaboy': ['betoya', 'teaboy'], + 'teacart': ['caretta', 'teacart', 'tearcat'], + 'teach': ['cheat', 'tache', 'teach', 'theca'], + 'teachable': ['cheatable', 'teachable'], + 'teachableness': ['cheatableness', 'teachableness'], + 'teache': ['achete', 'hecate', 'teache', 'thecae'], + 'teacher': ['cheater', 'hectare', 'recheat', 'reteach', 'teacher'], + 'teachery': ['cheatery', 'cytherea', 'teachery'], + 'teaching': ['cheating', 'teaching'], + 'teachingly': ['cheatingly', 'teachingly'], + 'teachless': ['tacheless', 'teachless'], + 'tead': ['adet', 'date', 'tade', 'tead', 'teda'], + 'teaer': ['arete', 'eater', 'teaer'], + 'teagle': ['eaglet', 'legate', 'teagle', 'telega'], + 'teaish': ['saithe', 'tashie', 'teaish'], + 'teaism': ['samite', 'semita', 'tamise', 'teaism'], + 'teak': ['kate', 'keta', 'take', 'teak'], + 'teal': ['atle', 'laet', 'late', 'leat', 'tael', 'tale', 'teal'], + 'team': ['mate', 'meat', 'meta', 'tame', 'team', 'tema'], + 'teamer': ['reetam', 'retame', 'teamer'], + 'teaming': ['mintage', 'teaming', 'tegmina'], + 'teamless': ['mateless', 'meatless', 'tameless', 'teamless'], + 'teamman': ['meatman', 'teamman'], + 'teamster': ['teamster', 'trametes'], + 'tean': ['ante', 'aten', 'etna', 'nate', 'neat', 'taen', 'tane', 'tean'], + 'teanal': ['anteal', 'lanate', 'teanal'], + 'teap': ['pate', 'peat', 'tape', 'teap'], + 'teapot': ['aptote', 'optate', 'potate', 'teapot'], + 'tear': ['rate', 'tare', 'tear', 'tera'], + 'tearable': ['elabrate', 'tearable'], + 'tearably': ['betrayal', 'tearably'], + 'tearcat': ['caretta', 'teacart', 'tearcat'], + 'teardown': ['danewort', 'teardown'], + 'teardrop': ['predator', 'protrade', 'teardrop'], + 'tearer': ['rerate', 'retare', 'tearer'], + 'tearful': ['faulter', 'refutal', 'tearful'], + 'tearing': ['angrite', 'granite', 'ingrate', 'tangier', 'tearing', 'tigrean'], + 'tearless': ['rateless', 'tasseler', 'tearless', 'tesseral'], + 'tearlike': ['keralite', 'tearlike'], + 'tearpit': ['partite', 'tearpit'], + 'teart': ['atter', 'tater', 'teart', 'tetra', 'treat'], + 'teary': ['tayer', 'teary'], + 'teasably': ['stayable', 'teasably'], + 'tease': ['setae', 'tease'], + 'teasel': ['ateles', 'saltee', 'sealet', 'stelae', 'teasel'], + 'teaser': ['asteer', + 'easter', + 'eastre', + 'reseat', + 'saeter', + 'seater', + 'staree', + 'teaser', + 'teresa'], + 'teasing': ['easting', + 'gainset', + 'genista', + 'ingesta', + 'seating', + 'signate', + 'teasing'], + 'teasler': ['realest', 'reslate', 'resteal', 'stealer', 'teasler'], + 'teasy': ['teasy', 'yeast'], + 'teat': ['etta', 'tate', 'teat'], + 'teather': ['teather', 'theater', 'thereat'], + 'tebu': ['bute', 'tebu', 'tube'], + 'teca': ['cate', 'teca'], + 'tecali': ['calite', 'laetic', 'tecali'], + 'tech': ['chet', 'etch', 'tche', 'tech'], + 'techily': ['ethylic', 'techily'], + 'technica': ['atechnic', 'catechin', 'technica'], + 'technocracy': ['conycatcher', 'technocracy'], + 'technopsychology': ['psychotechnology', 'technopsychology'], + 'techous': ['souchet', 'techous', 'tousche'], + 'techy': ['techy', 'tyche'], + 'tecla': ['cleat', 'eclat', 'ectal', 'lacet', 'tecla'], + 'teco': ['cote', 'teco'], + 'tecoma': ['comate', 'metoac', 'tecoma'], + 'tecomin': ['centimo', 'entomic', 'tecomin'], + 'tecon': ['cento', 'conte', 'tecon'], + 'tectal': ['cattle', 'tectal'], + 'tectology': ['ctetology', 'tectology'], + 'tectona': ['oncetta', 'tectona'], + 'tectospinal': ['entoplastic', 'spinotectal', 'tectospinal', 'tenoplastic'], + 'tecuma': ['acetum', 'tecuma'], + 'tecuna': ['tecuna', 'uncate'], + 'teda': ['adet', 'date', 'tade', 'tead', 'teda'], + 'tedious': ['outside', 'tedious'], + 'tediousness': ['outsideness', 'tediousness'], + 'teedle': ['delete', 'teedle'], + 'teel': ['leet', 'lete', 'teel', 'tele'], + 'teem': ['meet', 'mete', 'teem'], + 'teemer': ['meeter', 'remeet', 'teemer'], + 'teeming': ['meeting', 'teeming', 'tegmine'], + 'teems': ['teems', 'temse'], + 'teen': ['neet', 'nete', 'teen'], + 'teens': ['steen', 'teens', 'tense'], + 'teer': ['reet', 'teer', 'tree'], + 'teerer': ['retree', 'teerer'], + 'teest': ['teest', 'teste'], + 'teet': ['teet', 'tete'], + 'teeter': ['teeter', 'terete'], + 'teeth': ['teeth', 'theet'], + 'teething': ['genthite', 'teething'], + 'teg': ['get', 'teg'], + 'tegean': ['geneat', 'negate', 'tegean'], + 'tegmina': ['mintage', 'teaming', 'tegmina'], + 'tegminal': ['ligament', 'metaling', 'tegminal'], + 'tegmine': ['meeting', 'teeming', 'tegmine'], + 'tegular': ['gaulter', 'tegular'], + 'teheran': ['earthen', 'enheart', 'hearten', 'naether', 'teheran', 'traheen'], + 'tehsildar': ['heraldist', 'tehsildar'], + 'teian': ['entia', 'teian', 'tenai', 'tinea'], + 'teicher': ['erethic', 'etheric', 'heretic', 'heteric', 'teicher'], + 'teil': ['lite', 'teil', 'teli', 'tile'], + 'teind': ['detin', 'teind', 'tined'], + 'teinder': ['nitered', 'redient', 'teinder'], + 'teinland': ['dentinal', 'teinland', 'tendinal'], + 'teioid': ['iodite', 'teioid'], + 'teju': ['jute', 'teju'], + 'telamon': ['omental', 'telamon'], + 'telang': ['tangle', 'telang'], + 'telar': ['alert', 'alter', 'artel', 'later', 'ratel', 'taler', 'telar'], + 'telarian': ['retainal', 'telarian'], + 'telary': ['lyrate', 'raylet', 'realty', 'telary'], + 'tele': ['leet', 'lete', 'teel', 'tele'], + 'telecast': ['castelet', 'telecast'], + 'telega': ['eaglet', 'legate', 'teagle', 'telega'], + 'telegn': ['gentle', 'telegn'], + 'telegrapher': ['retelegraph', 'telegrapher'], + 'telei': ['elite', 'telei'], + 'telephone': ['phenetole', 'telephone'], + 'telephony': ['polythene', 'telephony'], + 'telephotograph': ['phototelegraph', 'telephotograph'], + 'telephotographic': ['phototelegraphic', 'telephotographic'], + 'telephotography': ['phototelegraphy', 'telephotography'], + 'teleradiophone': ['radiotelephone', 'teleradiophone'], + 'teleran': ['alterne', 'enteral', 'eternal', 'teleran', 'teneral'], + 'teleseism': ['messelite', 'semisteel', 'teleseism'], + 'telespectroscope': ['spectrotelescope', 'telespectroscope'], + 'telestereoscope': ['stereotelescope', 'telestereoscope'], + 'telestial': ['satellite', 'telestial'], + 'telestic': ['telestic', 'testicle'], + 'telfer': ['felter', 'telfer', 'trefle'], + 'teli': ['lite', 'teil', 'teli', 'tile'], + 'telial': ['taille', 'telial'], + 'telic': ['clite', 'telic'], + 'telinga': ['atingle', 'gelatin', 'genital', 'langite', 'telinga'], + 'tellach': ['hellcat', 'tellach'], + 'teller': ['retell', 'teller'], + 'tellima': ['mitella', 'tellima'], + 'tellina': ['nitella', 'tellina'], + 'tellurian': ['tellurian', 'unliteral'], + 'telome': ['omelet', 'telome'], + 'telonism': ['melonist', 'telonism'], + 'telopsis': ['polistes', 'telopsis'], + 'telpath': ['pathlet', 'telpath'], + 'telson': ['solent', 'stolen', 'telson'], + 'telsonic': ['lentisco', 'telsonic'], + 'telt': ['lett', 'telt'], + 'tema': ['mate', 'meat', 'meta', 'tame', 'team', 'tema'], + 'teman': ['ament', 'meant', 'teman'], + 'temin': ['metin', 'temin', 'timne'], + 'temp': ['empt', 'temp'], + 'tempean': ['peteman', 'tempean'], + 'temper': ['temper', 'tempre'], + 'tempera': ['premate', 'tempera'], + 'temperer': ['retemper', 'temperer'], + 'temperish': ['herpetism', 'metership', 'metreship', 'temperish'], + 'templar': ['templar', 'trample'], + 'template': ['palmette', 'template'], + 'temple': ['pelmet', 'temple'], + 'tempora': ['pteroma', 'tempora'], + 'temporarily': ['polarimetry', 'premorality', 'temporarily'], + 'temporofrontal': ['frontotemporal', 'temporofrontal'], + 'temporooccipital': ['occipitotemporal', 'temporooccipital'], + 'temporoparietal': ['parietotemporal', 'temporoparietal'], + 'tempre': ['temper', 'tempre'], + 'tempter': ['retempt', 'tempter'], + 'temse': ['teems', 'temse'], + 'temser': ['mester', 'restem', 'temser', 'termes'], + 'temulent': ['temulent', 'unmettle'], + 'ten': ['net', 'ten'], + 'tenable': ['beltane', 'tenable'], + 'tenace': ['cetane', 'tenace'], + 'tenai': ['entia', 'teian', 'tenai', 'tinea'], + 'tenanter': ['retenant', 'tenanter'], + 'tenantless': ['latentness', 'tenantless'], + 'tencteri': ['reticent', 'tencteri'], + 'tend': ['dent', 'tend'], + 'tender': ['denter', 'rented', 'tender'], + 'tenderer': ['retender', 'tenderer'], + 'tenderish': ['disherent', 'hinderest', 'tenderish'], + 'tendinal': ['dentinal', 'teinland', 'tendinal'], + 'tendinitis': ['dentinitis', 'tendinitis'], + 'tendour': ['tendour', 'unroted'], + 'tendril': ['tendril', 'trindle'], + 'tendron': ['donnert', 'tendron'], + 'teneral': ['alterne', 'enteral', 'eternal', 'teleran', 'teneral'], + 'teneriffe': ['fifteener', 'teneriffe'], + 'tenesmus': ['muteness', 'tenesmus'], + 'teng': ['gent', 'teng'], + 'tengu': ['tengu', 'unget'], + 'teniacidal': ['acetanilid', 'laciniated', 'teniacidal'], + 'teniacide': ['deciatine', 'diacetine', 'taenicide', 'teniacide'], + 'tenible': ['beltine', 'tenible'], + 'tenino': ['intone', 'tenino'], + 'tenline': ['lenient', 'tenline'], + 'tenner': ['rennet', 'tenner'], + 'tennis': ['innest', 'sennit', 'sinnet', 'tennis'], + 'tenomyotomy': ['myotenotomy', 'tenomyotomy'], + 'tenon': ['nonet', 'tenon'], + 'tenoner': ['enteron', 'tenoner'], + 'tenonian': ['annotine', 'tenonian'], + 'tenonitis': ['sentition', 'tenonitis'], + 'tenontophyma': ['nematophyton', 'tenontophyma'], + 'tenophyte': ['entophyte', 'tenophyte'], + 'tenoplastic': ['entoplastic', 'spinotectal', 'tectospinal', 'tenoplastic'], + 'tenor': ['noter', 'tenor', 'toner', 'trone'], + 'tenorist': ['ortstein', 'tenorist'], + 'tenovaginitis': ['investigation', 'tenovaginitis'], + 'tenpin': ['pinnet', 'tenpin'], + 'tenrec': ['center', 'recent', 'tenrec'], + 'tense': ['steen', 'teens', 'tense'], + 'tensible': ['nebelist', 'stilbene', 'tensible'], + 'tensile': ['leisten', 'setline', 'tensile'], + 'tension': ['stenion', 'tension'], + 'tensional': ['alstonine', 'tensional'], + 'tensive': ['estevin', 'tensive'], + 'tenson': ['sonnet', 'stonen', 'tenson'], + 'tensor': ['nestor', 'sterno', 'stoner', 'strone', 'tensor'], + 'tentable': ['nettable', 'tentable'], + 'tentacle': ['ectental', 'tentacle'], + 'tentage': ['genetta', 'tentage'], + 'tentation': ['attention', 'tentation'], + 'tentative': ['attentive', 'tentative'], + 'tentatively': ['attentively', 'tentatively'], + 'tentativeness': ['attentiveness', 'tentativeness'], + 'tented': ['detent', 'netted', 'tented'], + 'tenter': ['netter', 'retent', 'tenter'], + 'tention': ['nettion', 'tention', 'tontine'], + 'tentorial': ['natrolite', 'tentorial'], + 'tenty': ['netty', 'tenty'], + 'tenuiroster': ['tenuiroster', 'urosternite'], + 'tenuistriate': ['intersituate', 'tenuistriate'], + 'tenure': ['neuter', 'retune', 'runtee', 'tenure', 'tureen'], + 'tenurial': ['lutrinae', 'retinula', 'rutelian', 'tenurial'], + 'teocalli': ['colletia', 'teocalli'], + 'teosinte': ['noisette', 'teosinte'], + 'tepache': ['heptace', 'tepache'], + 'tepal': ['leapt', + 'palet', + 'patel', + 'pelta', + 'petal', + 'plate', + 'pleat', + 'tepal'], + 'tepanec': ['pentace', 'tepanec'], + 'tepecano': ['conepate', 'tepecano'], + 'tephrite': ['perthite', 'tephrite'], + 'tephritic': ['perthitic', 'tephritic'], + 'tephroite': ['heptorite', 'tephroite'], + 'tephrosis': ['posterish', 'prothesis', 'sophister', 'storeship', 'tephrosis'], + 'tepor': ['poter', 'prote', 'repot', 'tepor', 'toper', 'trope'], + 'tequila': ['liquate', 'tequila'], + 'tera': ['rate', 'tare', 'tear', 'tera'], + 'teraglin': ['integral', 'teraglin', 'triangle'], + 'terap': ['apert', 'pater', 'peart', 'prate', 'taper', 'terap'], + 'teras': ['aster', 'serta', 'stare', 'strae', 'tarse', 'teras'], + 'teratism': ['mistreat', 'teratism'], + 'terbia': ['baiter', 'barite', 'rebait', 'terbia'], + 'terbium': ['burmite', 'imbrute', 'terbium'], + 'tercelet': ['electret', 'tercelet'], + 'terceron': ['corrente', 'terceron'], + 'tercia': ['acrite', 'arcite', 'tercia', 'triace', 'tricae'], + 'tercine': ['citrene', 'enteric', 'enticer', 'tercine'], + 'tercio': ['erotic', 'tercio'], + 'terebilic': ['celtiberi', 'terebilic'], + 'terebinthian': ['terebinthian', 'terebinthina'], + 'terebinthina': ['terebinthian', 'terebinthina'], + 'terebra': ['rebater', 'terebra'], + 'terebral': ['barrelet', 'terebral'], + 'terentian': ['entertain', 'tarentine', 'terentian'], + 'teresa': ['asteer', + 'easter', + 'eastre', + 'reseat', + 'saeter', + 'seater', + 'staree', + 'teaser', + 'teresa'], + 'teresian': ['arsenite', 'resinate', 'teresian', 'teresina'], + 'teresina': ['arsenite', 'resinate', 'teresian', 'teresina'], + 'terete': ['teeter', 'terete'], + 'teretial': ['laterite', 'literate', 'teretial'], + 'tereus': ['retuse', 'tereus'], + 'tergal': ['raglet', 'tergal'], + 'tergant': ['garnett', 'gnatter', 'gratten', 'tergant'], + 'tergeminous': ['mentigerous', 'tergeminous'], + 'teri': ['iter', 'reit', 'rite', 'teri', 'tier', 'tire'], + 'teriann': ['entrain', 'teriann'], + 'terma': ['armet', + 'mater', + 'merat', + 'metra', + 'ramet', + 'tamer', + 'terma', + 'trame', + 'trema'], + 'termagant': ['targetman', 'termagant'], + 'termes': ['mester', 'restem', 'temser', 'termes'], + 'termin': ['minter', 'remint', 'termin'], + 'terminal': ['terminal', 'tramline'], + 'terminalia': ['laminarite', 'terminalia'], + 'terminate': ['antimeter', 'attermine', 'interteam', 'terminate', 'tetramine'], + 'termini': ['interim', 'termini'], + 'terminine': ['intermine', 'nemertini', 'terminine'], + 'terminus': ['numerist', 'terminus'], + 'termital': ['remittal', 'termital'], + 'termite': ['emitter', 'termite'], + 'termly': ['myrtle', 'termly'], + 'termon': ['mentor', 'merton', 'termon', 'tormen'], + 'termor': ['termor', 'tremor'], + 'tern': ['rent', 'tern'], + 'terna': ['antre', 'arent', 'retan', 'terna'], + 'ternal': ['altern', 'antler', 'learnt', 'rental', 'ternal'], + 'ternar': ['arrent', 'errant', 'ranter', 'ternar'], + 'ternarious': ['souterrain', 'ternarious', 'trouserian'], + 'ternate': ['entreat', 'ratteen', 'tarente', 'ternate', 'tetrane'], + 'terne': ['enter', 'neter', 'renet', 'terne', 'treen'], + 'ternion': ['intoner', 'ternion'], + 'ternlet': ['nettler', 'ternlet'], + 'terp': ['pert', 'petr', 'terp'], + 'terpane': ['patener', 'pearten', 'petrean', 'terpane'], + 'terpeneless': ['repleteness', 'terpeneless'], + 'terpin': ['nipter', 'terpin'], + 'terpine': ['petrine', 'terpine'], + 'terpineol': ['interlope', 'interpole', 'repletion', 'terpineol'], + 'terpinol': ['pointrel', 'terpinol'], + 'terrace': ['caterer', 'recrate', 'retrace', 'terrace'], + 'terraciform': ['crateriform', 'terraciform'], + 'terrage': ['greater', 'regrate', 'terrage'], + 'terrain': ['arterin', 'retrain', 'terrain', 'trainer'], + 'terral': ['retral', 'terral'], + 'terrance': ['canterer', 'recanter', 'recreant', 'terrance'], + 'terrapin': ['pretrain', 'terrapin'], + 'terrar': ['tarrer', 'terrar'], + 'terrence': ['centerer', 'recenter', 'recentre', 'terrence'], + 'terrene': ['enterer', 'terrene'], + 'terret': ['retter', 'terret'], + 'terri': ['terri', 'tirer', 'trier'], + 'terrier': ['retirer', 'terrier'], + 'terrine': ['reinter', 'terrine'], + 'terron': ['terron', 'treron', 'troner'], + 'terry': ['retry', 'terry'], + 'terse': ['ester', + 'estre', + 'reest', + 'reset', + 'steer', + 'stere', + 'stree', + 'terse', + 'tsere'], + 'tersely': ['restyle', 'tersely'], + 'tersion': ['oestrin', 'tersion'], + 'tertia': ['attire', 'ratite', 'tertia'], + 'tertian': ['intreat', 'iterant', 'nitrate', 'tertian'], + 'tertiana': ['attainer', 'reattain', 'tertiana'], + 'terton': ['rotten', 'terton'], + 'tervee': ['revete', 'tervee'], + 'terzina': ['retzian', 'terzina'], + 'terzo': ['terzo', 'tozer'], + 'tesack': ['casket', 'tesack'], + 'teskere': ['skeeter', 'teskere'], + 'tessella': ['satelles', 'tessella'], + 'tesseral': ['rateless', 'tasseler', 'tearless', 'tesseral'], + 'test': ['sett', 'stet', 'test'], + 'testa': ['state', 'taste', 'tates', 'testa'], + 'testable': ['settable', 'testable'], + 'testament': ['statement', 'testament'], + 'testar': ['stater', 'taster', 'testar'], + 'teste': ['teest', 'teste'], + 'tested': ['detest', 'tested'], + 'testee': ['settee', 'testee'], + 'tester': ['retest', 'setter', 'street', 'tester'], + 'testes': ['sestet', 'testes', 'tsetse'], + 'testicle': ['telestic', 'testicle'], + 'testicular': ['testicular', 'trisulcate'], + 'testily': ['stylite', 'testily'], + 'testing': ['setting', 'testing'], + 'teston': ['ostent', 'teston'], + 'testor': ['sotter', 'testor'], + 'testril': ['litster', 'slitter', 'stilter', 'testril'], + 'testy': ['testy', 'tyste'], + 'tetanic': ['nictate', 'tetanic'], + 'tetanical': ['cantalite', 'lactinate', 'tetanical'], + 'tetanoid': ['antidote', 'tetanoid'], + 'tetanus': ['tetanus', 'unstate', 'untaste'], + 'tetarconid': ['detraction', 'doctrinate', 'tetarconid'], + 'tetard': ['tetard', 'tetrad'], + 'tetchy': ['chetty', 'tetchy'], + 'tete': ['teet', 'tete'], + 'tetel': ['ettle', 'tetel'], + 'tether': ['hetter', 'tether'], + 'tethys': ['stythe', 'tethys'], + 'tetra': ['atter', 'tater', 'teart', 'tetra', 'treat'], + 'tetracid': ['citrated', 'tetracid', 'tetradic'], + 'tetrad': ['tetard', 'tetrad'], + 'tetradic': ['citrated', 'tetracid', 'tetradic'], + 'tetragonia': ['giornatate', 'tetragonia'], + 'tetrahexahedron': ['hexatetrahedron', 'tetrahexahedron'], + 'tetrakishexahedron': ['hexakistetrahedron', 'tetrakishexahedron'], + 'tetralin': ['tetralin', 'triental'], + 'tetramin': ['intermat', 'martinet', 'tetramin'], + 'tetramine': ['antimeter', 'attermine', 'interteam', 'terminate', 'tetramine'], + 'tetrander': ['retardent', 'tetrander'], + 'tetrandrous': ['tetrandrous', 'unrostrated'], + 'tetrane': ['entreat', 'ratteen', 'tarente', 'ternate', 'tetrane'], + 'tetrao': ['rotate', 'tetrao'], + 'tetraodon': ['detonator', 'tetraodon'], + 'tetraonine': ['entoretina', 'tetraonine'], + 'tetraplous': ['supertotal', 'tetraplous'], + 'tetrasporic': ['tetrasporic', 'triceratops'], + 'tetraxonia': ['retaxation', 'tetraxonia'], + 'tetrical': ['tetrical', 'tractile'], + 'tetricous': ['tetricous', 'toreutics'], + 'tetronic': ['contrite', 'tetronic'], + 'tetrose': ['rosette', 'tetrose'], + 'tetterous': ['outstreet', 'tetterous'], + 'teucri': ['curite', 'teucri', 'uretic'], + 'teucrian': ['anuretic', 'centauri', 'centuria', 'teucrian'], + 'teucrin': ['nutrice', 'teucrin'], + 'teuk': ['ketu', 'teuk', 'tuke'], + 'tew': ['tew', 'wet'], + 'tewa': ['tewa', 'twae', 'weta'], + 'tewel': ['tewel', 'tweel'], + 'tewer': ['rewet', 'tewer', 'twere'], + 'tewit': ['tewit', 'twite'], + 'tewly': ['tewly', 'wetly'], + 'tha': ['aht', 'hat', 'tha'], + 'thai': ['hati', 'thai'], + 'thais': ['shita', 'thais'], + 'thalami': ['hamital', 'thalami'], + 'thaler': ['arthel', 'halter', 'lather', 'thaler'], + 'thalia': ['hiatal', 'thalia'], + 'thaliard': ['hardtail', 'thaliard'], + 'thamesis': ['mathesis', 'thamesis'], + 'than': ['hant', 'tanh', 'than'], + 'thana': ['atnah', 'tanha', 'thana'], + 'thanan': ['nathan', 'thanan'], + 'thanatism': ['staithman', 'thanatism'], + 'thanatotic': ['chattation', 'thanatotic'], + 'thane': ['enhat', 'ethan', 'nathe', 'neath', 'thane'], + 'thanker': ['rethank', 'thanker'], + 'thapes': ['spathe', 'thapes'], + 'thar': ['hart', 'rath', 'tahr', 'thar', 'trah'], + 'tharen': ['anther', 'nather', 'tharen', 'thenar'], + 'tharm': ['tharm', 'thram'], + 'thasian': ['ashanti', 'sanhita', 'shaitan', 'thasian'], + 'that': ['hatt', 'tath', 'that'], + 'thatcher': ['rethatch', 'thatcher'], + 'thaw': ['thaw', 'wath', 'what'], + 'thawer': ['rethaw', 'thawer', 'wreath'], + 'the': ['het', 'the'], + 'thea': ['ahet', 'haet', 'hate', 'heat', 'thea'], + 'theah': ['heath', 'theah'], + 'thearchy': ['hatchery', 'thearchy'], + 'theat': ['theat', 'theta'], + 'theater': ['teather', 'theater', 'thereat'], + 'theatricism': ['chemiatrist', 'chrismatite', 'theatricism'], + 'theatropolis': ['strophiolate', 'theatropolis'], + 'theatry': ['hattery', 'theatry'], + 'theb': ['beth', 'theb'], + 'thebaid': ['habited', 'thebaid'], + 'theca': ['cheat', 'tache', 'teach', 'theca'], + 'thecae': ['achete', 'hecate', 'teache', 'thecae'], + 'thecal': ['achtel', 'chalet', 'thecal', 'thecla'], + 'thecasporal': ['archapostle', 'thecasporal'], + 'thecata': ['attache', 'thecata'], + 'thecitis': ['ethicist', 'thecitis', 'theistic'], + 'thecla': ['achtel', 'chalet', 'thecal', 'thecla'], + 'theer': ['ether', 'rethe', 'theer', 'there', 'three'], + 'theet': ['teeth', 'theet'], + 'thegn': ['ghent', 'thegn'], + 'thegnly': ['lengthy', 'thegnly'], + 'theine': ['ethine', 'theine'], + 'their': ['ither', 'their'], + 'theirn': ['hinter', 'nither', 'theirn'], + 'theirs': ['shrite', 'theirs'], + 'theism': ['theism', 'themis'], + 'theist': ['theist', 'thetis'], + 'theistic': ['ethicist', 'thecitis', 'theistic'], + 'thema': ['ahmet', 'thema'], + 'thematic': ['mathetic', 'thematic'], + 'thematist': ['hattemist', 'thematist'], + 'themer': ['mether', 'themer'], + 'themis': ['theism', 'themis'], + 'themistian': ['antitheism', 'themistian'], + 'then': ['hent', 'neth', 'then'], + 'thenal': ['ethnal', 'hantle', 'lathen', 'thenal'], + 'thenar': ['anther', 'nather', 'tharen', 'thenar'], + 'theobald': ['bolthead', 'theobald'], + 'theocrasia': ['oireachtas', 'theocrasia'], + 'theocrat': ['theocrat', 'trochate'], + 'theocratic': ['rheotactic', 'theocratic'], + 'theodora': ['dorothea', 'theodora'], + 'theodore': ['theodore', 'treehood'], + 'theogonal': ['halogeton', 'theogonal'], + 'theologic': ['ethologic', 'theologic'], + 'theological': ['ethological', 'lethologica', 'theological'], + 'theologism': ['hemologist', 'theologism'], + 'theology': ['ethology', 'theology'], + 'theophanic': ['phaethonic', 'theophanic'], + 'theophilist': ['philotheist', 'theophilist'], + 'theopsychism': ['psychotheism', 'theopsychism'], + 'theorbo': ['boother', 'theorbo'], + 'theorematic': ['heteratomic', 'theorematic'], + 'theoretic': ['heterotic', 'theoretic'], + 'theoretician': ['heretication', 'theoretician'], + 'theorician': ['antiheroic', 'theorician'], + 'theorics': ['chirotes', 'theorics'], + 'theorism': ['homerist', 'isotherm', 'otherism', 'theorism'], + 'theorist': ['otherist', 'theorist'], + 'theorizer': ['rhetorize', 'theorizer'], + 'theorum': ['mouther', 'theorum'], + 'theotherapy': ['heteropathy', 'theotherapy'], + 'therblig': ['blighter', 'therblig'], + 'there': ['ether', 'rethe', 'theer', 'there', 'three'], + 'thereas': ['thereas', 'theresa'], + 'thereat': ['teather', 'theater', 'thereat'], + 'therein': ['enherit', 'etherin', 'neither', 'therein'], + 'thereness': ['retheness', 'thereness', 'threeness'], + 'thereology': ['heterology', 'thereology'], + 'theres': ['esther', 'hester', 'theres'], + 'theresa': ['thereas', 'theresa'], + 'therese': ['sheeter', 'therese'], + 'therewithal': ['therewithal', 'whitleather'], + 'theriac': ['certhia', 'rhaetic', 'theriac'], + 'therial': ['hairlet', 'therial'], + 'theriodic': ['dichroite', 'erichtoid', 'theriodic'], + 'theriodonta': ['dehortation', 'theriodonta'], + 'thermantic': ['intermatch', 'thermantic'], + 'thermo': ['mother', 'thermo'], + 'thermobarograph': ['barothermograph', 'thermobarograph'], + 'thermoelectric': ['electrothermic', 'thermoelectric'], + 'thermoelectrometer': ['electrothermometer', 'thermoelectrometer'], + 'thermogalvanometer': ['galvanothermometer', 'thermogalvanometer'], + 'thermogeny': ['mythogreen', 'thermogeny'], + 'thermography': ['mythographer', 'thermography'], + 'thermology': ['mythologer', 'thermology'], + 'thermos': ['smother', 'thermos'], + 'thermotype': ['phytometer', 'thermotype'], + 'thermotypic': ['phytometric', 'thermotypic'], + 'thermotypy': ['phytometry', 'thermotypy'], + 'theroid': ['rhodite', 'theroid'], + 'theron': ['hornet', 'nother', 'theron', 'throne'], + 'thersitical': ['thersitical', 'trachelitis'], + 'these': ['sheet', 'these'], + 'thesean': ['sneathe', 'thesean'], + 'thesial': ['heliast', 'thesial'], + 'thesis': ['shiest', 'thesis'], + 'theta': ['theat', 'theta'], + 'thetical': ['athletic', 'thetical'], + 'thetis': ['theist', 'thetis'], + 'thew': ['hewt', 'thew', 'whet'], + 'they': ['they', 'yeth'], + 'theyre': ['theyre', 'yether'], + 'thicken': ['kitchen', 'thicken'], + 'thickener': ['kitchener', 'rethicken', 'thickener'], + 'thicket': ['chettik', 'thicket'], + 'thienyl': ['ethylin', 'thienyl'], + 'thig': ['gith', 'thig'], + 'thigh': ['hight', 'thigh'], + 'thill': ['illth', 'thill'], + 'thin': ['hint', 'thin'], + 'thing': ['night', 'thing'], + 'thingal': ['halting', 'lathing', 'thingal'], + 'thingless': ['lightness', 'nightless', 'thingless'], + 'thinglet': ['thinglet', 'thlinget'], + 'thinglike': ['nightlike', 'thinglike'], + 'thingly': ['nightly', 'thingly'], + 'thingman': ['nightman', 'thingman'], + 'thinker': ['rethink', 'thinker'], + 'thio': ['hoit', 'hoti', 'thio'], + 'thiocresol': ['holosteric', 'thiocresol'], + 'thiol': ['litho', 'thiol', 'tholi'], + 'thiolacetic': ['heliotactic', 'thiolacetic'], + 'thiophenol': ['lithophone', 'thiophenol'], + 'thiopyran': ['phoniatry', 'thiopyran'], + 'thirlage': ['litharge', 'thirlage'], + 'this': ['hist', 'sith', 'this', 'tshi'], + 'thissen': ['sithens', 'thissen'], + 'thistle': ['lettish', 'thistle'], + 'thlinget': ['thinglet', 'thlinget'], + 'tho': ['hot', 'tho'], + 'thob': ['both', 'thob'], + 'thole': ['helot', 'hotel', 'thole'], + 'tholi': ['litho', 'thiol', 'tholi'], + 'tholos': ['soloth', 'tholos'], + 'thomaean': ['amaethon', 'thomaean'], + 'thomasine': ['hematosin', 'thomasine'], + 'thomisid': ['isthmoid', 'thomisid'], + 'thomsonite': ['monotheist', 'thomsonite'], + 'thonder': ['thonder', 'thorned'], + 'thonga': ['gnatho', 'thonga'], + 'thoo': ['hoot', 'thoo', 'toho'], + 'thoom': ['mooth', 'thoom'], + 'thoracectomy': ['chromatocyte', 'thoracectomy'], + 'thoracic': ['thoracic', 'tocharic', 'trochaic'], + 'thoral': ['harlot', 'orthal', 'thoral'], + 'thore': ['other', 'thore', 'throe', 'toher'], + 'thoric': ['chorti', 'orthic', 'thoric', 'trochi'], + 'thorina': ['orthian', 'thorina'], + 'thorite': ['hortite', 'orthite', 'thorite'], + 'thorn': ['north', 'thorn'], + 'thorned': ['thonder', 'thorned'], + 'thornhead': ['rhodanthe', 'thornhead'], + 'thorny': ['rhyton', 'thorny'], + 'thoro': ['ortho', 'thoro'], + 'thort': ['thort', 'troth'], + 'thos': ['host', 'shot', 'thos', 'tosh'], + 'those': ['ethos', 'shote', 'those'], + 'thowel': ['howlet', 'thowel'], + 'thraces': ['stacher', 'thraces'], + 'thracian': ['taranchi', 'thracian'], + 'thraep': ['thraep', 'threap'], + 'thrain': ['hartin', 'thrain'], + 'thram': ['tharm', 'thram'], + 'thrang': ['granth', 'thrang'], + 'thrasher': ['rethrash', 'thrasher'], + 'thrast': ['strath', 'thrast'], + 'thraw': ['thraw', 'warth', 'whart', 'wrath'], + 'thread': ['dearth', 'hatred', 'rathed', 'thread'], + 'threaden': ['adherent', 'headrent', 'neatherd', 'threaden'], + 'threader': ['rethread', 'threader'], + 'threadworm': ['motherward', 'threadworm'], + 'thready': ['hydrate', 'thready'], + 'threap': ['thraep', 'threap'], + 'threat': ['hatter', 'threat'], + 'threatener': ['rethreaten', 'threatener'], + 'three': ['ether', 'rethe', 'theer', 'there', 'three'], + 'threeling': ['lightener', 'relighten', 'threeling'], + 'threeness': ['retheness', 'thereness', 'threeness'], + 'threne': ['erthen', 'henter', 'nether', 'threne'], + 'threnode': ['dethrone', 'threnode'], + 'threnodic': ['chondrite', 'threnodic'], + 'threnos': ['shorten', 'threnos'], + 'thresher': ['rethresh', 'thresher'], + 'thrice': ['cither', 'thrice'], + 'thriller': ['rethrill', 'thriller'], + 'thripel': ['philter', 'thripel'], + 'thripidae': ['rhipidate', 'thripidae'], + 'throat': ['athort', 'throat'], + 'throb': ['broth', 'throb'], + 'throe': ['other', 'thore', 'throe', 'toher'], + 'thronal': ['althorn', 'anthrol', 'thronal'], + 'throne': ['hornet', 'nother', 'theron', 'throne'], + 'throu': ['routh', 'throu'], + 'throughout': ['outthrough', 'throughout'], + 'throw': ['throw', 'whort', 'worth', 'wroth'], + 'throwdown': ['downthrow', 'throwdown'], + 'thrower': ['rethrow', 'thrower'], + 'throwing': ['ingrowth', 'throwing'], + 'throwout': ['outthrow', 'outworth', 'throwout'], + 'thrum': ['thrum', 'thurm'], + 'thrust': ['struth', 'thrust'], + 'thruster': ['rethrust', 'thruster'], + 'thuan': ['ahunt', 'haunt', 'thuan', 'unhat'], + 'thulr': ['thulr', 'thurl'], + 'thunderbearing': ['thunderbearing', 'underbreathing'], + 'thunderer': ['rethunder', 'thunderer'], + 'thundering': ['thundering', 'underthing'], + 'thuoc': ['couth', 'thuoc', 'touch'], + 'thurl': ['thulr', 'thurl'], + 'thurm': ['thrum', 'thurm'], + 'thurse': ['reshut', 'suther', 'thurse', 'tusher'], + 'thurt': ['thurt', 'truth'], + 'thus': ['shut', 'thus', 'tush'], + 'thusness': ['shutness', 'thusness'], + 'thwacker': ['thwacker', 'whatreck'], + 'thwartover': ['overthwart', 'thwartover'], + 'thymelic': ['methylic', 'thymelic'], + 'thymetic': ['hymettic', 'thymetic'], + 'thymus': ['mythus', 'thymus'], + 'thyreogenous': ['heterogynous', 'thyreogenous'], + 'thyreohyoid': ['hyothyreoid', 'thyreohyoid'], + 'thyreoid': ['hydriote', 'thyreoid'], + 'thyreoidal': ['thyreoidal', 'thyroideal'], + 'thyreosis': ['oysterish', 'thyreosis'], + 'thyris': ['shirty', 'thyris'], + 'thyrocricoid': ['cricothyroid', 'thyrocricoid'], + 'thyrogenic': ['thyrogenic', 'trichogyne'], + 'thyrohyoid': ['hyothyroid', 'thyrohyoid'], + 'thyroideal': ['thyreoidal', 'thyroideal'], + 'thyroiodin': ['iodothyrin', 'thyroiodin'], + 'thyroprivic': ['thyroprivic', 'vitrophyric'], + 'thysanopteran': ['parasyntheton', 'thysanopteran'], + 'thysel': ['shelty', 'thysel'], + 'ti': ['it', 'ti'], + 'tiang': ['giant', 'tangi', 'tiang'], + 'tiao': ['iota', 'tiao'], + 'tiar': ['airt', 'rita', 'tari', 'tiar'], + 'tiara': ['arati', 'atria', 'riata', 'tarai', 'tiara'], + 'tiarella': ['arillate', 'tiarella'], + 'tib': ['bit', 'tib'], + 'tibetan': ['bettina', 'tabinet', 'tibetan'], + 'tibial': ['bilati', 'tibial'], + 'tibiale': ['biliate', 'tibiale'], + 'tibiofemoral': ['femorotibial', 'tibiofemoral'], + 'tic': ['cit', 'tic'], + 'ticca': ['cacti', 'ticca'], + 'tice': ['ceti', 'cite', 'tice'], + 'ticer': ['citer', 'recti', 'ticer', 'trice'], + 'tichodroma': ['chromatoid', 'tichodroma'], + 'ticketer': ['reticket', 'ticketer'], + 'tickler': ['tickler', 'trickle'], + 'tickproof': ['prickfoot', 'tickproof'], + 'ticuna': ['anicut', 'nautic', 'ticuna', 'tunica'], + 'ticunan': ['ticunan', 'tunican'], + 'tid': ['dit', 'tid'], + 'tidal': ['datil', 'dital', 'tidal', 'tilda'], + 'tiddley': ['lyddite', 'tiddley'], + 'tide': ['diet', 'dite', 'edit', 'tide', 'tied'], + 'tidely': ['idlety', 'lydite', 'tidely', 'tidley'], + 'tiding': ['tiding', 'tingid'], + 'tidley': ['idlety', 'lydite', 'tidely', 'tidley'], + 'tied': ['diet', 'dite', 'edit', 'tide', 'tied'], + 'tien': ['iten', 'neti', 'tien', 'tine'], + 'tiepin': ['pinite', 'tiepin'], + 'tier': ['iter', 'reit', 'rite', 'teri', 'tier', 'tire'], + 'tierce': ['cerite', 'certie', 'recite', 'tierce'], + 'tiered': ['dieter', 'tiered'], + 'tierer': ['errite', 'reiter', 'retier', 'retire', 'tierer'], + 'tiffy': ['fifty', 'tiffy'], + 'tifter': ['fitter', 'tifter'], + 'tig': ['git', 'tig'], + 'tigella': ['tigella', 'tillage'], + 'tiger': ['tiger', 'tigre'], + 'tigereye': ['geyerite', 'tigereye'], + 'tightener': ['retighten', 'tightener'], + 'tiglinic': ['lignitic', 'tiglinic'], + 'tigre': ['tiger', 'tigre'], + 'tigrean': ['angrite', 'granite', 'ingrate', 'tangier', 'tearing', 'tigrean'], + 'tigress': ['striges', 'tigress'], + 'tigrine': ['igniter', 'ringite', 'tigrine'], + 'tigurine': ['intrigue', 'tigurine'], + 'tikka': ['katik', 'tikka'], + 'tikur': ['tikur', 'turki'], + 'til': ['lit', 'til'], + 'tilaite': ['italite', 'letitia', 'tilaite'], + 'tilda': ['datil', 'dital', 'tidal', 'tilda'], + 'tilde': ['tilde', 'tiled'], + 'tile': ['lite', 'teil', 'teli', 'tile'], + 'tiled': ['tilde', 'tiled'], + 'tiler': ['liter', 'tiler'], + 'tilery': ['tilery', 'tilyer'], + 'tileways': ['sweatily', 'tileways'], + 'tileyard': ['dielytra', 'tileyard'], + 'tilia': ['itali', 'tilia'], + 'tilikum': ['kulimit', 'tilikum'], + 'till': ['lilt', 'till'], + 'tillable': ['belltail', 'bletilla', 'tillable'], + 'tillaea': ['alalite', 'tillaea'], + 'tillage': ['tigella', 'tillage'], + 'tiller': ['retill', 'rillet', 'tiller'], + 'tilmus': ['litmus', 'tilmus'], + 'tilpah': ['lapith', 'tilpah'], + 'tilter': ['litter', 'tilter', 'titler'], + 'tilting': ['tilting', 'titling', 'tlingit'], + 'tiltup': ['tiltup', 'uptilt'], + 'tilyer': ['tilery', 'tilyer'], + 'timable': ['limbate', 'timable', 'timbale'], + 'timaeus': ['metusia', 'suimate', 'timaeus'], + 'timaline': ['meliatin', 'timaline'], + 'timani': ['intima', 'timani'], + 'timar': ['mitra', 'tarmi', 'timar', 'tirma'], + 'timbal': ['limbat', 'timbal'], + 'timbale': ['limbate', 'timable', 'timbale'], + 'timber': ['betrim', 'timber', 'timbre'], + 'timbered': ['bemitred', 'timbered'], + 'timberer': ['retimber', 'timberer'], + 'timberlike': ['kimberlite', 'timberlike'], + 'timbre': ['betrim', 'timber', 'timbre'], + 'time': ['emit', 'item', 'mite', 'time'], + 'timecard': ['dermatic', 'timecard'], + 'timed': ['demit', 'timed'], + 'timeproof': ['miteproof', 'timeproof'], + 'timer': ['merit', 'miter', 'mitre', 'remit', 'timer'], + 'times': ['metis', 'smite', 'stime', 'times'], + 'timesaving': ['negativism', 'timesaving'], + 'timework': ['timework', 'worktime'], + 'timid': ['dimit', 'timid'], + 'timidly': ['mytilid', 'timidly'], + 'timidness': ['destinism', 'timidness'], + 'timish': ['isthmi', 'timish'], + 'timne': ['metin', 'temin', 'timne'], + 'timo': ['itmo', 'moit', 'omit', 'timo'], + 'timon': ['minot', 'timon', 'tomin'], + 'timorese': ['rosetime', 'timorese', 'tiresome'], + 'timpani': ['impaint', 'timpani'], + 'timpano': ['maintop', 'ptomain', 'tampion', 'timpano'], + 'tin': ['nit', 'tin'], + 'tina': ['aint', 'anti', 'tain', 'tina'], + 'tincal': ['catlin', 'tincal'], + 'tinchel': ['linchet', 'tinchel'], + 'tinctorial': ['tinctorial', 'trinoctial'], + 'tind': ['dint', 'tind'], + 'tindal': ['antlid', 'tindal'], + 'tindalo': ['itoland', 'talonid', 'tindalo'], + 'tinder': ['dirten', 'rident', 'tinder'], + 'tindered': ['dendrite', 'tindered'], + 'tinderous': ['detrusion', 'tinderous', 'unstoried'], + 'tine': ['iten', 'neti', 'tien', 'tine'], + 'tinea': ['entia', 'teian', 'tenai', 'tinea'], + 'tineal': ['entail', 'tineal'], + 'tinean': ['annite', 'innate', 'tinean'], + 'tined': ['detin', 'teind', 'tined'], + 'tineid': ['indite', 'tineid'], + 'tineman': ['mannite', 'tineman'], + 'tineoid': ['edition', 'odinite', 'otidine', 'tineoid'], + 'tinetare': ['intereat', 'tinetare'], + 'tinety': ['entity', 'tinety'], + 'tinged': ['nidget', 'tinged'], + 'tinger': ['engirt', 'tinger'], + 'tingid': ['tiding', 'tingid'], + 'tingitidae': ['indigitate', 'tingitidae'], + 'tingler': ['ringlet', 'tingler', 'tringle'], + 'tinhouse': ['outshine', 'tinhouse'], + 'tink': ['knit', 'tink'], + 'tinker': ['reknit', 'tinker'], + 'tinkerer': ['retinker', 'tinkerer'], + 'tinkler': ['tinkler', 'trinkle'], + 'tinlet': ['litten', 'tinlet'], + 'tinne': ['innet', 'tinne'], + 'tinned': ['dentin', 'indent', 'intend', 'tinned'], + 'tinner': ['intern', 'tinner'], + 'tinnet': ['intent', 'tinnet'], + 'tino': ['into', 'nito', 'oint', 'tino'], + 'tinoceras': ['atroscine', 'certosina', 'ostracine', 'tinoceras', 'tricosane'], + 'tinosa': ['sotnia', 'tinosa'], + 'tinsel': ['enlist', 'listen', 'silent', 'tinsel'], + 'tinselly': ['silently', 'tinselly'], + 'tinta': ['taint', 'tanti', 'tinta', 'titan'], + 'tintage': ['attinge', 'tintage'], + 'tinter': ['nitter', 'tinter'], + 'tintie': ['tintie', 'titien'], + 'tintiness': ['insistent', 'tintiness'], + 'tinty': ['nitty', 'tinty'], + 'tinworker': ['interwork', 'tinworker'], + 'tionontates': ['ostentation', 'tionontates'], + 'tip': ['pit', 'tip'], + 'tipe': ['piet', 'tipe'], + 'tipful': ['tipful', 'uplift'], + 'tipless': ['pitless', 'tipless'], + 'tipman': ['pitman', 'tampin', 'tipman'], + 'tipper': ['rippet', 'tipper'], + 'tippler': ['ripplet', 'tippler', 'tripple'], + 'tipster': ['spitter', 'tipster'], + 'tipstock': ['potstick', 'tipstock'], + 'tipula': ['tipula', 'tulipa'], + 'tiralee': ['atelier', 'tiralee'], + 'tire': ['iter', 'reit', 'rite', 'teri', 'tier', 'tire'], + 'tired': ['diter', 'tired', 'tried'], + 'tiredly': ['tiredly', 'triedly'], + 'tiredness': ['dissenter', 'tiredness'], + 'tireless': ['riteless', 'tireless'], + 'tirelessness': ['ritelessness', 'tirelessness'], + 'tiremaid': ['dimetria', 'mitridae', 'tiremaid', 'triamide'], + 'tireman': ['minaret', 'raiment', 'tireman'], + 'tirer': ['terri', 'tirer', 'trier'], + 'tiresmith': ['tiresmith', 'tritheism'], + 'tiresome': ['rosetime', 'timorese', 'tiresome'], + 'tirma': ['mitra', 'tarmi', 'timar', 'tirma'], + 'tirolean': ['oriental', 'relation', 'tirolean'], + 'tirolese': ['literose', 'roselite', 'tirolese'], + 'tirve': ['rivet', 'tirve', 'tiver'], + 'tisane': ['satine', 'tisane'], + 'tisar': ['arist', + 'astir', + 'sitar', + 'stair', + 'stria', + 'tarsi', + 'tisar', + 'trias'], + 'titan': ['taint', 'tanti', 'tinta', 'titan'], + 'titaness': ['antistes', 'titaness'], + 'titanic': ['tanitic', 'titanic'], + 'titano': ['otiant', 'titano'], + 'titanocolumbate': ['columbotitanate', 'titanocolumbate'], + 'titanofluoride': ['rotundifoliate', 'titanofluoride'], + 'titanosaur': ['saturation', 'titanosaur'], + 'titanosilicate': ['silicotitanate', 'titanosilicate'], + 'titanous': ['outsaint', 'titanous'], + 'titanyl': ['nattily', 'titanyl'], + 'titar': ['ratti', 'titar', 'trait'], + 'titer': ['titer', 'titre', 'trite'], + 'tithable': ['hittable', 'tithable'], + 'tither': ['hitter', 'tither'], + 'tithonic': ['chinotti', 'tithonic'], + 'titien': ['tintie', 'titien'], + 'titleboard': ['titleboard', 'trilobated'], + 'titler': ['litter', 'tilter', 'titler'], + 'titling': ['tilting', 'titling', 'tlingit'], + 'titrate': ['attrite', 'titrate'], + 'titration': ['attrition', 'titration'], + 'titre': ['titer', 'titre', 'trite'], + 'tiver': ['rivet', 'tirve', 'tiver'], + 'tiza': ['itza', 'tiza', 'zati'], + 'tlaco': ['lacto', 'tlaco'], + 'tlingit': ['tilting', 'titling', 'tlingit'], + 'tmesis': ['misset', 'tmesis'], + 'toa': ['oat', 'tao', 'toa'], + 'toad': ['doat', 'toad', 'toda'], + 'toader': ['doater', 'toader'], + 'toadflower': ['floodwater', 'toadflower', 'waterflood'], + 'toadier': ['roadite', 'toadier'], + 'toadish': ['doatish', 'toadish'], + 'toady': ['toady', 'today'], + 'toadyish': ['toadyish', 'todayish'], + 'toag': ['goat', 'toag', 'toga'], + 'toast': ['stoat', 'toast'], + 'toaster': ['retoast', 'rosetta', 'stoater', 'toaster'], + 'toba': ['boat', 'bota', 'toba'], + 'tobe': ['bote', 'tobe'], + 'tobiah': ['bhotia', 'tobiah'], + 'tobine': ['botein', 'tobine'], + 'toccata': ['attacco', 'toccata'], + 'tocharese': ['escheator', 'tocharese'], + 'tocharian': ['archontia', 'tocharian'], + 'tocharic': ['thoracic', 'tocharic', 'trochaic'], + 'tocher': ['hector', 'rochet', 'tocher', 'troche'], + 'toco': ['coot', 'coto', 'toco'], + 'tocogenetic': ['geotectonic', 'tocogenetic'], + 'tocometer': ['octometer', 'rectotome', 'tocometer'], + 'tocsin': ['nostic', 'sintoc', 'tocsin'], + 'tod': ['dot', 'tod'], + 'toda': ['doat', 'toad', 'toda'], + 'today': ['toady', 'today'], + 'todayish': ['toadyish', 'todayish'], + 'toddle': ['dodlet', 'toddle'], + 'tode': ['dote', 'tode', 'toed'], + 'todea': ['deota', 'todea'], + 'tody': ['doty', 'tody'], + 'toecap': ['capote', 'toecap'], + 'toed': ['dote', 'tode', 'toed'], + 'toeless': ['osselet', 'sestole', 'toeless'], + 'toenail': ['alnoite', 'elation', 'toenail'], + 'tog': ['got', 'tog'], + 'toga': ['goat', 'toag', 'toga'], + 'togaed': ['dogate', 'dotage', 'togaed'], + 'togalike': ['goatlike', 'togalike'], + 'toggel': ['goglet', 'toggel', 'toggle'], + 'toggle': ['goglet', 'toggel', 'toggle'], + 'togs': ['stog', 'togs'], + 'toher': ['other', 'thore', 'throe', 'toher'], + 'toho': ['hoot', 'thoo', 'toho'], + 'tohunga': ['hangout', 'tohunga'], + 'toi': ['ito', 'toi'], + 'toil': ['ilot', 'toil'], + 'toiler': ['loiter', 'toiler', 'triole'], + 'toilet': ['lottie', 'toilet', 'tolite'], + 'toiletry': ['toiletry', 'tyrolite'], + 'toise': ['sotie', 'toise'], + 'tokay': ['otyak', 'tokay'], + 'toke': ['keto', 'oket', 'toke'], + 'toko': ['koto', 'toko', 'took'], + 'tol': ['lot', 'tol'], + 'tolamine': ['lomatine', 'tolamine'], + 'tolan': ['notal', 'ontal', 'talon', 'tolan', 'tonal'], + 'tolane': ['etalon', 'tolane'], + 'told': ['dolt', 'told'], + 'tole': ['leto', 'lote', 'tole'], + 'toledan': ['taloned', 'toledan'], + 'toledo': ['toledo', 'toodle'], + 'tolerance': ['antrocele', 'coeternal', 'tolerance'], + 'tolerancy': ['alectryon', 'tolerancy'], + 'tolidine': ['lindoite', 'tolidine'], + 'tolite': ['lottie', 'toilet', 'tolite'], + 'tollery': ['tollery', 'trolley'], + 'tolly': ['tolly', 'tolyl'], + 'tolpatch': ['potlatch', 'tolpatch'], + 'tolsey': ['tolsey', 'tylose'], + 'tolter': ['lotter', 'rottle', 'tolter'], + 'tolu': ['lout', 'tolu'], + 'toluic': ['coutil', 'toluic'], + 'toluifera': ['foliature', 'toluifera'], + 'tolyl': ['tolly', 'tolyl'], + 'tom': ['mot', 'tom'], + 'toma': ['atmo', 'atom', 'moat', 'toma'], + 'toman': ['manto', 'toman'], + 'tomas': ['atmos', 'stoma', 'tomas'], + 'tombac': ['combat', 'tombac'], + 'tome': ['mote', 'tome'], + 'tomentose': ['metosteon', 'tomentose'], + 'tomial': ['lomita', 'tomial'], + 'tomin': ['minot', 'timon', 'tomin'], + 'tomographic': ['motographic', 'tomographic'], + 'tomorn': ['morton', 'tomorn'], + 'tomorrow': ['moorwort', 'rootworm', 'tomorrow', 'wormroot'], + 'ton': ['not', 'ton'], + 'tonal': ['notal', 'ontal', 'talon', 'tolan', 'tonal'], + 'tonalitive': ['levitation', 'tonalitive', 'velitation'], + 'tonation': ['notation', 'tonation'], + 'tone': ['note', 'tone'], + 'toned': ['donet', 'noted', 'toned'], + 'toneless': ['noteless', 'toneless'], + 'tonelessly': ['notelessly', 'tonelessly'], + 'tonelessness': ['notelessness', 'tonelessness'], + 'toner': ['noter', 'tenor', 'toner', 'trone'], + 'tonetic': ['entotic', 'tonetic'], + 'tonetics': ['stenotic', 'tonetics'], + 'tonga': ['tango', 'tonga'], + 'tongan': ['ganton', 'tongan'], + 'tongas': ['sontag', 'tongas'], + 'tonger': ['geront', 'tonger'], + 'tongrian': ['ignorant', 'tongrian'], + 'tongs': ['stong', 'tongs'], + 'tonicize': ['nicotize', 'tonicize'], + 'tonicoclonic': ['clonicotonic', 'tonicoclonic'], + 'tonify': ['notify', 'tonify'], + 'tonish': ['histon', 'shinto', 'tonish'], + 'tonk': ['knot', 'tonk'], + 'tonkin': ['inknot', 'tonkin'], + 'tonna': ['anton', 'notan', 'tonna'], + 'tonological': ['ontological', 'tonological'], + 'tonology': ['ontology', 'tonology'], + 'tonsorial': ['tonsorial', 'torsional'], + 'tonsure': ['snouter', 'tonsure', 'unstore'], + 'tonsured': ['tonsured', 'unsorted', 'unstored'], + 'tontine': ['nettion', 'tention', 'tontine'], + 'tonus': ['notus', 'snout', 'stoun', 'tonus'], + 'tony': ['tony', 'yont'], + 'too': ['oto', 'too'], + 'toodle': ['toledo', 'toodle'], + 'took': ['koto', 'toko', 'took'], + 'tool': ['loot', 'tool'], + 'tooler': ['looter', 'retool', 'rootle', 'tooler'], + 'tooling': ['ilongot', 'tooling'], + 'toom': ['moot', 'toom'], + 'toon': ['onto', 'oont', 'toon'], + 'toona': ['naoto', 'toona'], + 'toop': ['poot', 'toop', 'topo'], + 'toosh': ['shoot', 'sooth', 'sotho', 'toosh'], + 'toot': ['otto', 'toot', 'toto'], + 'toother': ['retooth', 'toother'], + 'toothpick': ['picktooth', 'toothpick'], + 'tootler': ['rootlet', 'tootler'], + 'top': ['opt', 'pot', 'top'], + 'toparch': ['caphtor', 'toparch'], + 'topass': ['potass', 'topass'], + 'topchrome': ['ectomorph', 'topchrome'], + 'tope': ['peto', 'poet', 'pote', 'tope'], + 'toper': ['poter', 'prote', 'repot', 'tepor', 'toper', 'trope'], + 'topfull': ['plotful', 'topfull'], + 'toph': ['phot', 'toph'], + 'tophus': ['tophus', 'upshot'], + 'topia': ['patio', 'taipo', 'topia'], + 'topiarist': ['parotitis', 'topiarist'], + 'topic': ['optic', 'picot', 'topic'], + 'topical': ['capitol', 'coalpit', 'optical', 'topical'], + 'topically': ['optically', 'topically'], + 'toplike': ['kitlope', 'potlike', 'toplike'], + 'topline': ['pointel', 'pontile', 'topline'], + 'topmaker': ['potmaker', 'topmaker'], + 'topmaking': ['potmaking', 'topmaking'], + 'topman': ['potman', 'tampon', 'topman'], + 'topmast': ['tapmost', 'topmast'], + 'topo': ['poot', 'toop', 'topo'], + 'topographics': ['coprophagist', 'topographics'], + 'topography': ['optography', 'topography'], + 'topological': ['optological', 'topological'], + 'topologist': ['optologist', 'topologist'], + 'topology': ['optology', 'topology'], + 'toponymal': ['monotypal', 'toponymal'], + 'toponymic': ['monotypic', 'toponymic'], + 'toponymical': ['monotypical', 'toponymical'], + 'topophone': ['optophone', 'topophone'], + 'topotype': ['optotype', 'topotype'], + 'topple': ['loppet', 'topple'], + 'toppler': ['preplot', 'toppler'], + 'toprail': ['portail', 'toprail'], + 'tops': ['post', 'spot', 'stop', 'tops'], + 'topsail': ['apostil', 'topsail'], + 'topside': ['deposit', 'topside'], + 'topsman': ['postman', 'topsman'], + 'topsoil': ['loopist', 'poloist', 'topsoil'], + 'topstone': ['potstone', 'topstone'], + 'toptail': ['ptilota', 'talipot', 'toptail'], + 'toque': ['quote', 'toque'], + 'tor': ['ort', 'rot', 'tor'], + 'tora': ['rota', 'taro', 'tora'], + 'toral': ['latro', 'rotal', 'toral'], + 'toran': ['orant', 'rotan', 'toran', 'trona'], + 'torbanite': ['abortient', 'torbanite'], + 'torcel': ['colter', 'lector', 'torcel'], + 'torch': ['chort', 'rotch', 'torch'], + 'tore': ['rote', 'tore'], + 'tored': ['doter', 'tored', 'trode'], + 'torenia': ['otarine', 'torenia'], + 'torero': ['reroot', 'rooter', 'torero'], + 'toreutics': ['tetricous', 'toreutics'], + 'torfel': ['floret', 'forlet', 'lofter', 'torfel'], + 'torgot': ['grotto', 'torgot'], + 'toric': ['toric', 'troic'], + 'torinese': ['serotine', 'torinese'], + 'torma': ['amort', 'morat', 'torma'], + 'tormen': ['mentor', 'merton', 'termon', 'tormen'], + 'tormina': ['amintor', 'tormina'], + 'torn': ['torn', 'tron'], + 'tornachile': ['chlorinate', 'ectorhinal', 'tornachile'], + 'tornado': ['donator', 'odorant', 'tornado'], + 'tornal': ['latron', 'lontar', 'tornal'], + 'tornaria': ['rotarian', 'tornaria'], + 'tornarian': ['narration', 'tornarian'], + 'tornese': ['enstore', 'estrone', 'storeen', 'tornese'], + 'torney': ['torney', 'tyrone'], + 'tornit': ['intort', 'tornit', 'triton'], + 'tornus': ['tornus', 'unsort'], + 'toro': ['root', 'roto', 'toro'], + 'torose': ['seroot', 'sooter', 'torose'], + 'torpent': ['portent', 'torpent'], + 'torpescent': ['precontest', 'torpescent'], + 'torpid': ['torpid', 'tripod'], + 'torpify': ['portify', 'torpify'], + 'torpor': ['portor', 'torpor'], + 'torque': ['quoter', 'roquet', 'torque'], + 'torques': ['questor', 'torques'], + 'torrubia': ['rubiator', 'torrubia'], + 'torsade': ['rosated', 'torsade'], + 'torse': ['roset', 'rotse', 'soter', 'stero', 'store', 'torse'], + 'torsel': ['relost', 'reslot', 'rostel', 'sterol', 'torsel'], + 'torsile': ['estriol', 'torsile'], + 'torsion': ['isotron', 'torsion'], + 'torsional': ['tonsorial', 'torsional'], + 'torsk': ['stork', 'torsk'], + 'torso': ['roost', 'torso'], + 'torsten': ['snotter', 'stentor', 'torsten'], + 'tort': ['tort', 'trot'], + 'torta': ['ottar', 'tarot', 'torta', 'troat'], + 'torteau': ['outrate', 'outtear', 'torteau'], + 'torticone': ['torticone', 'tritocone'], + 'tortile': ['lotrite', 'tortile', 'triolet'], + 'tortilla': ['littoral', 'tortilla'], + 'tortonian': ['intonator', 'tortonian'], + 'tortrices': ['tortrices', 'trisector'], + 'torture': ['torture', 'trouter', 'tutorer'], + 'toru': ['rout', 'toru', 'tour'], + 'torula': ['rotula', 'torula'], + 'torulaform': ['formulator', 'torulaform'], + 'toruliform': ['rotuliform', 'toruliform'], + 'torulose': ['outsoler', 'torulose'], + 'torulus': ['rotulus', 'torulus'], + 'torus': ['roust', 'rusot', 'stour', 'sutor', 'torus'], + 'torve': ['overt', 'rovet', 'torve', 'trove', 'voter'], + 'tory': ['royt', 'ryot', 'tory', 'troy', 'tyro'], + 'toryish': ['history', 'toryish'], + 'toryism': ['toryism', 'trisomy'], + 'tosephtas': ['posthaste', 'tosephtas'], + 'tosh': ['host', 'shot', 'thos', 'tosh'], + 'tosher': ['hoster', 'tosher'], + 'toshly': ['hostly', 'toshly'], + 'toshnail': ['histonal', 'toshnail'], + 'toss': ['sots', 'toss'], + 'tosser': ['retoss', 'tosser'], + 'tossily': ['tossily', 'tylosis'], + 'tossup': ['tossup', 'uptoss'], + 'tost': ['stot', 'tost'], + 'total': ['lotta', 'total'], + 'totanine': ['intonate', 'totanine'], + 'totaquin': ['quintato', 'totaquin'], + 'totchka': ['hattock', 'totchka'], + 'totem': ['motet', 'motte', 'totem'], + 'toter': ['ortet', 'otter', 'toter'], + 'tother': ['hotter', 'tother'], + 'toto': ['otto', 'toot', 'toto'], + 'toty': ['toty', 'tyto'], + 'tou': ['out', 'tou'], + 'toucan': ['toucan', 'tucano', 'uncoat'], + 'touch': ['couth', 'thuoc', 'touch'], + 'toucher': ['retouch', 'toucher'], + 'touchily': ['couthily', 'touchily'], + 'touchiness': ['couthiness', 'touchiness'], + 'touching': ['touching', 'ungothic'], + 'touchless': ['couthless', 'touchless'], + 'toug': ['gout', 'toug'], + 'tough': ['ought', 'tough'], + 'toughness': ['oughtness', 'toughness'], + 'toup': ['pout', 'toup'], + 'tour': ['rout', 'toru', 'tour'], + 'tourer': ['retour', 'router', 'tourer'], + 'touring': ['outgrin', 'outring', 'routing', 'touring'], + 'tourism': ['sumitro', 'tourism'], + 'touristy': ['touristy', 'yttrious'], + 'tourmalinic': ['latrocinium', 'tourmalinic'], + 'tournamental': ['tournamental', 'ultramontane'], + 'tourte': ['tourte', 'touter'], + 'tousche': ['souchet', 'techous', 'tousche'], + 'touser': ['ouster', 'souter', 'touser', 'trouse'], + 'tousle': ['lutose', 'solute', 'tousle'], + 'touter': ['tourte', 'touter'], + 'tovaria': ['aviator', 'tovaria'], + 'tow': ['tow', 'two', 'wot'], + 'towel': ['owlet', 'towel'], + 'tower': ['rowet', 'tower', 'wrote'], + 'town': ['nowt', 'town', 'wont'], + 'towned': ['towned', 'wonted'], + 'towser': ['restow', 'stower', 'towser', 'worset'], + 'towy': ['towy', 'yowt'], + 'toxemia': ['oximate', 'toxemia'], + 'toy': ['toy', 'yot'], + 'toyer': ['royet', 'toyer'], + 'toyful': ['outfly', 'toyful'], + 'toyless': ['systole', 'toyless'], + 'toysome': ['myosote', 'toysome'], + 'tozer': ['terzo', 'tozer'], + 'tra': ['art', 'rat', 'tar', 'tra'], + 'trabea': ['abater', 'artabe', 'eartab', 'trabea'], + 'trace': ['caret', + 'carte', + 'cater', + 'crate', + 'creat', + 'creta', + 'react', + 'recta', + 'trace'], + 'traceable': ['creatable', 'traceable'], + 'tracer': ['arrect', 'carter', 'crater', 'recart', 'tracer'], + 'tracheata': ['cathartae', 'tracheata'], + 'trachelitis': ['thersitical', 'trachelitis'], + 'tracheolaryngotomy': ['laryngotracheotomy', 'tracheolaryngotomy'], + 'trachinoid': ['anhidrotic', 'trachinoid'], + 'trachitis': ['citharist', 'trachitis'], + 'trachle': ['clethra', 'latcher', 'ratchel', 'relatch', 'talcher', 'trachle'], + 'trachoma': ['achromat', 'trachoma'], + 'trachylinae': ['chatelainry', 'trachylinae'], + 'trachyte': ['chattery', 'ratchety', 'trachyte'], + 'tracker': ['retrack', 'tracker'], + 'trackside': ['sidetrack', 'trackside'], + 'tractator': ['attractor', 'tractator'], + 'tractile': ['tetrical', 'tractile'], + 'tracy': ['carty', 'tracy'], + 'trade': ['dater', 'derat', 'detar', 'drate', 'rated', 'trade', 'tread'], + 'trader': ['darter', + 'dartre', + 'redart', + 'retard', + 'retrad', + 'tarred', + 'trader'], + 'trading': ['darting', 'trading'], + 'tradite': ['attired', 'tradite'], + 'traditioner': ['retradition', 'traditioner'], + 'traditionism': ['mistradition', 'traditionism'], + 'traditorship': ['podarthritis', 'traditorship'], + 'traducent': ['reductant', 'traducent', 'truncated'], + 'trady': ['tardy', 'trady'], + 'trag': ['grat', 'trag'], + 'tragedial': ['taligrade', 'tragedial'], + 'tragicomedy': ['comitragedy', 'tragicomedy'], + 'tragulina': ['tragulina', 'triangula'], + 'traguline': ['granulite', 'traguline'], + 'trah': ['hart', 'rath', 'tahr', 'thar', 'trah'], + 'traheen': ['earthen', 'enheart', 'hearten', 'naether', 'teheran', 'traheen'], + 'traik': ['kitar', 'krait', 'rakit', 'traik'], + 'trail': ['litra', 'trail', 'trial'], + 'trailer': ['retiral', 'retrial', 'trailer'], + 'trailery': ['literary', 'trailery'], + 'trailing': ['ringtail', 'trailing'], + 'trailside': ['dialister', 'trailside'], + 'train': ['riant', 'tairn', 'tarin', 'train'], + 'trainable': ['albertina', 'trainable'], + 'trainage': ['antiager', 'trainage'], + 'trainboy': ['bonitary', 'trainboy'], + 'trained': ['antired', 'detrain', 'randite', 'trained'], + 'trainee': ['enteria', 'trainee', 'triaene'], + 'trainer': ['arterin', 'retrain', 'terrain', 'trainer'], + 'trainless': ['sternalis', 'trainless'], + 'trainster': ['restraint', 'retransit', 'trainster', 'transiter'], + 'traintime': ['intimater', 'traintime'], + 'trainy': ['rytina', 'trainy', 'tyrian'], + 'traipse': ['piaster', 'piastre', 'raspite', 'spirate', 'traipse'], + 'trait': ['ratti', 'titar', 'trait'], + 'tram': ['mart', 'tram'], + 'trama': ['matar', 'matra', 'trama'], + 'tramal': ['matral', 'tramal'], + 'trame': ['armet', + 'mater', + 'merat', + 'metra', + 'ramet', + 'tamer', + 'terma', + 'trame', + 'trema'], + 'trametes': ['teamster', 'trametes'], + 'tramline': ['terminal', 'tramline'], + 'tramper': ['retramp', 'tramper'], + 'trample': ['templar', 'trample'], + 'trampoline': ['intemporal', 'trampoline'], + 'tran': ['natr', 'rant', 'tarn', 'tran'], + 'trance': ['canter', + 'creant', + 'cretan', + 'nectar', + 'recant', + 'tanrec', + 'trance'], + 'tranced': ['cantred', 'centrad', 'tranced'], + 'trancelike': ['nectarlike', 'trancelike'], + 'trankum': ['trankum', 'turkman'], + 'transamination': ['transamination', 'transanimation'], + 'transanimation': ['transamination', 'transanimation'], + 'transept': ['prestant', 'transept'], + 'transeptally': ['platysternal', 'transeptally'], + 'transformer': ['retransform', 'transformer'], + 'transfuge': ['afterguns', 'transfuge'], + 'transient': ['instanter', 'transient'], + 'transigent': ['astringent', 'transigent'], + 'transimpression': ['pretransmission', 'transimpression'], + 'transire': ['restrain', 'strainer', 'transire'], + 'transit': ['straint', 'transit', 'tristan'], + 'transiter': ['restraint', 'retransit', 'trainster', 'transiter'], + 'transitive': ['revisitant', 'transitive'], + 'transmarine': ['strainerman', 'transmarine'], + 'transmit': ['tantrism', 'transmit'], + 'transmold': ['landstorm', 'transmold'], + 'transoceanic': ['narcaciontes', 'transoceanic'], + 'transonic': ['constrain', 'transonic'], + 'transpire': ['prestrain', 'transpire'], + 'transplanter': ['retransplant', 'transplanter'], + 'transportee': ['paternoster', 'prosternate', 'transportee'], + 'transporter': ['retransport', 'transporter'], + 'transpose': ['patroness', 'transpose'], + 'transposer': ['transposer', 'transprose'], + 'transprose': ['transposer', 'transprose'], + 'trap': ['part', 'prat', 'rapt', 'tarp', 'trap'], + 'trapa': ['apart', 'trapa'], + 'trapes': ['paster', 'repast', 'trapes'], + 'trapfall': ['pratfall', 'trapfall'], + 'traphole': ['plethora', 'traphole'], + 'trappean': ['apparent', 'trappean'], + 'traps': ['spart', 'sprat', 'strap', 'traps'], + 'traship': ['harpist', 'traship'], + 'trasy': ['satyr', 'stary', 'stray', 'trasy'], + 'traulism': ['altruism', 'muralist', 'traulism', 'ultraism'], + 'trauma': ['taruma', 'trauma'], + 'travale': ['larvate', 'lavaret', 'travale'], + 'trave': ['avert', 'tarve', 'taver', 'trave'], + 'travel': ['travel', 'varlet'], + 'traveler': ['retravel', 'revertal', 'traveler'], + 'traversion': ['overstrain', 'traversion'], + 'travertine': ['travertine', 'trinervate'], + 'travoy': ['travoy', 'votary'], + 'tray': ['arty', 'atry', 'tray'], + 'treacle': ['electra', 'treacle'], + 'tread': ['dater', 'derat', 'detar', 'drate', 'rated', 'trade', 'tread'], + 'treader': ['derater', 'retrade', 'retread', 'treader'], + 'treading': ['gradient', 'treading'], + 'treadle': ['delater', 'related', 'treadle'], + 'treason': ['noreast', 'rosetan', 'seatron', 'senator', 'treason'], + 'treasonish': ['astonisher', 'reastonish', 'treasonish'], + 'treasonist': ['steatornis', 'treasonist'], + 'treasonous': ['anoestrous', 'treasonous'], + 'treasurer': ['serrature', 'treasurer'], + 'treat': ['atter', 'tater', 'teart', 'tetra', 'treat'], + 'treatably': ['tabletary', 'treatably'], + 'treatee': ['ateeter', 'treatee'], + 'treater': ['ettarre', 'retreat', 'treater'], + 'treatise': ['estriate', 'treatise'], + 'treaty': ['attery', 'treaty', 'yatter'], + 'treble': ['belter', 'elbert', 'treble'], + 'treculia': ['arculite', 'cutleria', 'lucretia', 'reticula', 'treculia'], + 'tree': ['reet', 'teer', 'tree'], + 'treed': ['deter', 'treed'], + 'treeful': ['fleuret', 'treeful'], + 'treehood': ['theodore', 'treehood'], + 'treemaker': ['marketeer', 'treemaker'], + 'treeman': ['remanet', 'remeant', 'treeman'], + 'treen': ['enter', 'neter', 'renet', 'terne', 'treen'], + 'treenail': ['elaterin', 'entailer', 'treenail'], + 'treeship': ['hepteris', 'treeship'], + 'tref': ['fret', 'reft', 'tref'], + 'trefle': ['felter', 'telfer', 'trefle'], + 'trellis': ['stiller', 'trellis'], + 'trema': ['armet', + 'mater', + 'merat', + 'metra', + 'ramet', + 'tamer', + 'terma', + 'trame', + 'trema'], + 'trematoid': ['meditator', 'trematoid'], + 'tremella': ['realmlet', 'tremella'], + 'tremie': ['metier', 'retime', 'tremie'], + 'tremolo': ['roomlet', 'tremolo'], + 'tremor': ['termor', 'tremor'], + 'trenail': ['entrail', + 'latiner', + 'latrine', + 'ratline', + 'reliant', + 'retinal', + 'trenail'], + 'trenchant': ['centranth', 'trenchant'], + 'trencher': ['retrench', 'trencher'], + 'trenchmaster': ['stretcherman', 'trenchmaster'], + 'trenchwise': ['trenchwise', 'winchester'], + 'trentine': ['renitent', 'trentine'], + 'trepan': ['arpent', + 'enrapt', + 'entrap', + 'panter', + 'parent', + 'pretan', + 'trepan'], + 'trephine': ['nephrite', 'prehnite', 'trephine'], + 'trepid': ['dipter', 'trepid'], + 'trepidation': ['departition', 'partitioned', 'trepidation'], + 'treron': ['terron', 'treron', 'troner'], + 'treronidae': ['reordinate', 'treronidae'], + 'tressed': ['dessert', 'tressed'], + 'tressful': ['tressful', 'turfless'], + 'tressour': ['tressour', 'trousers'], + 'trest': ['stert', 'stret', 'trest'], + 'trestle': ['settler', 'sterlet', 'trestle'], + 'trevor': ['trevor', 'trover'], + 'trews': ['strew', 'trews', 'wrest'], + 'trey': ['trey', 'tyre'], + 'tri': ['rit', 'tri'], + 'triable': ['betrail', 'librate', 'triable', 'trilabe'], + 'triace': ['acrite', 'arcite', 'tercia', 'triace', 'tricae'], + 'triacid': ['arctiid', 'triacid', 'triadic'], + 'triacontane': ['recantation', 'triacontane'], + 'triaconter': ['retraction', 'triaconter'], + 'triactine': ['intricate', 'triactine'], + 'triadic': ['arctiid', 'triacid', 'triadic'], + 'triadical': ['raticidal', 'triadical'], + 'triadist': ['distrait', 'triadist'], + 'triaene': ['enteria', 'trainee', 'triaene'], + 'triage': ['gaiter', 'tairge', 'triage'], + 'trial': ['litra', 'trail', 'trial'], + 'trialism': ['mistrial', 'trialism'], + 'trialist': ['taistril', 'trialist'], + 'triamide': ['dimetria', 'mitridae', 'tiremaid', 'triamide'], + 'triamino': ['miniator', 'triamino'], + 'triandria': ['irradiant', 'triandria'], + 'triangle': ['integral', 'teraglin', 'triangle'], + 'triangula': ['tragulina', 'triangula'], + 'triannual': ['innatural', 'triannual'], + 'triannulate': ['antineutral', 'triannulate'], + 'triantelope': ['interpolate', 'triantelope'], + 'triapsidal': ['lapidarist', 'triapsidal'], + 'triareal': ['arterial', 'triareal'], + 'trias': ['arist', + 'astir', + 'sitar', + 'stair', + 'stria', + 'tarsi', + 'tisar', + 'trias'], + 'triassic': ['sarcitis', 'triassic'], + 'triazane': ['nazarite', 'nazirate', 'triazane'], + 'triazine': ['nazirite', 'triazine'], + 'tribade': ['redbait', 'tribade'], + 'tribase': ['baister', 'tribase'], + 'tribe': ['biter', 'tribe'], + 'tribelet': ['belitter', 'tribelet'], + 'triblet': ['blitter', 'brittle', 'triblet'], + 'tribonema': ['brominate', 'tribonema'], + 'tribuna': ['arbutin', 'tribuna'], + 'tribunal': ['tribunal', 'turbinal', 'untribal'], + 'tribunate': ['tribunate', 'turbinate'], + 'tribune': ['tribune', 'tuberin', 'turbine'], + 'tricae': ['acrite', 'arcite', 'tercia', 'triace', 'tricae'], + 'trice': ['citer', 'recti', 'ticer', 'trice'], + 'tricennial': ['encrinital', 'tricennial'], + 'triceratops': ['tetrasporic', 'triceratops'], + 'triceria': ['criteria', 'triceria'], + 'tricerion': ['criterion', 'tricerion'], + 'tricerium': ['criterium', 'tricerium'], + 'trichinous': ['trichinous', 'unhistoric'], + 'trichogyne': ['thyrogenic', 'trichogyne'], + 'trichoid': ['hidrotic', 'trichoid'], + 'trichomanes': ['anchoretism', 'trichomanes'], + 'trichome': ['chromite', 'trichome'], + 'trichopore': ['horopteric', 'rheotropic', 'trichopore'], + 'trichosis': ['historics', 'trichosis'], + 'trichosporum': ['sporotrichum', 'trichosporum'], + 'trichroic': ['cirrhotic', 'trichroic'], + 'trichroism': ['trichroism', 'triorchism'], + 'trichromic': ['microcrith', 'trichromic'], + 'tricia': ['iatric', 'tricia'], + 'trickle': ['tickler', 'trickle'], + 'triclinate': ['intractile', 'triclinate'], + 'tricolumnar': ['tricolumnar', 'ultramicron'], + 'tricosane': ['atroscine', 'certosina', 'ostracine', 'tinoceras', 'tricosane'], + 'tridacna': ['antacrid', 'cardiant', 'radicant', 'tridacna'], + 'tridecane': ['nectaried', 'tridecane'], + 'tridecene': ['intercede', 'tridecene'], + 'tridecyl': ['directly', 'tridecyl'], + 'tridiapason': ['disparation', 'tridiapason'], + 'tried': ['diter', 'tired', 'tried'], + 'triedly': ['tiredly', 'triedly'], + 'triene': ['entire', 'triene'], + 'triens': ['estrin', 'insert', 'sinter', 'sterin', 'triens'], + 'triental': ['tetralin', 'triental'], + 'triequal': ['quartile', 'requital', 'triequal'], + 'trier': ['terri', 'tirer', 'trier'], + 'trifle': ['fertil', 'filter', 'lifter', 'relift', 'trifle'], + 'trifler': ['flirter', 'trifler'], + 'triflet': ['flitter', 'triflet'], + 'trifling': ['flirting', 'trifling'], + 'triflingly': ['flirtingly', 'triflingly'], + 'trifolium': ['lituiform', 'trifolium'], + 'trig': ['girt', 'grit', 'trig'], + 'trigona': ['grotian', 'trigona'], + 'trigone': ['ergotin', 'genitor', 'negrito', 'ogtiern', 'trigone'], + 'trigonia': ['rigation', 'trigonia'], + 'trigonid': ['trigonid', 'tringoid'], + 'trigyn': ['trigyn', 'trying'], + 'trilabe': ['betrail', 'librate', 'triable', 'trilabe'], + 'trilineate': ['retinalite', 'trilineate'], + 'trilisa': ['liatris', 'trilisa'], + 'trillet': ['rillett', 'trillet'], + 'trilobate': ['latrobite', 'trilobate'], + 'trilobated': ['titleboard', 'trilobated'], + 'trimacular': ['matricular', 'trimacular'], + 'trimensual': ['neutralism', 'trimensual'], + 'trimer': ['mitrer', 'retrim', 'trimer'], + 'trimesic': ['meristic', 'trimesic', 'trisemic'], + 'trimesitinic': ['interimistic', 'trimesitinic'], + 'trimesyl': ['trimesyl', 'tylerism'], + 'trimeter': ['remitter', 'trimeter'], + 'trimstone': ['sortiment', 'trimstone'], + 'trinalize': ['latinizer', 'trinalize'], + 'trindle': ['tendril', 'trindle'], + 'trine': ['inert', 'inter', 'niter', 'retin', 'trine'], + 'trinely': ['elytrin', 'inertly', 'trinely'], + 'trinervate': ['travertine', 'trinervate'], + 'trinerve': ['inverter', 'reinvert', 'trinerve'], + 'trineural': ['retinular', 'trineural'], + 'tringa': ['rating', 'tringa'], + 'tringle': ['ringlet', 'tingler', 'tringle'], + 'tringoid': ['trigonid', 'tringoid'], + 'trinket': ['knitter', 'trinket'], + 'trinkle': ['tinkler', 'trinkle'], + 'trinoctial': ['tinctorial', 'trinoctial'], + 'trinodine': ['rendition', 'trinodine'], + 'trintle': ['lettrin', 'trintle'], + 'trio': ['riot', 'roit', 'trio'], + 'triode': ['editor', 'triode'], + 'trioecism': ['eroticism', 'isometric', 'meroistic', 'trioecism'], + 'triole': ['loiter', 'toiler', 'triole'], + 'trioleic': ['elicitor', 'trioleic'], + 'triolet': ['lotrite', 'tortile', 'triolet'], + 'trionymal': ['normality', 'trionymal'], + 'triopidae': ['poritidae', 'triopidae'], + 'triops': ['ripost', 'triops', 'tripos'], + 'triorchism': ['trichroism', 'triorchism'], + 'triose': ['restio', 'sorite', 'sortie', 'triose'], + 'tripe': ['perit', 'retip', 'tripe'], + 'tripedal': ['dipteral', 'tripedal'], + 'tripel': ['tripel', 'triple'], + 'tripeman': ['imperant', 'pairment', 'partimen', 'premiant', 'tripeman'], + 'tripersonal': ['intersporal', 'tripersonal'], + 'tripestone': ['septentrio', 'tripestone'], + 'triphane': ['perianth', 'triphane'], + 'triplane': ['interlap', 'repliant', 'triplane'], + 'triplasian': ['airplanist', 'triplasian'], + 'triplasic': ['pilastric', 'triplasic'], + 'triple': ['tripel', 'triple'], + 'triplice': ['perlitic', 'triplice'], + 'triplopia': ['propitial', 'triplopia'], + 'tripod': ['torpid', 'tripod'], + 'tripodal': ['dioptral', 'tripodal'], + 'tripodic': ['dioptric', 'tripodic'], + 'tripodical': ['dioptrical', 'tripodical'], + 'tripody': ['dioptry', 'tripody'], + 'tripos': ['ripost', 'triops', 'tripos'], + 'trippist': ['strippit', 'trippist'], + 'tripple': ['ripplet', 'tippler', 'tripple'], + 'tripsis': ['pristis', 'tripsis'], + 'tripsome': ['imposter', 'tripsome'], + 'tripudiant': ['antiputrid', 'tripudiant'], + 'tripyrenous': ['neurotripsy', 'tripyrenous'], + 'triratna': ['tartarin', 'triratna'], + 'trireme': ['meriter', 'miterer', 'trireme'], + 'trisalt': ['starlit', 'trisalt'], + 'trisected': ['decretist', 'trisected'], + 'trisector': ['tortrices', 'trisector'], + 'trisemic': ['meristic', 'trimesic', 'trisemic'], + 'trisetose': ['esoterist', 'trisetose'], + 'trishna': ['tarnish', 'trishna'], + 'trisilane': ['listerian', 'trisilane'], + 'triskele': ['kreistle', 'triskele'], + 'trismus': ['sistrum', 'trismus'], + 'trisome': ['erotism', 'mortise', 'trisome'], + 'trisomy': ['toryism', 'trisomy'], + 'trisonant': ['strontian', 'trisonant'], + 'trispinose': ['pirssonite', 'trispinose'], + 'trist': ['strit', 'trist'], + 'tristan': ['straint', 'transit', 'tristan'], + 'trisula': ['latirus', 'trisula'], + 'trisulcate': ['testicular', 'trisulcate'], + 'tritanope': ['antitrope', 'patronite', 'tritanope'], + 'tritanopic': ['antitropic', 'tritanopic'], + 'trite': ['titer', 'titre', 'trite'], + 'tritely': ['littery', 'tritely'], + 'triterpene': ['preterient', 'triterpene'], + 'tritheism': ['tiresmith', 'tritheism'], + 'trithionate': ['anorthitite', 'trithionate'], + 'tritocone': ['torticone', 'tritocone'], + 'tritoma': ['mattoir', 'tritoma'], + 'triton': ['intort', 'tornit', 'triton'], + 'triune': ['runite', 'triune', 'uniter', 'untire'], + 'trivalence': ['cantilever', 'trivalence'], + 'trivial': ['trivial', 'vitrail'], + 'trivialist': ['trivialist', 'vitrailist'], + 'troat': ['ottar', 'tarot', 'torta', 'troat'], + 'troca': ['actor', 'corta', 'croat', 'rocta', 'taroc', 'troca'], + 'trocar': ['carrot', 'trocar'], + 'trochaic': ['thoracic', 'tocharic', 'trochaic'], + 'trochate': ['theocrat', 'trochate'], + 'troche': ['hector', 'rochet', 'tocher', 'troche'], + 'trochi': ['chorti', 'orthic', 'thoric', 'trochi'], + 'trochidae': ['charioted', 'trochidae'], + 'trochila': ['acrolith', 'trochila'], + 'trochilic': ['chloritic', 'trochilic'], + 'trochlea': ['chlorate', 'trochlea'], + 'trochlearis': ['rhetoricals', 'trochlearis'], + 'trode': ['doter', 'tored', 'trode'], + 'trog': ['grot', 'trog'], + 'trogonidae': ['derogation', 'trogonidae'], + 'troiades': ['asteroid', 'troiades'], + 'troic': ['toric', 'troic'], + 'troika': ['korait', 'troika'], + 'trolley': ['tollery', 'trolley'], + 'tromba': ['tambor', 'tromba'], + 'trombe': ['retomb', 'trombe'], + 'trompe': ['emptor', 'trompe'], + 'tron': ['torn', 'tron'], + 'trona': ['orant', 'rotan', 'toran', 'trona'], + 'tronage': ['negator', 'tronage'], + 'trone': ['noter', 'tenor', 'toner', 'trone'], + 'troner': ['terron', 'treron', 'troner'], + 'troop': ['porto', 'proto', 'troop'], + 'trooper': ['protore', 'trooper'], + 'tropaeolum': ['pleurotoma', 'tropaeolum'], + 'tropaion': ['opinator', 'tropaion'], + 'tropal': ['patrol', 'portal', 'tropal'], + 'troparion': ['proration', 'troparion'], + 'tropary': ['parroty', 'portray', 'tropary'], + 'trope': ['poter', 'prote', 'repot', 'tepor', 'toper', 'trope'], + 'tropeic': ['perotic', 'proteic', 'tropeic'], + 'tropeine': ['ereption', 'tropeine'], + 'troper': ['porret', 'porter', 'report', 'troper'], + 'trophema': ['metaphor', 'trophema'], + 'trophesial': ['hospitaler', 'trophesial'], + 'trophical': ['carpolith', 'politarch', 'trophical'], + 'trophodisc': ['doctorship', 'trophodisc'], + 'trophonema': ['homopteran', 'trophonema'], + 'trophotropic': ['prototrophic', 'trophotropic'], + 'tropical': ['plicator', 'tropical'], + 'tropically': ['polycitral', 'tropically'], + 'tropidine': ['direption', 'perdition', 'tropidine'], + 'tropine': ['pointer', 'protein', 'pterion', 'repoint', 'tropine'], + 'tropism': ['primost', 'tropism'], + 'tropist': ['protist', 'tropist'], + 'tropistic': ['proctitis', 'protistic', 'tropistic'], + 'tropophyte': ['protophyte', 'tropophyte'], + 'tropophytic': ['protophytic', 'tropophytic'], + 'tropyl': ['portly', 'protyl', 'tropyl'], + 'trostera': ['rostrate', 'trostera'], + 'trot': ['tort', 'trot'], + 'troth': ['thort', 'troth'], + 'trotline': ['interlot', 'trotline'], + 'trouble': ['boulter', 'trouble'], + 'troughy': ['troughy', 'yoghurt'], + 'trounce': ['cornute', 'counter', 'recount', 'trounce'], + 'troupe': ['pouter', 'roupet', 'troupe'], + 'trouse': ['ouster', 'souter', 'touser', 'trouse'], + 'trouser': ['rouster', 'trouser'], + 'trouserian': ['souterrain', 'ternarious', 'trouserian'], + 'trousers': ['tressour', 'trousers'], + 'trout': ['trout', 'tutor'], + 'trouter': ['torture', 'trouter', 'tutorer'], + 'troutless': ['troutless', 'tutorless'], + 'trouty': ['trouty', 'tryout', 'tutory'], + 'trouvere': ['overtrue', 'overture', 'trouvere'], + 'trove': ['overt', 'rovet', 'torve', 'trove', 'voter'], + 'trover': ['trevor', 'trover'], + 'trow': ['trow', 'wort'], + 'trowel': ['rowlet', 'trowel', 'wolter'], + 'troy': ['royt', 'ryot', 'tory', 'troy', 'tyro'], + 'truandise': ['disnature', 'sturnidae', 'truandise'], + 'truant': ['truant', 'turtan'], + 'trub': ['brut', 'burt', 'trub', 'turb'], + 'trubu': ['burut', 'trubu'], + 'truce': ['cruet', 'eruct', 'recut', 'truce'], + 'truceless': ['cutleress', 'lecturess', 'truceless'], + 'trucial': ['curtail', 'trucial'], + 'trucks': ['struck', 'trucks'], + 'truculent': ['truculent', 'unclutter'], + 'truelove': ['revolute', 'truelove'], + 'truffle': ['fretful', 'truffle'], + 'trug': ['gurt', 'trug'], + 'truistical': ['altruistic', 'truistical', 'ultraistic'], + 'truly': ['rutyl', 'truly'], + 'trumperiness': ['surprisement', 'trumperiness'], + 'trumpie': ['imputer', 'trumpie'], + 'trun': ['runt', 'trun', 'turn'], + 'truncated': ['reductant', 'traducent', 'truncated'], + 'trundle': ['rundlet', 'trundle'], + 'trush': ['hurst', 'trush'], + 'trusion': ['nitrous', 'trusion'], + 'trust': ['strut', 'sturt', 'trust'], + 'trustee': ['surette', 'trustee'], + 'trusteeism': ['sestertium', 'trusteeism'], + 'trusten': ['entrust', 'stunter', 'trusten'], + 'truster': ['retrust', 'truster'], + 'trustle': ['slutter', 'trustle'], + 'truth': ['thurt', 'truth'], + 'trying': ['trigyn', 'trying'], + 'tryma': ['marty', 'tryma'], + 'tryout': ['trouty', 'tryout', 'tutory'], + 'trypa': ['party', 'trypa'], + 'trypan': ['pantry', 'trypan'], + 'tryptase': ['tapestry', 'tryptase'], + 'tsar': ['sart', 'star', 'stra', 'tars', 'tsar'], + 'tsardom': ['stardom', 'tsardom'], + 'tsarina': ['artisan', 'astrain', 'sartain', 'tsarina'], + 'tsarship': ['starship', 'tsarship'], + 'tsatlee': ['atelets', 'tsatlee'], + 'tsere': ['ester', + 'estre', + 'reest', + 'reset', + 'steer', + 'stere', + 'stree', + 'terse', + 'tsere'], + 'tsetse': ['sestet', 'testes', 'tsetse'], + 'tshi': ['hist', 'sith', 'this', 'tshi'], + 'tsia': ['atis', 'sita', 'tsia'], + 'tsine': ['inset', 'neist', 'snite', 'stein', 'stine', 'tsine'], + 'tsiology': ['sitology', 'tsiology'], + 'tsoneca': ['costean', 'tsoneca'], + 'tsonecan': ['noncaste', 'tsonecan'], + 'tsuga': ['agust', 'tsuga'], + 'tsuma': ['matsu', 'tamus', 'tsuma'], + 'tsun': ['stun', 'sunt', 'tsun'], + 'tu': ['tu', 'ut'], + 'tua': ['tau', 'tua', 'uta'], + 'tuan': ['antu', 'aunt', 'naut', 'taun', 'tuan', 'tuna'], + 'tuareg': ['argute', 'guetar', 'rugate', 'tuareg'], + 'tuarn': ['arnut', 'tuarn', 'untar'], + 'tub': ['but', 'tub'], + 'tuba': ['abut', 'tabu', 'tuba'], + 'tubae': ['butea', 'taube', 'tubae'], + 'tubal': ['balut', 'tubal'], + 'tubar': ['bruta', 'tubar'], + 'tubate': ['battue', 'tubate'], + 'tube': ['bute', 'tebu', 'tube'], + 'tuber': ['brute', 'buret', 'rebut', 'tuber'], + 'tubercula': ['lucubrate', 'tubercula'], + 'tuberin': ['tribune', 'tuberin', 'turbine'], + 'tuberless': ['butleress', 'tuberless'], + 'tublet': ['buttle', 'tublet'], + 'tuboovarial': ['ovariotubal', 'tuboovarial'], + 'tucana': ['canaut', 'tucana'], + 'tucano': ['toucan', 'tucano', 'uncoat'], + 'tuchun': ['tuchun', 'uncuth'], + 'tucker': ['retuck', 'tucker'], + 'tue': ['tue', 'ute'], + 'tueiron': ['routine', 'tueiron'], + 'tug': ['gut', 'tug'], + 'tughra': ['raught', 'tughra'], + 'tugless': ['gutless', 'tugless'], + 'tuglike': ['gutlike', 'tuglike'], + 'tugman': ['tangum', 'tugman'], + 'tuism': ['muist', 'tuism'], + 'tuke': ['ketu', 'teuk', 'tuke'], + 'tukra': ['kraut', 'tukra'], + 'tulare': ['tulare', 'uretal'], + 'tulasi': ['situal', 'situla', 'tulasi'], + 'tulchan': ['tulchan', 'unlatch'], + 'tule': ['lute', 'tule'], + 'tulipa': ['tipula', 'tulipa'], + 'tulisan': ['latinus', 'tulisan', 'unalist'], + 'tulsi': ['litus', 'sluit', 'tulsi'], + 'tumbler': ['tumbler', 'tumbrel'], + 'tumbrel': ['tumbler', 'tumbrel'], + 'tume': ['mute', 'tume'], + 'tumescence': ['mutescence', 'tumescence'], + 'tumorous': ['mortuous', 'tumorous'], + 'tumulary': ['mutulary', 'tumulary'], + 'tun': ['nut', 'tun'], + 'tuna': ['antu', 'aunt', 'naut', 'taun', 'tuan', 'tuna'], + 'tunable': ['abluent', 'tunable'], + 'tunbellied': ['tunbellied', 'unbilleted'], + 'tunca': ['tunca', 'unact'], + 'tund': ['dunt', 'tund'], + 'tunder': ['runted', 'tunder', 'turned'], + 'tundra': ['durant', 'tundra'], + 'tuner': ['enrut', 'tuner', 'urent'], + 'tunga': ['gaunt', 'tunga'], + 'tungan': ['tangun', 'tungan'], + 'tungate': ['tungate', 'tutenag'], + 'tungo': ['tungo', 'ungot'], + 'tungstosilicate': ['silicotungstate', 'tungstosilicate'], + 'tungstosilicic': ['silicotungstic', 'tungstosilicic'], + 'tunic': ['cutin', 'incut', 'tunic'], + 'tunica': ['anicut', 'nautic', 'ticuna', 'tunica'], + 'tunican': ['ticunan', 'tunican'], + 'tunicary': ['nycturia', 'tunicary'], + 'tunicle': ['linecut', 'tunicle'], + 'tunicless': ['lentiscus', 'tunicless'], + 'tunist': ['suttin', 'tunist'], + 'tunk': ['knut', 'tunk'], + 'tunker': ['tunker', 'turken'], + 'tunlike': ['nutlike', 'tunlike'], + 'tunna': ['naunt', 'tunna'], + 'tunnel': ['nunlet', 'tunnel', 'unlent'], + 'tunnelman': ['annulment', 'tunnelman'], + 'tunner': ['runnet', 'tunner', 'unrent'], + 'tunnor': ['tunnor', 'untorn'], + 'tuno': ['tuno', 'unto'], + 'tup': ['put', 'tup'], + 'tur': ['rut', 'tur'], + 'turacin': ['curtain', 'turacin', 'turcian'], + 'turanian': ['nutarian', 'turanian'], + 'turanism': ['naturism', 'sturmian', 'turanism'], + 'turb': ['brut', 'burt', 'trub', 'turb'], + 'turban': ['tanbur', 'turban'], + 'turbaned': ['breadnut', 'turbaned'], + 'turbanless': ['substernal', 'turbanless'], + 'turbeh': ['hubert', 'turbeh'], + 'turbinal': ['tribunal', 'turbinal', 'untribal'], + 'turbinate': ['tribunate', 'turbinate'], + 'turbine': ['tribune', 'tuberin', 'turbine'], + 'turbined': ['turbined', 'underbit'], + 'turcian': ['curtain', 'turacin', 'turcian'], + 'turco': ['court', 'crout', 'turco'], + 'turcoman': ['courtman', 'turcoman'], + 'turdinae': ['indurate', 'turdinae'], + 'turdine': ['intrude', 'turdine', 'untired', 'untried'], + 'tureen': ['neuter', 'retune', 'runtee', 'tenure', 'tureen'], + 'turfed': ['dufter', 'turfed'], + 'turfen': ['turfen', 'unfret'], + 'turfless': ['tressful', 'turfless'], + 'turgent': ['grutten', 'turgent'], + 'turk': ['kurt', 'turk'], + 'turken': ['tunker', 'turken'], + 'turki': ['tikur', 'turki'], + 'turkman': ['trankum', 'turkman'], + 'turma': ['martu', 'murat', 'turma'], + 'turn': ['runt', 'trun', 'turn'], + 'turndown': ['downturn', 'turndown'], + 'turned': ['runted', 'tunder', 'turned'], + 'turnel': ['runlet', 'turnel'], + 'turner': ['return', 'turner'], + 'turnhall': ['turnhall', 'unthrall'], + 'turnout': ['outturn', 'turnout'], + 'turnover': ['overturn', 'turnover'], + 'turnpin': ['turnpin', 'unprint'], + 'turns': ['snurt', 'turns'], + 'turntail': ['rutilant', 'turntail'], + 'turnup': ['turnup', 'upturn'], + 'turp': ['prut', 'turp'], + 'turpid': ['putrid', 'turpid'], + 'turpidly': ['putridly', 'turpidly'], + 'turps': ['spurt', 'turps'], + 'turret': ['rutter', 'turret'], + 'turricula': ['turricula', 'utricular'], + 'turse': ['serut', 'strue', 'turse', 'uster'], + 'tursenoi': ['rutinose', 'tursenoi'], + 'tursio': ['suitor', 'tursio'], + 'turtan': ['truant', 'turtan'], + 'tuscan': ['cantus', 'tuscan', 'uncast'], + 'tusche': ['schute', 'tusche'], + 'tush': ['shut', 'thus', 'tush'], + 'tusher': ['reshut', 'suther', 'thurse', 'tusher'], + 'tussal': ['saltus', 'tussal'], + 'tusser': ['russet', 'tusser'], + 'tussore': ['estrous', 'oestrus', 'sestuor', 'tussore'], + 'tutelo': ['outlet', 'tutelo'], + 'tutenag': ['tungate', 'tutenag'], + 'tutman': ['mutant', 'tantum', 'tutman'], + 'tutor': ['trout', 'tutor'], + 'tutorer': ['torture', 'trouter', 'tutorer'], + 'tutorial': ['outtrail', 'tutorial'], + 'tutorism': ['mistutor', 'tutorism'], + 'tutorless': ['troutless', 'tutorless'], + 'tutory': ['trouty', 'tryout', 'tutory'], + 'tuts': ['stut', 'tuts'], + 'tutster': ['stutter', 'tutster'], + 'twa': ['taw', 'twa', 'wat'], + 'twae': ['tewa', 'twae', 'weta'], + 'twain': ['atwin', 'twain', 'witan'], + 'twaite': ['tawite', 'tawtie', 'twaite'], + 'twal': ['twal', 'walt'], + 'twas': ['sawt', 'staw', 'swat', 'taws', 'twas', 'wast'], + 'twat': ['twat', 'watt'], + 'twee': ['twee', 'weet'], + 'tweel': ['tewel', 'tweel'], + 'twere': ['rewet', 'tewer', 'twere'], + 'twi': ['twi', 'wit'], + 'twigsome': ['twigsome', 'wegotism'], + 'twin': ['twin', 'wint'], + 'twiner': ['twiner', 'winter'], + 'twingle': ['twingle', 'welting', 'winglet'], + 'twinkle': ['twinkle', 'winklet'], + 'twinkler': ['twinkler', 'wrinklet'], + 'twinter': ['twinter', 'written'], + 'twire': ['twire', 'write'], + 'twister': ['retwist', 'twister'], + 'twitchety': ['twitchety', 'witchetty'], + 'twite': ['tewit', 'twite'], + 'two': ['tow', 'two', 'wot'], + 'twoling': ['lingtow', 'twoling'], + 'tyche': ['techy', 'tyche'], + 'tydie': ['deity', 'tydie'], + 'tye': ['tye', 'yet'], + 'tyke': ['kyte', 'tyke'], + 'tylerism': ['trimesyl', 'tylerism'], + 'tyloma': ['latomy', 'tyloma'], + 'tylose': ['tolsey', 'tylose'], + 'tylosis': ['tossily', 'tylosis'], + 'tylotus': ['stoutly', 'tylotus'], + 'tylus': ['lusty', 'tylus'], + 'typal': ['aptly', 'patly', 'platy', 'typal'], + 'typees': ['steepy', 'typees'], + 'typer': ['perty', 'typer'], + 'typha': ['pathy', 'typha'], + 'typhia': ['pythia', 'typhia'], + 'typhic': ['phytic', 'pitchy', 'pythic', 'typhic'], + 'typhlopidae': ['heptaploidy', 'typhlopidae'], + 'typhoean': ['anophyte', 'typhoean'], + 'typhogenic': ['phytogenic', 'pythogenic', 'typhogenic'], + 'typhoid': ['phytoid', 'typhoid'], + 'typhonian': ['antiphony', 'typhonian'], + 'typhonic': ['hypnotic', 'phytonic', 'pythonic', 'typhonic'], + 'typhosis': ['phytosis', 'typhosis'], + 'typica': ['atypic', 'typica'], + 'typographer': ['petrography', 'pterography', 'typographer'], + 'typographic': ['graphotypic', 'pictography', 'typographic'], + 'typology': ['logotypy', 'typology'], + 'typophile': ['hippolyte', 'typophile'], + 'tyre': ['trey', 'tyre'], + 'tyrian': ['rytina', 'trainy', 'tyrian'], + 'tyro': ['royt', 'ryot', 'tory', 'troy', 'tyro'], + 'tyrocidin': ['nordicity', 'tyrocidin'], + 'tyrolean': ['neolatry', 'ornately', 'tyrolean'], + 'tyrolite': ['toiletry', 'tyrolite'], + 'tyrone': ['torney', 'tyrone'], + 'tyronism': ['smyrniot', 'tyronism'], + 'tyrosine': ['tyrosine', 'tyrsenoi'], + 'tyrrheni': ['erythrin', 'tyrrheni'], + 'tyrsenoi': ['tyrosine', 'tyrsenoi'], + 'tyste': ['testy', 'tyste'], + 'tyto': ['toty', 'tyto'], + 'uang': ['gaun', 'guan', 'guna', 'uang'], + 'ucal': ['caul', 'ucal'], + 'udal': ['auld', 'dual', 'laud', 'udal'], + 'udaler': ['lauder', 'udaler'], + 'udalman': ['ladanum', 'udalman'], + 'udo': ['duo', 'udo'], + 'uds': ['sud', 'uds'], + 'ugh': ['hug', 'ugh'], + 'uglisome': ['eulogism', 'uglisome'], + 'ugrian': ['gurian', 'ugrian'], + 'ugric': ['guric', 'ugric'], + 'uhtsong': ['gunshot', 'shotgun', 'uhtsong'], + 'uinal': ['inula', 'luian', 'uinal'], + 'uinta': ['uinta', 'uniat'], + 'ulcer': ['cruel', 'lucre', 'ulcer'], + 'ulcerate': ['celature', 'ulcerate'], + 'ulcerous': ['ulcerous', 'urceolus'], + 'ule': ['leu', 'lue', 'ule'], + 'ulema': ['amelu', 'leuma', 'ulema'], + 'uletic': ['lucite', 'luetic', 'uletic'], + 'ulex': ['luxe', 'ulex'], + 'ulla': ['lula', 'ulla'], + 'ulling': ['ulling', 'ungill'], + 'ulmin': ['linum', 'ulmin'], + 'ulminic': ['clinium', 'ulminic'], + 'ulmo': ['moul', 'ulmo'], + 'ulna': ['laun', 'luna', 'ulna', 'unal'], + 'ulnad': ['dunal', 'laund', 'lunda', 'ulnad'], + 'ulnar': ['lunar', 'ulnar', 'urnal'], + 'ulnare': ['lunare', 'neural', 'ulnare', 'unreal'], + 'ulnaria': ['lunaria', 'ulnaria', 'uralian'], + 'ulotrichi': ['ulotrichi', 'urolithic'], + 'ulster': ['luster', 'result', 'rustle', 'sutler', 'ulster'], + 'ulstered': ['deluster', 'ulstered'], + 'ulsterian': ['neuralist', 'ulsterian', 'unrealist'], + 'ulstering': ['resulting', 'ulstering'], + 'ulsterman': ['menstrual', 'ulsterman'], + 'ultima': ['mulita', 'ultima'], + 'ultimate': ['mutilate', 'ultimate'], + 'ultimation': ['mutilation', 'ultimation'], + 'ultonian': ['lunation', 'ultonian'], + 'ultra': ['lutra', 'ultra'], + 'ultrabasic': ['arcubalist', 'ultrabasic'], + 'ultraism': ['altruism', 'muralist', 'traulism', 'ultraism'], + 'ultraist': ['altruist', 'ultraist'], + 'ultraistic': ['altruistic', 'truistical', 'ultraistic'], + 'ultramicron': ['tricolumnar', 'ultramicron'], + 'ultraminute': ['intermutual', 'ultraminute'], + 'ultramontane': ['tournamental', 'ultramontane'], + 'ultranice': ['centurial', 'lucretian', 'ultranice'], + 'ultrasterile': ['reillustrate', 'ultrasterile'], + 'ulua': ['aulu', 'ulua'], + 'ulva': ['ulva', 'uval'], + 'um': ['mu', 'um'], + 'umbel': ['umbel', 'umble'], + 'umbellar': ['umbellar', 'umbrella'], + 'umber': ['brume', 'umber'], + 'umbilic': ['bulimic', 'umbilic'], + 'umbiliform': ['bulimiform', 'umbiliform'], + 'umble': ['umbel', 'umble'], + 'umbonial': ['olibanum', 'umbonial'], + 'umbral': ['brumal', 'labrum', 'lumbar', 'umbral'], + 'umbrel': ['lumber', 'rumble', 'umbrel'], + 'umbrella': ['umbellar', 'umbrella'], + 'umbrous': ['brumous', 'umbrous'], + 'ume': ['emu', 'ume'], + 'umlaut': ['mutual', 'umlaut'], + 'umph': ['hump', 'umph'], + 'umpire': ['impure', 'umpire'], + 'un': ['nu', 'un'], + 'unabetted': ['debutante', 'unabetted'], + 'unabhorred': ['unabhorred', 'unharbored'], + 'unable': ['nebula', 'unable', 'unbale'], + 'unaccumulate': ['acutenaculum', 'unaccumulate'], + 'unact': ['tunca', 'unact'], + 'unadherent': ['unadherent', 'underneath', 'underthane'], + 'unadmire': ['unadmire', 'underaim'], + 'unadmired': ['unadmired', 'undermaid'], + 'unadored': ['unadored', 'unroaded'], + 'unadvertised': ['disadventure', 'unadvertised'], + 'unafire': ['fuirena', 'unafire'], + 'unaged': ['augend', 'engaud', 'unaged'], + 'unagreed': ['dungaree', 'guardeen', 'unagreed', 'underage', 'ungeared'], + 'unailing': ['inguinal', 'unailing'], + 'unaimed': ['numidae', 'unaimed'], + 'unaisled': ['unaisled', 'unsailed'], + 'unakite': ['kutenai', 'unakite'], + 'unal': ['laun', 'luna', 'ulna', 'unal'], + 'unalarming': ['unalarming', 'unmarginal'], + 'unalert': ['laurent', 'neutral', 'unalert'], + 'unalertly': ['neutrally', 'unalertly'], + 'unalertness': ['neutralness', 'unalertness'], + 'unalimentary': ['anteluminary', 'unalimentary'], + 'unalist': ['latinus', 'tulisan', 'unalist'], + 'unallotted': ['unallotted', 'untotalled'], + 'unalmsed': ['dulseman', 'unalmsed'], + 'unaltered': ['unaltered', 'unrelated'], + 'unaltering': ['unaltering', 'unrelating'], + 'unamassed': ['mussaenda', 'unamassed'], + 'unambush': ['subhuman', 'unambush'], + 'unamenability': ['unamenability', 'unnameability'], + 'unamenable': ['unamenable', 'unnameable'], + 'unamenableness': ['unamenableness', 'unnameableness'], + 'unamenably': ['unamenably', 'unnameably'], + 'unamend': ['mundane', 'unamend', 'unmaned', 'unnamed'], + 'unami': ['maniu', 'munia', 'unami'], + 'unapt': ['punta', 'unapt', 'untap'], + 'unarising': ['grusinian', 'unarising'], + 'unarm': ['muran', 'ruman', 'unarm', 'unram', 'urman'], + 'unarmed': ['duramen', 'maunder', 'unarmed'], + 'unarray': ['unarray', 'yaruran'], + 'unarrestable': ['subterraneal', 'unarrestable'], + 'unarrested': ['unarrested', 'unserrated'], + 'unarted': ['daunter', 'unarted', 'unrated', 'untread'], + 'unarticled': ['denticular', 'unarticled'], + 'unartistic': ['naturistic', 'unartistic'], + 'unartistical': ['naturalistic', 'unartistical'], + 'unartistically': ['naturistically', 'unartistically'], + 'unary': ['anury', 'unary', 'unray'], + 'unastray': ['auntsary', 'unastray'], + 'unathirst': ['struthian', 'unathirst'], + 'unattire': ['tainture', 'unattire'], + 'unattuned': ['unattuned', 'untaunted'], + 'unaverted': ['adventure', 'unaverted'], + 'unavertible': ['unavertible', 'unveritable'], + 'unbag': ['bugan', 'bunga', 'unbag'], + 'unbain': ['nubian', 'unbain'], + 'unbale': ['nebula', 'unable', 'unbale'], + 'unbar': ['buran', 'unbar', 'urban'], + 'unbare': ['eburna', 'unbare', 'unbear', 'urbane'], + 'unbarred': ['errabund', 'unbarred'], + 'unbased': ['subdean', 'unbased'], + 'unbaste': ['unbaste', 'unbeast'], + 'unbatted': ['debutant', 'unbatted'], + 'unbay': ['bunya', 'unbay'], + 'unbe': ['benu', 'unbe'], + 'unbear': ['eburna', 'unbare', 'unbear', 'urbane'], + 'unbearded': ['unbearded', 'unbreaded'], + 'unbeast': ['unbaste', 'unbeast'], + 'unbeavered': ['unbeavered', 'unbereaved'], + 'unbelied': ['unbelied', 'unedible'], + 'unbereaved': ['unbeavered', 'unbereaved'], + 'unbesot': ['subnote', 'subtone', 'unbesot'], + 'unbias': ['anubis', 'unbias'], + 'unbillet': ['bulletin', 'unbillet'], + 'unbilleted': ['tunbellied', 'unbilleted'], + 'unblasted': ['dunstable', 'unblasted', 'unstabled'], + 'unbled': ['bundle', 'unbled'], + 'unboasted': ['eastbound', 'unboasted'], + 'unboat': ['outban', 'unboat'], + 'unboding': ['bounding', 'unboding'], + 'unbog': ['bungo', 'unbog'], + 'unboiled': ['unboiled', 'unilobed'], + 'unboned': ['bounden', 'unboned'], + 'unborder': ['unborder', 'underorb'], + 'unbored': ['beround', 'bounder', 'rebound', 'unbored', 'unorbed', 'unrobed'], + 'unboweled': ['unboweled', 'unelbowed'], + 'unbrace': ['bucrane', 'unbrace'], + 'unbraceleted': ['unbraceleted', 'uncelebrated'], + 'unbraid': ['barundi', 'unbraid'], + 'unbrailed': ['indurable', 'unbrailed', 'unridable'], + 'unbreaded': ['unbearded', 'unbreaded'], + 'unbred': ['bunder', 'burden', 'burned', 'unbred'], + 'unbribed': ['unbribed', 'unribbed'], + 'unbrief': ['unbrief', 'unfiber'], + 'unbriefed': ['unbriefed', 'unfibered'], + 'unbroiled': ['unbroiled', 'underboil'], + 'unbrushed': ['unbrushed', 'underbush'], + 'unbud': ['bundu', 'unbud', 'undub'], + 'unburden': ['unburden', 'unburned'], + 'unburned': ['unburden', 'unburned'], + 'unbuttered': ['unbuttered', 'unrebutted'], + 'unca': ['cuna', 'unca'], + 'uncage': ['cangue', 'uncage'], + 'uncambered': ['uncambered', 'unembraced'], + 'uncamerated': ['uncamerated', 'unmacerated'], + 'uncapable': ['uncapable', 'unpacable'], + 'uncaptious': ['uncaptious', 'usucaption'], + 'uncarted': ['uncarted', 'uncrated', 'underact', 'untraced'], + 'uncartooned': ['uncartooned', 'uncoronated'], + 'uncase': ['uncase', 'usance'], + 'uncask': ['uncask', 'unsack'], + 'uncasked': ['uncasked', 'unsacked'], + 'uncast': ['cantus', 'tuscan', 'uncast'], + 'uncatalogued': ['uncatalogued', 'uncoagulated'], + 'uncate': ['tecuna', 'uncate'], + 'uncaused': ['uncaused', 'unsauced'], + 'uncavalier': ['naviculare', 'uncavalier'], + 'uncelebrated': ['unbraceleted', 'uncelebrated'], + 'uncellar': ['lucernal', 'nucellar', 'uncellar'], + 'uncenter': ['uncenter', 'unrecent'], + 'uncertain': ['encurtain', 'runcinate', 'uncertain'], + 'uncertifiable': ['uncertifiable', 'unrectifiable'], + 'uncertified': ['uncertified', 'unrectified'], + 'unchain': ['chunnia', 'unchain'], + 'unchair': ['chunari', 'unchair'], + 'unchalked': ['unchalked', 'unhackled'], + 'uncharge': ['gunreach', 'uncharge'], + 'uncharm': ['uncharm', 'unmarch'], + 'uncharming': ['uncharming', 'unmarching'], + 'uncharred': ['uncharred', 'underarch'], + 'uncheat': ['uncheat', 'unteach'], + 'uncheating': ['uncheating', 'unteaching'], + 'unchoked': ['unchoked', 'unhocked'], + 'unchoosable': ['chaenolobus', 'unchoosable'], + 'unchosen': ['nonesuch', 'unchosen'], + 'uncial': ['cunila', 'lucian', 'lucina', 'uncial'], + 'unciferous': ['nuciferous', 'unciferous'], + 'unciform': ['nuciform', 'unciform'], + 'uncinate': ['nunciate', 'uncinate'], + 'unclaimed': ['unclaimed', 'undecimal', 'unmedical'], + 'unclay': ['lunacy', 'unclay'], + 'unclead': ['unclead', 'unlaced'], + 'unclear': ['crenula', 'lucarne', 'nuclear', 'unclear'], + 'uncleared': ['uncleared', 'undeclare'], + 'uncledom': ['columned', 'uncledom'], + 'uncleship': ['siphuncle', 'uncleship'], + 'uncloister': ['cornulites', 'uncloister'], + 'unclose': ['counsel', 'unclose'], + 'unclutter': ['truculent', 'unclutter'], + 'unco': ['cuon', 'unco'], + 'uncoagulated': ['uncatalogued', 'uncoagulated'], + 'uncoat': ['toucan', 'tucano', 'uncoat'], + 'uncoated': ['outdance', 'uncoated'], + 'uncoiled': ['nucleoid', 'uncoiled'], + 'uncoin': ['nuncio', 'uncoin'], + 'uncollapsed': ['uncollapsed', 'unscalloped'], + 'uncolored': ['uncolored', 'undercool'], + 'uncomic': ['muconic', 'uncomic'], + 'uncompatible': ['incomputable', 'uncompatible'], + 'uncomplaint': ['uncomplaint', 'uncompliant'], + 'uncomplete': ['couplement', 'uncomplete'], + 'uncompliant': ['uncomplaint', 'uncompliant'], + 'unconcerted': ['unconcerted', 'unconcreted'], + 'unconcreted': ['unconcerted', 'unconcreted'], + 'unconservable': ['unconservable', 'unconversable'], + 'unconstraint': ['noncurantist', 'unconstraint'], + 'uncontrasted': ['counterstand', 'uncontrasted'], + 'unconversable': ['unconservable', 'unconversable'], + 'uncoop': ['coupon', 'uncoop'], + 'uncooped': ['couponed', 'uncooped'], + 'uncope': ['pounce', 'uncope'], + 'uncopied': ['cupidone', 'uncopied'], + 'uncore': ['conure', 'rounce', 'uncore'], + 'uncored': ['crunode', 'uncored'], + 'uncorked': ['uncorked', 'unrocked'], + 'uncoronated': ['uncartooned', 'uncoronated'], + 'uncorrect': ['cocurrent', 'occurrent', 'uncorrect'], + 'uncorrugated': ['counterguard', 'uncorrugated'], + 'uncorseted': ['uncorseted', 'unescorted'], + 'uncostumed': ['uncostumed', 'uncustomed'], + 'uncoursed': ['uncoursed', 'unscoured'], + 'uncouth': ['uncouth', 'untouch'], + 'uncoverable': ['uncoverable', 'unrevocable'], + 'uncradled': ['uncradled', 'underclad'], + 'uncrated': ['uncarted', 'uncrated', 'underact', 'untraced'], + 'uncreased': ['uncreased', 'undercase'], + 'uncreatable': ['uncreatable', 'untraceable'], + 'uncreatableness': ['uncreatableness', 'untraceableness'], + 'uncreation': ['enunciator', 'uncreation'], + 'uncreative': ['uncreative', 'unreactive'], + 'uncredited': ['uncredited', 'undirected'], + 'uncrest': ['encrust', 'uncrest'], + 'uncrested': ['uncrested', 'undersect'], + 'uncried': ['inducer', 'uncried'], + 'uncrooked': ['uncrooked', 'undercook'], + 'uncrude': ['uncrude', 'uncured'], + 'unctional': ['continual', 'inoculant', 'unctional'], + 'unctioneer': ['recontinue', 'unctioneer'], + 'uncured': ['uncrude', 'uncured'], + 'uncustomed': ['uncostumed', 'uncustomed'], + 'uncuth': ['tuchun', 'uncuth'], + 'undam': ['maund', 'munda', 'numda', 'undam', 'unmad'], + 'undangered': ['undangered', 'underanged', 'ungardened'], + 'undarken': ['undarken', 'unranked'], + 'undashed': ['undashed', 'unshaded'], + 'undate': ['nudate', 'undate'], + 'unde': ['dune', 'nude', 'unde'], + 'undean': ['duenna', 'undean'], + 'undear': ['endura', 'neurad', 'undear', 'unread'], + 'undeceiver': ['undeceiver', 'unreceived'], + 'undecimal': ['unclaimed', 'undecimal', 'unmedical'], + 'undeclare': ['uncleared', 'undeclare'], + 'undecolic': ['coinclude', 'undecolic'], + 'undecorated': ['undecorated', 'undercoated'], + 'undefiled': ['undefiled', 'unfielded'], + 'undeified': ['undeified', 'unedified'], + 'undelible': ['undelible', 'unlibeled'], + 'undelight': ['undelight', 'unlighted'], + 'undelude': ['undelude', 'uneluded'], + 'undeluding': ['undeluding', 'unindulged'], + 'undemanded': ['undemanded', 'unmaddened'], + 'unden': ['dunne', 'unden'], + 'undeparted': ['dunderpate', 'undeparted'], + 'undepraved': ['undepraved', 'unpervaded'], + 'under': ['runed', 'under', 'unred'], + 'underact': ['uncarted', 'uncrated', 'underact', 'untraced'], + 'underacted': ['underacted', 'unredacted'], + 'underaction': ['denunciator', 'underaction'], + 'underage': ['dungaree', 'guardeen', 'unagreed', 'underage', 'ungeared'], + 'underaid': ['underaid', 'unraided'], + 'underaim': ['unadmire', 'underaim'], + 'underanged': ['undangered', 'underanged', 'ungardened'], + 'underarch': ['uncharred', 'underarch'], + 'underarm': ['underarm', 'unmarred'], + 'underbake': ['underbake', 'underbeak'], + 'underbeak': ['underbake', 'underbeak'], + 'underbeat': ['eburnated', 'underbeat', 'unrebated'], + 'underbit': ['turbined', 'underbit'], + 'underboil': ['unbroiled', 'underboil'], + 'underbreathing': ['thunderbearing', 'underbreathing'], + 'underbrush': ['underbrush', 'undershrub'], + 'underbush': ['unbrushed', 'underbush'], + 'undercase': ['uncreased', 'undercase'], + 'underchap': ['underchap', 'unparched'], + 'underclad': ['uncradled', 'underclad'], + 'undercoat': ['cornuated', 'undercoat'], + 'undercoated': ['undecorated', 'undercoated'], + 'undercook': ['uncrooked', 'undercook'], + 'undercool': ['uncolored', 'undercool'], + 'undercut': ['undercut', 'unreduct'], + 'underdead': ['underdead', 'undreaded'], + 'underdig': ['underdig', 'ungirded', 'unridged'], + 'underdive': ['underdive', 'underived'], + 'underdo': ['redound', 'rounded', 'underdo'], + 'underdoer': ['underdoer', 'unordered'], + 'underdog': ['grounded', 'underdog', 'undergod'], + 'underdown': ['underdown', 'undrowned'], + 'underdrag': ['underdrag', 'undergrad'], + 'underdraw': ['underdraw', 'underward'], + 'undereat': ['denature', 'undereat'], + 'underer': ['endurer', 'underer'], + 'underfiend': ['underfiend', 'unfriended'], + 'underfill': ['underfill', 'unfrilled'], + 'underfire': ['underfire', 'unferried'], + 'underflow': ['underflow', 'wonderful'], + 'underfur': ['underfur', 'unfurred'], + 'undergo': ['guerdon', 'undergo', 'ungored'], + 'undergod': ['grounded', 'underdog', 'undergod'], + 'undergoer': ['guerdoner', 'reundergo', 'undergoer', 'undergore'], + 'undergore': ['guerdoner', 'reundergo', 'undergoer', 'undergore'], + 'undergown': ['undergown', 'unwronged'], + 'undergrad': ['underdrag', 'undergrad'], + 'undergrade': ['undergrade', 'unregarded'], + 'underheat': ['underheat', 'unearthed'], + 'underhonest': ['underhonest', 'unshortened'], + 'underhorse': ['underhorse', 'undershore'], + 'underived': ['underdive', 'underived'], + 'underkind': ['underkind', 'unkindred'], + 'underlap': ['pendular', 'underlap', 'uplander'], + 'underleaf': ['underleaf', 'unfederal'], + 'underlease': ['underlease', 'unreleased'], + 'underlegate': ['underlegate', 'unrelegated'], + 'underlid': ['underlid', 'unriddle'], + 'underlive': ['underlive', 'unreviled'], + 'underlying': ['enduringly', 'underlying'], + 'undermade': ['undermade', 'undreamed'], + 'undermaid': ['unadmired', 'undermaid'], + 'undermaker': ['undermaker', 'unremarked'], + 'undermaster': ['undermaster', 'understream'], + 'undermeal': ['denumeral', 'undermeal', 'unrealmed'], + 'undermine': ['undermine', 'unermined'], + 'undermost': ['undermost', 'unstormed'], + 'undermotion': ['undermotion', 'unmonitored'], + 'undern': ['dunner', 'undern'], + 'underneath': ['unadherent', 'underneath', 'underthane'], + 'undernote': ['undernote', 'undertone'], + 'undernoted': ['undernoted', 'undertoned'], + 'underntide': ['indentured', 'underntide'], + 'underorb': ['unborder', 'underorb'], + 'underpay': ['underpay', 'unprayed'], + 'underpeer': ['perendure', 'underpeer'], + 'underpick': ['underpick', 'unpricked'], + 'underpier': ['underpier', 'underripe'], + 'underpile': ['underpile', 'unreplied'], + 'underpose': ['underpose', 'unreposed'], + 'underpuke': ['underpuke', 'unperuked'], + 'underream': ['maunderer', 'underream'], + 'underripe': ['underpier', 'underripe'], + 'underrobe': ['rebounder', 'underrobe'], + 'undersap': ['undersap', 'unparsed', 'unrasped', 'unspared', 'unspread'], + 'undersea': ['undersea', 'unerased', 'unseared'], + 'underseam': ['underseam', 'unsmeared'], + 'undersect': ['uncrested', 'undersect'], + 'underserve': ['underserve', + 'underverse', + 'undeserver', + 'unreserved', + 'unreversed'], + 'underset': ['sederunt', 'underset', 'undesert', 'unrested'], + 'undershapen': ['undershapen', 'unsharpened'], + 'undershore': ['underhorse', 'undershore'], + 'undershrub': ['underbrush', 'undershrub'], + 'underside': ['underside', 'undesired'], + 'undersoil': ['undersoil', 'unsoldier'], + 'undersow': ['sewround', 'undersow'], + 'underspar': ['underspar', 'unsparred'], + 'understain': ['understain', 'unstrained'], + 'understand': ['understand', 'unstranded'], + 'understream': ['undermaster', 'understream'], + 'underthane': ['unadherent', 'underneath', 'underthane'], + 'underthing': ['thundering', 'underthing'], + 'undertide': ['durdenite', 'undertide'], + 'undertime': ['undertime', 'unmerited'], + 'undertimed': ['demiturned', 'undertimed'], + 'undertitle': ['undertitle', 'unlittered'], + 'undertone': ['undernote', 'undertone'], + 'undertoned': ['undernoted', 'undertoned'], + 'undertow': ['undertow', 'untrowed'], + 'undertread': ['undertread', 'unretarded'], + 'undertutor': ['undertutor', 'untortured'], + 'underverse': ['underserve', + 'underverse', + 'undeserver', + 'unreserved', + 'unreversed'], + 'underwage': ['underwage', 'unwagered'], + 'underward': ['underdraw', 'underward'], + 'underwarp': ['underwarp', 'underwrap'], + 'underwave': ['underwave', 'unwavered'], + 'underwrap': ['underwarp', 'underwrap'], + 'undesert': ['sederunt', 'underset', 'undesert', 'unrested'], + 'undeserve': ['undeserve', 'unsevered'], + 'undeserver': ['underserve', + 'underverse', + 'undeserver', + 'unreserved', + 'unreversed'], + 'undesign': ['undesign', 'unsigned', 'unsinged'], + 'undesired': ['underside', 'undesired'], + 'undeviated': ['denudative', 'undeviated'], + 'undieted': ['undieted', 'unedited'], + 'undig': ['gundi', 'undig'], + 'undirect': ['undirect', 'untriced'], + 'undirected': ['uncredited', 'undirected'], + 'undiscerned': ['undiscerned', 'unrescinded'], + 'undiscretion': ['discontinuer', 'undiscretion'], + 'undistress': ['sturdiness', 'undistress'], + 'undiverse': ['undiverse', 'unrevised'], + 'undog': ['undog', 'ungod'], + 'undrab': ['durban', 'undrab'], + 'undrag': ['durgan', 'undrag'], + 'undrape': ['undrape', 'unpared', 'unraped'], + 'undreaded': ['underdead', 'undreaded'], + 'undreamed': ['undermade', 'undreamed'], + 'undrowned': ['underdown', 'undrowned'], + 'undrugged': ['undrugged', 'ungrudged'], + 'undryable': ['endurably', 'undryable'], + 'undub': ['bundu', 'unbud', 'undub'], + 'undumped': ['pudendum', 'undumped'], + 'undy': ['duny', 'undy'], + 'uneager': ['geneura', 'uneager'], + 'unearned': ['unearned', 'unneared'], + 'unearnest': ['unearnest', 'uneastern'], + 'unearth': ['haunter', 'nauther', 'unearth', 'unheart', 'urethan'], + 'unearthed': ['underheat', 'unearthed'], + 'unearthly': ['unearthly', 'urethylan'], + 'uneastern': ['unearnest', 'uneastern'], + 'uneath': ['uneath', 'unhate'], + 'unebriate': ['beraunite', 'unebriate'], + 'unedge': ['dengue', 'unedge'], + 'unedible': ['unbelied', 'unedible'], + 'unedified': ['undeified', 'unedified'], + 'unedited': ['undieted', 'unedited'], + 'unelapsed': ['unelapsed', 'unpleased'], + 'unelated': ['antelude', 'unelated'], + 'unelbowed': ['unboweled', 'unelbowed'], + 'unelidible': ['ineludible', 'unelidible'], + 'uneluded': ['undelude', 'uneluded'], + 'unembased': ['sunbeamed', 'unembased'], + 'unembraced': ['uncambered', 'unembraced'], + 'unenabled': ['unenabled', 'unendable'], + 'unencored': ['denouncer', 'unencored'], + 'unendable': ['unenabled', 'unendable'], + 'unending': ['unending', 'unginned'], + 'unenervated': ['unenervated', 'unvenerated'], + 'unenlisted': ['unenlisted', 'unlistened', 'untinseled'], + 'unenterprised': ['superintender', 'unenterprised'], + 'unenviable': ['unenviable', 'unveniable'], + 'unenvied': ['unenvied', 'unveined'], + 'unequitable': ['unequitable', 'unquietable'], + 'unerased': ['undersea', 'unerased', 'unseared'], + 'unermined': ['undermine', 'unermined'], + 'unerratic': ['recurtain', 'unerratic'], + 'unerupted': ['unerupted', 'unreputed'], + 'unescorted': ['uncorseted', 'unescorted'], + 'unevil': ['unevil', 'unlive', 'unveil'], + 'unexactly': ['exultancy', 'unexactly'], + 'unexceptable': ['unexceptable', 'unexpectable'], + 'unexcepted': ['unexcepted', 'unexpected'], + 'unexcepting': ['unexcepting', 'unexpecting'], + 'unexpectable': ['unexceptable', 'unexpectable'], + 'unexpected': ['unexcepted', 'unexpected'], + 'unexpecting': ['unexcepting', 'unexpecting'], + 'unfabled': ['fundable', 'unfabled'], + 'unfaceted': ['fecundate', 'unfaceted'], + 'unfactional': ['afunctional', 'unfactional'], + 'unfactored': ['fecundator', 'unfactored'], + 'unfainting': ['antifungin', 'unfainting'], + 'unfallible': ['unfallible', 'unfillable'], + 'unfar': ['furan', 'unfar'], + 'unfarmed': ['unfarmed', 'unframed'], + 'unfederal': ['underleaf', 'unfederal'], + 'unfeeding': ['unfeeding', 'unfeigned'], + 'unfeeling': ['unfeeling', 'unfleeing'], + 'unfeigned': ['unfeeding', 'unfeigned'], + 'unfelt': ['fluent', 'netful', 'unfelt', 'unleft'], + 'unfelted': ['defluent', 'unfelted'], + 'unferried': ['underfire', 'unferried'], + 'unfiber': ['unbrief', 'unfiber'], + 'unfibered': ['unbriefed', 'unfibered'], + 'unfielded': ['undefiled', 'unfielded'], + 'unfiend': ['unfiend', 'unfined'], + 'unfiery': ['reunify', 'unfiery'], + 'unfillable': ['unfallible', 'unfillable'], + 'unfined': ['unfiend', 'unfined'], + 'unfired': ['unfired', 'unfried'], + 'unflag': ['fungal', 'unflag'], + 'unflat': ['flaunt', 'unflat'], + 'unfleeing': ['unfeeling', 'unfleeing'], + 'unfloured': ['unfloured', 'unfoldure'], + 'unfolder': ['flounder', 'reunfold', 'unfolder'], + 'unfolding': ['foundling', 'unfolding'], + 'unfoldure': ['unfloured', 'unfoldure'], + 'unforest': ['furstone', 'unforest'], + 'unforested': ['unforested', 'unfostered'], + 'unformality': ['fulminatory', 'unformality'], + 'unforward': ['unforward', 'unfroward'], + 'unfostered': ['unforested', 'unfostered'], + 'unfrail': ['rainful', 'unfrail'], + 'unframed': ['unfarmed', 'unframed'], + 'unfret': ['turfen', 'unfret'], + 'unfriable': ['funebrial', 'unfriable'], + 'unfried': ['unfired', 'unfried'], + 'unfriended': ['underfiend', 'unfriended'], + 'unfriending': ['unfriending', 'uninfringed'], + 'unfrilled': ['underfill', 'unfrilled'], + 'unfroward': ['unforward', 'unfroward'], + 'unfurl': ['unfurl', 'urnful'], + 'unfurred': ['underfur', 'unfurred'], + 'ungaite': ['ungaite', 'unitage'], + 'unganged': ['unganged', 'unnagged'], + 'ungardened': ['undangered', 'underanged', 'ungardened'], + 'ungarnish': ['ungarnish', 'unsharing'], + 'ungear': ['nauger', 'raunge', 'ungear'], + 'ungeared': ['dungaree', 'guardeen', 'unagreed', 'underage', 'ungeared'], + 'ungelt': ['englut', 'gluten', 'ungelt'], + 'ungenerable': ['ungenerable', 'ungreenable'], + 'unget': ['tengu', 'unget'], + 'ungilded': ['deluding', 'ungilded'], + 'ungill': ['ulling', 'ungill'], + 'ungilt': ['glutin', 'luting', 'ungilt'], + 'unginned': ['unending', 'unginned'], + 'ungird': ['during', 'ungird'], + 'ungirded': ['underdig', 'ungirded', 'unridged'], + 'ungirdle': ['indulger', 'ungirdle'], + 'ungirt': ['ungirt', 'untrig'], + 'ungirth': ['hurting', 'ungirth', 'unright'], + 'ungirthed': ['ungirthed', 'unrighted'], + 'unglad': ['gandul', 'unglad'], + 'unglued': ['unglued', 'unguled'], + 'ungod': ['undog', 'ungod'], + 'ungold': ['dungol', 'ungold'], + 'ungone': ['guenon', 'ungone'], + 'ungored': ['guerdon', 'undergo', 'ungored'], + 'ungorge': ['gurgeon', 'ungorge'], + 'ungot': ['tungo', 'ungot'], + 'ungothic': ['touching', 'ungothic'], + 'ungraphic': ['ungraphic', 'uparching'], + 'ungreenable': ['ungenerable', 'ungreenable'], + 'ungrieved': ['gerundive', 'ungrieved'], + 'ungroined': ['ungroined', 'unignored'], + 'ungrudged': ['undrugged', 'ungrudged'], + 'ungual': ['ungual', 'ungula'], + 'ungueal': ['ungueal', 'ungulae'], + 'ungula': ['ungual', 'ungula'], + 'ungulae': ['ungueal', 'ungulae'], + 'unguled': ['unglued', 'unguled'], + 'ungulp': ['ungulp', 'unplug'], + 'unhabit': ['bhutani', 'unhabit'], + 'unhackled': ['unchalked', 'unhackled'], + 'unhairer': ['rhineura', 'unhairer'], + 'unhalsed': ['unhalsed', 'unlashed', 'unshaled'], + 'unhalted': ['unhalted', 'unlathed'], + 'unhalter': ['lutheran', 'unhalter'], + 'unhaltered': ['unhaltered', 'unlathered'], + 'unhamper': ['prehuman', 'unhamper'], + 'unharbored': ['unabhorred', 'unharbored'], + 'unhasped': ['unhasped', 'unphased', 'unshaped'], + 'unhat': ['ahunt', 'haunt', 'thuan', 'unhat'], + 'unhate': ['uneath', 'unhate'], + 'unhatingly': ['hauntingly', 'unhatingly'], + 'unhayed': ['unhayed', 'unheady'], + 'unheady': ['unhayed', 'unheady'], + 'unhearsed': ['unhearsed', 'unsheared'], + 'unheart': ['haunter', 'nauther', 'unearth', 'unheart', 'urethan'], + 'unhid': ['hindu', 'hundi', 'unhid'], + 'unhistoric': ['trichinous', 'unhistoric'], + 'unhittable': ['unhittable', 'untithable'], + 'unhoarded': ['roundhead', 'unhoarded'], + 'unhocked': ['unchoked', 'unhocked'], + 'unhoisted': ['hudsonite', 'unhoisted'], + 'unhorse': ['unhorse', 'unshore'], + 'unhose': ['unhose', 'unshoe'], + 'unhosed': ['unhosed', 'unshoed'], + 'unhurt': ['unhurt', 'unruth'], + 'uniat': ['uinta', 'uniat'], + 'uniate': ['auntie', 'uniate'], + 'unible': ['nubile', 'unible'], + 'uniced': ['induce', 'uniced'], + 'unicentral': ['incruental', 'unicentral'], + 'unideal': ['aliunde', 'unideal'], + 'unidentified': ['indefinitude', 'unidentified'], + 'unidly': ['unidly', 'yildun'], + 'unie': ['niue', 'unie'], + 'unifilar': ['friulian', 'unifilar'], + 'uniflorate': ['antifouler', 'fluorinate', 'uniflorate'], + 'unigenous': ['ingenuous', 'unigenous'], + 'unignored': ['ungroined', 'unignored'], + 'unilobar': ['orbulina', 'unilobar'], + 'unilobed': ['unboiled', 'unilobed'], + 'unimedial': ['aluminide', 'unimedial'], + 'unimpair': ['manipuri', 'unimpair'], + 'unimparted': ['diparentum', 'unimparted'], + 'unimportance': ['importunance', 'unimportance'], + 'unimpressible': ['unimpressible', 'unpermissible'], + 'unimpressive': ['unimpressive', 'unpermissive'], + 'unindented': ['unindented', 'unintended'], + 'unindulged': ['undeluding', 'unindulged'], + 'uninervate': ['aventurine', 'uninervate'], + 'uninfringed': ['unfriending', 'uninfringed'], + 'uningested': ['uningested', 'unsigneted'], + 'uninn': ['nunni', 'uninn'], + 'uninnate': ['eutannin', 'uninnate'], + 'uninodal': ['annuloid', 'uninodal'], + 'unintended': ['unindented', 'unintended'], + 'unintoned': ['nonunited', 'unintoned'], + 'uninured': ['uninured', 'unruined'], + 'unionist': ['inustion', 'unionist'], + 'unipersonal': ['spinoneural', 'unipersonal'], + 'unipod': ['dupion', 'unipod'], + 'uniradial': ['nidularia', 'uniradial'], + 'unireme': ['erineum', 'unireme'], + 'uniserrate': ['arseniuret', 'uniserrate'], + 'unison': ['nonius', 'unison'], + 'unitage': ['ungaite', 'unitage'], + 'unital': ['inlaut', 'unital'], + 'unite': ['intue', 'unite', 'untie'], + 'united': ['dunite', 'united', 'untied'], + 'uniter': ['runite', 'triune', 'uniter', 'untire'], + 'unitiveness': ['unitiveness', 'unsensitive'], + 'unitrope': ['eruption', 'unitrope'], + 'univied': ['univied', 'viduine'], + 'unket': ['knute', 'unket'], + 'unkilned': ['unkilned', 'unlinked'], + 'unkin': ['nunki', 'unkin'], + 'unkindred': ['underkind', 'unkindred'], + 'unlabiate': ['laubanite', 'unlabiate'], + 'unlabored': ['burdalone', 'unlabored'], + 'unlace': ['auncel', 'cuneal', 'lacune', 'launce', 'unlace'], + 'unlaced': ['unclead', 'unlaced'], + 'unlade': ['unlade', 'unlead'], + 'unlaid': ['dualin', 'ludian', 'unlaid'], + 'unlame': ['manuel', 'unlame'], + 'unlapped': ['unlapped', 'unpalped'], + 'unlarge': ['granule', 'unlarge', 'unregal'], + 'unlashed': ['unhalsed', 'unlashed', 'unshaled'], + 'unlasting': ['unlasting', 'unslating'], + 'unlatch': ['tulchan', 'unlatch'], + 'unlathed': ['unhalted', 'unlathed'], + 'unlathered': ['unhaltered', 'unlathered'], + 'unlay': ['unlay', 'yulan'], + 'unlead': ['unlade', 'unlead'], + 'unleasable': ['unleasable', 'unsealable'], + 'unleased': ['unleased', 'unsealed'], + 'unleash': ['hulsean', 'unleash'], + 'unled': ['lendu', 'unled'], + 'unleft': ['fluent', 'netful', 'unfelt', 'unleft'], + 'unlent': ['nunlet', 'tunnel', 'unlent'], + 'unlevied': ['unlevied', 'unveiled'], + 'unlibeled': ['undelible', 'unlibeled'], + 'unliberal': ['brunellia', 'unliberal'], + 'unlicensed': ['unlicensed', 'unsilenced'], + 'unlighted': ['undelight', 'unlighted'], + 'unliken': ['nunlike', 'unliken'], + 'unlime': ['lumine', 'unlime'], + 'unlinked': ['unkilned', 'unlinked'], + 'unlist': ['insult', 'sunlit', 'unlist', 'unslit'], + 'unlistened': ['unenlisted', 'unlistened', 'untinseled'], + 'unlit': ['unlit', 'until'], + 'unliteral': ['tellurian', 'unliteral'], + 'unlittered': ['undertitle', 'unlittered'], + 'unlive': ['unevil', 'unlive', 'unveil'], + 'unloaded': ['duodenal', 'unloaded'], + 'unloaden': ['unloaden', 'unloaned'], + 'unloader': ['unloader', 'urodelan'], + 'unloaned': ['unloaden', 'unloaned'], + 'unlodge': ['unlodge', 'unogled'], + 'unlogic': ['gulonic', 'unlogic'], + 'unlooped': ['unlooped', 'unpooled'], + 'unlooted': ['unlooted', 'untooled'], + 'unlost': ['unlost', 'unslot'], + 'unlowered': ['unlowered', 'unroweled'], + 'unlucid': ['nuculid', 'unlucid'], + 'unlumped': ['pendulum', 'unlumped', 'unplumed'], + 'unlured': ['unlured', 'unruled'], + 'unlyrical': ['runically', 'unlyrical'], + 'unmacerated': ['uncamerated', 'unmacerated'], + 'unmad': ['maund', 'munda', 'numda', 'undam', 'unmad'], + 'unmadded': ['addendum', 'unmadded'], + 'unmaddened': ['undemanded', 'unmaddened'], + 'unmaid': ['numida', 'unmaid'], + 'unmail': ['alumni', 'unmail'], + 'unmailed': ['adlumine', 'unmailed'], + 'unmaned': ['mundane', 'unamend', 'unmaned', 'unnamed'], + 'unmantle': ['unmantle', 'unmental'], + 'unmarch': ['uncharm', 'unmarch'], + 'unmarching': ['uncharming', 'unmarching'], + 'unmarginal': ['unalarming', 'unmarginal'], + 'unmarred': ['underarm', 'unmarred'], + 'unmashed': ['unmashed', 'unshamed'], + 'unmate': ['unmate', 'untame', 'unteam'], + 'unmated': ['unmated', 'untamed'], + 'unmaterial': ['manualiter', 'unmaterial'], + 'unmeated': ['unmeated', 'unteamed'], + 'unmedical': ['unclaimed', 'undecimal', 'unmedical'], + 'unmeet': ['unmeet', 'unteem'], + 'unmemoired': ['unmemoired', 'unmemoried'], + 'unmemoried': ['unmemoired', 'unmemoried'], + 'unmental': ['unmantle', 'unmental'], + 'unmerged': ['gerendum', 'unmerged'], + 'unmerited': ['undertime', 'unmerited'], + 'unmettle': ['temulent', 'unmettle'], + 'unminable': ['nelumbian', 'unminable'], + 'unmined': ['minuend', 'unmined'], + 'unminted': ['indument', 'unminted'], + 'unmisled': ['muslined', 'unmisled', 'unsmiled'], + 'unmiter': ['minuter', 'unmiter'], + 'unmodest': ['mudstone', 'unmodest'], + 'unmodish': ['muishond', 'unmodish'], + 'unmomentary': ['monumentary', 'unmomentary'], + 'unmonitored': ['undermotion', 'unmonitored'], + 'unmorbid': ['moribund', 'unmorbid'], + 'unmorose': ['enormous', 'unmorose'], + 'unmortised': ['semirotund', 'unmortised'], + 'unmotived': ['unmotived', 'unvomited'], + 'unmystical': ['stimulancy', 'unmystical'], + 'unnagged': ['unganged', 'unnagged'], + 'unnail': ['alnuin', 'unnail'], + 'unnameability': ['unamenability', 'unnameability'], + 'unnameable': ['unamenable', 'unnameable'], + 'unnameableness': ['unamenableness', 'unnameableness'], + 'unnameably': ['unamenably', 'unnameably'], + 'unnamed': ['mundane', 'unamend', 'unmaned', 'unnamed'], + 'unnational': ['annulation', 'unnational'], + 'unnative': ['unnative', 'venutian'], + 'unneared': ['unearned', 'unneared'], + 'unnest': ['unnest', 'unsent'], + 'unnetted': ['unnetted', 'untented'], + 'unnose': ['nonuse', 'unnose'], + 'unnoted': ['unnoted', 'untoned'], + 'unnoticed': ['continued', 'unnoticed'], + 'unoared': ['rondeau', 'unoared'], + 'unogled': ['unlodge', 'unogled'], + 'unomitted': ['dumontite', 'unomitted'], + 'unoperatic': ['precaution', 'unoperatic'], + 'unorbed': ['beround', 'bounder', 'rebound', 'unbored', 'unorbed', 'unrobed'], + 'unorder': ['rondure', 'rounder', 'unorder'], + 'unordered': ['underdoer', 'unordered'], + 'unoriented': ['nonerudite', 'unoriented'], + 'unown': ['unown', 'unwon'], + 'unowned': ['enwound', 'unowned'], + 'unpacable': ['uncapable', 'unpacable'], + 'unpacker': ['reunpack', 'unpacker'], + 'unpaired': ['unpaired', 'unrepaid'], + 'unpale': ['unpale', 'uplane'], + 'unpalped': ['unlapped', 'unpalped'], + 'unpanel': ['unpanel', 'unpenal'], + 'unparceled': ['unparceled', 'unreplaced'], + 'unparched': ['underchap', 'unparched'], + 'unpared': ['undrape', 'unpared', 'unraped'], + 'unparsed': ['undersap', 'unparsed', 'unrasped', 'unspared', 'unspread'], + 'unparted': ['depurant', 'unparted'], + 'unpartial': ['tarpaulin', 'unpartial'], + 'unpenal': ['unpanel', 'unpenal'], + 'unpenetrable': ['unpenetrable', 'unrepentable'], + 'unpent': ['punnet', 'unpent'], + 'unperch': ['puncher', 'unperch'], + 'unpercolated': ['counterpaled', 'counterplead', 'unpercolated'], + 'unpermissible': ['unimpressible', 'unpermissible'], + 'unpermissive': ['unimpressive', 'unpermissive'], + 'unperuked': ['underpuke', 'unperuked'], + 'unpervaded': ['undepraved', 'unpervaded'], + 'unpetal': ['plutean', 'unpetal', 'unpleat'], + 'unpharasaic': ['parasuchian', 'unpharasaic'], + 'unphased': ['unhasped', 'unphased', 'unshaped'], + 'unphrased': ['unphrased', 'unsharped'], + 'unpickled': ['dunpickle', 'unpickled'], + 'unpierced': ['preinduce', 'unpierced'], + 'unpile': ['lupine', 'unpile', 'upline'], + 'unpiled': ['unpiled', 'unplied'], + 'unplace': ['cleanup', 'unplace'], + 'unplain': ['pinnula', 'unplain'], + 'unplait': ['nuptial', 'unplait'], + 'unplanted': ['pendulant', 'unplanted'], + 'unplat': ['puntal', 'unplat'], + 'unpleased': ['unelapsed', 'unpleased'], + 'unpleat': ['plutean', 'unpetal', 'unpleat'], + 'unpleated': ['pendulate', 'unpleated'], + 'unplied': ['unpiled', 'unplied'], + 'unplug': ['ungulp', 'unplug'], + 'unplumed': ['pendulum', 'unlumped', 'unplumed'], + 'unpoled': ['duplone', 'unpoled'], + 'unpolished': ['disulphone', 'unpolished'], + 'unpolitic': ['punctilio', 'unpolitic'], + 'unpooled': ['unlooped', 'unpooled'], + 'unposted': ['outspend', 'unposted'], + 'unpot': ['punto', 'unpot', 'untop'], + 'unprayed': ['underpay', 'unprayed'], + 'unprelatic': ['periculant', 'unprelatic'], + 'unpressed': ['resuspend', 'suspender', 'unpressed'], + 'unpricked': ['underpick', 'unpricked'], + 'unprint': ['turnpin', 'unprint'], + 'unprosaic': ['inocarpus', 'unprosaic'], + 'unproselyted': ['pseudelytron', 'unproselyted'], + 'unproud': ['roundup', 'unproud'], + 'unpursued': ['unpursued', 'unusurped'], + 'unpursuing': ['unpursuing', 'unusurping'], + 'unquietable': ['unequitable', 'unquietable'], + 'unrabbeted': ['beturbaned', 'unrabbeted'], + 'unraced': ['durance', 'redunca', 'unraced'], + 'unraided': ['underaid', 'unraided'], + 'unraised': ['denarius', 'desaurin', 'unraised'], + 'unram': ['muran', 'ruman', 'unarm', 'unram', 'urman'], + 'unranked': ['undarken', 'unranked'], + 'unraped': ['undrape', 'unpared', 'unraped'], + 'unrasped': ['undersap', 'unparsed', 'unrasped', 'unspared', 'unspread'], + 'unrated': ['daunter', 'unarted', 'unrated', 'untread'], + 'unravel': ['unravel', 'venular'], + 'unray': ['anury', 'unary', 'unray'], + 'unrayed': ['unrayed', 'unready'], + 'unreactive': ['uncreative', 'unreactive'], + 'unread': ['endura', 'neurad', 'undear', 'unread'], + 'unready': ['unrayed', 'unready'], + 'unreal': ['lunare', 'neural', 'ulnare', 'unreal'], + 'unrealism': ['semilunar', 'unrealism'], + 'unrealist': ['neuralist', 'ulsterian', 'unrealist'], + 'unrealmed': ['denumeral', 'undermeal', 'unrealmed'], + 'unrebated': ['eburnated', 'underbeat', 'unrebated'], + 'unrebutted': ['unbuttered', 'unrebutted'], + 'unreceived': ['undeceiver', 'unreceived'], + 'unrecent': ['uncenter', 'unrecent'], + 'unrecited': ['centuried', 'unrecited'], + 'unrectifiable': ['uncertifiable', 'unrectifiable'], + 'unrectified': ['uncertified', 'unrectified'], + 'unred': ['runed', 'under', 'unred'], + 'unredacted': ['underacted', 'unredacted'], + 'unreduct': ['undercut', 'unreduct'], + 'unreeve': ['revenue', 'unreeve'], + 'unreeving': ['unreeving', 'unveering'], + 'unregal': ['granule', 'unlarge', 'unregal'], + 'unregard': ['grandeur', 'unregard'], + 'unregarded': ['undergrade', 'unregarded'], + 'unrein': ['enruin', 'neurin', 'unrein'], + 'unreinstated': ['unreinstated', 'unstraitened'], + 'unrelated': ['unaltered', 'unrelated'], + 'unrelating': ['unaltering', 'unrelating'], + 'unreleased': ['underlease', 'unreleased'], + 'unrelegated': ['underlegate', 'unrelegated'], + 'unremarked': ['undermaker', 'unremarked'], + 'unrent': ['runnet', 'tunner', 'unrent'], + 'unrented': ['unrented', 'untender'], + 'unrepaid': ['unpaired', 'unrepaid'], + 'unrepentable': ['unpenetrable', 'unrepentable'], + 'unrepined': ['unrepined', 'unripened'], + 'unrepining': ['unrepining', 'unripening'], + 'unreplaced': ['unparceled', 'unreplaced'], + 'unreplied': ['underpile', 'unreplied'], + 'unreposed': ['underpose', 'unreposed'], + 'unreputed': ['unerupted', 'unreputed'], + 'unrescinded': ['undiscerned', 'unrescinded'], + 'unrescued': ['unrescued', 'unsecured'], + 'unreserved': ['underserve', + 'underverse', + 'undeserver', + 'unreserved', + 'unreversed'], + 'unresisted': ['unresisted', 'unsistered'], + 'unresolve': ['nervulose', 'unresolve', 'vulnerose'], + 'unrespect': ['unrespect', 'unscepter', 'unsceptre'], + 'unrespected': ['unrespected', 'unsceptered'], + 'unrested': ['sederunt', 'underset', 'undesert', 'unrested'], + 'unresting': ['insurgent', 'unresting'], + 'unretarded': ['undertread', 'unretarded'], + 'unreticent': ['entincture', 'unreticent'], + 'unretired': ['reintrude', 'unretired'], + 'unrevered': ['enverdure', 'unrevered'], + 'unreversed': ['underserve', + 'underverse', + 'undeserver', + 'unreserved', + 'unreversed'], + 'unreviled': ['underlive', 'unreviled'], + 'unrevised': ['undiverse', 'unrevised'], + 'unrevocable': ['uncoverable', 'unrevocable'], + 'unribbed': ['unbribed', 'unribbed'], + 'unrich': ['unrich', 'urchin'], + 'unrid': ['rundi', 'unrid'], + 'unridable': ['indurable', 'unbrailed', 'unridable'], + 'unriddle': ['underlid', 'unriddle'], + 'unride': ['diurne', 'inured', 'ruined', 'unride'], + 'unridged': ['underdig', 'ungirded', 'unridged'], + 'unrig': ['irgun', 'ruing', 'unrig'], + 'unright': ['hurting', 'ungirth', 'unright'], + 'unrighted': ['ungirthed', 'unrighted'], + 'unring': ['unring', 'urning'], + 'unringed': ['enduring', 'unringed'], + 'unripe': ['purine', 'unripe', 'uprein'], + 'unripely': ['pyruline', 'unripely'], + 'unripened': ['unrepined', 'unripened'], + 'unripening': ['unrepining', 'unripening'], + 'unroaded': ['unadored', 'unroaded'], + 'unrobed': ['beround', 'bounder', 'rebound', 'unbored', 'unorbed', 'unrobed'], + 'unrocked': ['uncorked', 'unrocked'], + 'unroot': ['notour', 'unroot'], + 'unroped': ['pounder', 'repound', 'unroped'], + 'unrosed': ['resound', 'sounder', 'unrosed'], + 'unrostrated': ['tetrandrous', 'unrostrated'], + 'unrotated': ['rotundate', 'unrotated'], + 'unroted': ['tendour', 'unroted'], + 'unroused': ['unroused', 'unsoured'], + 'unrouted': ['unrouted', 'untoured'], + 'unrowed': ['rewound', 'unrowed', 'wounder'], + 'unroweled': ['unlowered', 'unroweled'], + 'unroyalist': ['unroyalist', 'unsolitary'], + 'unruined': ['uninured', 'unruined'], + 'unruled': ['unlured', 'unruled'], + 'unrun': ['unrun', 'unurn'], + 'unruth': ['unhurt', 'unruth'], + 'unsack': ['uncask', 'unsack'], + 'unsacked': ['uncasked', 'unsacked'], + 'unsacred': ['unsacred', 'unscared'], + 'unsad': ['sudan', 'unsad'], + 'unsadden': ['unsadden', 'unsanded'], + 'unsage': ['gnaeus', 'unsage'], + 'unsaid': ['sudani', 'unsaid'], + 'unsailed': ['unaisled', 'unsailed'], + 'unsaint': ['antisun', 'unsaint', 'unsatin', 'unstain'], + 'unsainted': ['unsainted', 'unstained'], + 'unsalt': ['sultan', 'unsalt'], + 'unsalted': ['unsalted', 'unslated', 'unstaled'], + 'unsanded': ['unsadden', 'unsanded'], + 'unsardonic': ['andronicus', 'unsardonic'], + 'unsashed': ['sunshade', 'unsashed'], + 'unsatable': ['sublanate', 'unsatable'], + 'unsatiable': ['balaustine', 'unsatiable'], + 'unsatin': ['antisun', 'unsaint', 'unsatin', 'unstain'], + 'unsauced': ['uncaused', 'unsauced'], + 'unscale': ['censual', 'unscale'], + 'unscalloped': ['uncollapsed', 'unscalloped'], + 'unscaly': ['ancylus', 'unscaly'], + 'unscared': ['unsacred', 'unscared'], + 'unscepter': ['unrespect', 'unscepter', 'unsceptre'], + 'unsceptered': ['unrespected', 'unsceptered'], + 'unsceptre': ['unrespect', 'unscepter', 'unsceptre'], + 'unscoured': ['uncoursed', 'unscoured'], + 'unseal': ['elanus', 'unseal'], + 'unsealable': ['unleasable', 'unsealable'], + 'unsealed': ['unleased', 'unsealed'], + 'unseared': ['undersea', 'unerased', 'unseared'], + 'unseat': ['nasute', 'nauset', 'unseat'], + 'unseated': ['unseated', 'unsedate', 'unteased'], + 'unsecured': ['unrescued', 'unsecured'], + 'unsedate': ['unseated', 'unsedate', 'unteased'], + 'unsee': ['ensue', 'seenu', 'unsee'], + 'unseethed': ['unseethed', 'unsheeted'], + 'unseizable': ['unseizable', 'unsizeable'], + 'unselect': ['esculent', 'unselect'], + 'unsensed': ['nudeness', 'unsensed'], + 'unsensitive': ['unitiveness', 'unsensitive'], + 'unsent': ['unnest', 'unsent'], + 'unsepulcher': ['unsepulcher', 'unsepulchre'], + 'unsepulchre': ['unsepulcher', 'unsepulchre'], + 'unserrated': ['unarrested', 'unserrated'], + 'unserved': ['unserved', 'unversed'], + 'unset': ['unset', 'usent'], + 'unsevered': ['undeserve', 'unsevered'], + 'unsewed': ['sunweed', 'unsewed'], + 'unsex': ['nexus', 'unsex'], + 'unshaded': ['undashed', 'unshaded'], + 'unshaled': ['unhalsed', 'unlashed', 'unshaled'], + 'unshamed': ['unmashed', 'unshamed'], + 'unshaped': ['unhasped', 'unphased', 'unshaped'], + 'unsharing': ['ungarnish', 'unsharing'], + 'unsharped': ['unphrased', 'unsharped'], + 'unsharpened': ['undershapen', 'unsharpened'], + 'unsheared': ['unhearsed', 'unsheared'], + 'unsheet': ['enthuse', 'unsheet'], + 'unsheeted': ['unseethed', 'unsheeted'], + 'unship': ['inpush', 'punish', 'unship'], + 'unshipment': ['punishment', 'unshipment'], + 'unshoe': ['unhose', 'unshoe'], + 'unshoed': ['unhosed', 'unshoed'], + 'unshore': ['unhorse', 'unshore'], + 'unshored': ['enshroud', 'unshored'], + 'unshortened': ['underhonest', 'unshortened'], + 'unsicker': ['cruisken', 'unsicker'], + 'unsickled': ['klendusic', 'unsickled'], + 'unsight': ['gutnish', 'husting', 'unsight'], + 'unsignable': ['unsignable', 'unsingable'], + 'unsigned': ['undesign', 'unsigned', 'unsinged'], + 'unsigneted': ['uningested', 'unsigneted'], + 'unsilenced': ['unlicensed', 'unsilenced'], + 'unsimple': ['splenium', 'unsimple'], + 'unsin': ['sunni', 'unsin'], + 'unsingable': ['unsignable', 'unsingable'], + 'unsinged': ['undesign', 'unsigned', 'unsinged'], + 'unsistered': ['unresisted', 'unsistered'], + 'unsizeable': ['unseizable', 'unsizeable'], + 'unskin': ['insunk', 'unskin'], + 'unslate': ['sultane', 'unslate'], + 'unslated': ['unsalted', 'unslated', 'unstaled'], + 'unslating': ['unlasting', 'unslating'], + 'unslept': ['unslept', 'unspelt'], + 'unslighted': ['sunlighted', 'unslighted'], + 'unslit': ['insult', 'sunlit', 'unlist', 'unslit'], + 'unslot': ['unlost', 'unslot'], + 'unsmeared': ['underseam', 'unsmeared'], + 'unsmiled': ['muslined', 'unmisled', 'unsmiled'], + 'unsnap': ['pannus', 'sannup', 'unsnap', 'unspan'], + 'unsnatch': ['unsnatch', 'unstanch'], + 'unsnow': ['unsnow', 'unsown'], + 'unsocial': ['sualocin', 'unsocial'], + 'unsoil': ['insoul', 'linous', 'nilous', 'unsoil'], + 'unsoiled': ['delusion', 'unsoiled'], + 'unsoldier': ['undersoil', 'unsoldier'], + 'unsole': ['ensoul', 'olenus', 'unsole'], + 'unsolitary': ['unroyalist', 'unsolitary'], + 'unsomber': ['unsomber', 'unsombre'], + 'unsombre': ['unsomber', 'unsombre'], + 'unsome': ['nomeus', 'unsome'], + 'unsore': ['souren', 'unsore', 'ursone'], + 'unsort': ['tornus', 'unsort'], + 'unsortable': ['neuroblast', 'unsortable'], + 'unsorted': ['tonsured', 'unsorted', 'unstored'], + 'unsoured': ['unroused', 'unsoured'], + 'unsown': ['unsnow', 'unsown'], + 'unspan': ['pannus', 'sannup', 'unsnap', 'unspan'], + 'unspar': ['surnap', 'unspar'], + 'unspared': ['undersap', 'unparsed', 'unrasped', 'unspared', 'unspread'], + 'unsparred': ['underspar', 'unsparred'], + 'unspecterlike': ['unspecterlike', 'unspectrelike'], + 'unspectrelike': ['unspecterlike', 'unspectrelike'], + 'unsped': ['unsped', 'upsend'], + 'unspelt': ['unslept', 'unspelt'], + 'unsphering': ['gunnership', 'unsphering'], + 'unspiable': ['subalpine', 'unspiable'], + 'unspike': ['spunkie', 'unspike'], + 'unspit': ['ptinus', 'unspit'], + 'unspoil': ['pulsion', 'unspoil', 'upsilon'], + 'unspot': ['pontus', 'unspot', 'unstop'], + 'unspread': ['undersap', 'unparsed', 'unrasped', 'unspared', 'unspread'], + 'unstabled': ['dunstable', 'unblasted', 'unstabled'], + 'unstain': ['antisun', 'unsaint', 'unsatin', 'unstain'], + 'unstained': ['unsainted', 'unstained'], + 'unstaled': ['unsalted', 'unslated', 'unstaled'], + 'unstanch': ['unsnatch', 'unstanch'], + 'unstar': ['saturn', 'unstar'], + 'unstatable': ['unstatable', 'untastable'], + 'unstate': ['tetanus', 'unstate', 'untaste'], + 'unstateable': ['unstateable', 'untasteable'], + 'unstated': ['unstated', 'untasted'], + 'unstating': ['unstating', 'untasting'], + 'unstayed': ['unstayed', 'unsteady'], + 'unsteady': ['unstayed', 'unsteady'], + 'unstercorated': ['countertrades', 'unstercorated'], + 'unstern': ['stunner', 'unstern'], + 'unstocked': ['duckstone', 'unstocked'], + 'unstoic': ['cotinus', 'suction', 'unstoic'], + 'unstoical': ['suctional', 'sulcation', 'unstoical'], + 'unstop': ['pontus', 'unspot', 'unstop'], + 'unstopple': ['pulpstone', 'unstopple'], + 'unstore': ['snouter', 'tonsure', 'unstore'], + 'unstored': ['tonsured', 'unsorted', 'unstored'], + 'unstoried': ['detrusion', 'tinderous', 'unstoried'], + 'unstormed': ['undermost', 'unstormed'], + 'unstrain': ['insurant', 'unstrain'], + 'unstrained': ['understain', 'unstrained'], + 'unstraitened': ['unreinstated', 'unstraitened'], + 'unstranded': ['understand', 'unstranded'], + 'unstrewed': ['unstrewed', 'unwrested'], + 'unsucculent': ['centunculus', 'unsucculent'], + 'unsued': ['unsued', 'unused'], + 'unsusceptible': ['unsusceptible', 'unsuspectible'], + 'unsusceptive': ['unsusceptive', 'unsuspective'], + 'unsuspectible': ['unsusceptible', 'unsuspectible'], + 'unsuspective': ['unsusceptive', 'unsuspective'], + 'untactful': ['fluctuant', 'untactful'], + 'untailed': ['nidulate', 'untailed'], + 'untame': ['unmate', 'untame', 'unteam'], + 'untamed': ['unmated', 'untamed'], + 'untanned': ['nunnated', 'untanned'], + 'untap': ['punta', 'unapt', 'untap'], + 'untar': ['arnut', 'tuarn', 'untar'], + 'untastable': ['unstatable', 'untastable'], + 'untaste': ['tetanus', 'unstate', 'untaste'], + 'untasteable': ['unstateable', 'untasteable'], + 'untasted': ['unstated', 'untasted'], + 'untasting': ['unstating', 'untasting'], + 'untaught': ['taungthu', 'untaught'], + 'untaunted': ['unattuned', 'untaunted'], + 'unteach': ['uncheat', 'unteach'], + 'unteaching': ['uncheating', 'unteaching'], + 'unteam': ['unmate', 'untame', 'unteam'], + 'unteamed': ['unmeated', 'unteamed'], + 'unteased': ['unseated', 'unsedate', 'unteased'], + 'unteem': ['unmeet', 'unteem'], + 'untemper': ['erumpent', 'untemper'], + 'untender': ['unrented', 'untender'], + 'untented': ['unnetted', 'untented'], + 'unthatch': ['nuthatch', 'unthatch'], + 'unthick': ['kutchin', 'unthick'], + 'unthrall': ['turnhall', 'unthrall'], + 'untiaraed': ['diuranate', 'untiaraed'], + 'untidy': ['nudity', 'untidy'], + 'untie': ['intue', 'unite', 'untie'], + 'untied': ['dunite', 'united', 'untied'], + 'until': ['unlit', 'until'], + 'untile': ['lutein', 'untile'], + 'untiled': ['diluent', 'untiled'], + 'untilted': ['dilutent', 'untilted', 'untitled'], + 'untimely': ['minutely', 'untimely'], + 'untin': ['nintu', 'ninut', 'untin'], + 'untine': ['ineunt', 'untine'], + 'untinseled': ['unenlisted', 'unlistened', 'untinseled'], + 'untirable': ['untirable', 'untriable'], + 'untire': ['runite', 'triune', 'uniter', 'untire'], + 'untired': ['intrude', 'turdine', 'untired', 'untried'], + 'untithable': ['unhittable', 'untithable'], + 'untitled': ['dilutent', 'untilted', 'untitled'], + 'unto': ['tuno', 'unto'], + 'untoiled': ['outlined', 'untoiled'], + 'untoned': ['unnoted', 'untoned'], + 'untooled': ['unlooted', 'untooled'], + 'untop': ['punto', 'unpot', 'untop'], + 'untorn': ['tunnor', 'untorn'], + 'untortured': ['undertutor', 'untortured'], + 'untotalled': ['unallotted', 'untotalled'], + 'untouch': ['uncouth', 'untouch'], + 'untoured': ['unrouted', 'untoured'], + 'untrace': ['centaur', 'untrace'], + 'untraceable': ['uncreatable', 'untraceable'], + 'untraceableness': ['uncreatableness', 'untraceableness'], + 'untraced': ['uncarted', 'uncrated', 'underact', 'untraced'], + 'untraceried': ['antireducer', 'reincrudate', 'untraceried'], + 'untradeable': ['untradeable', 'untreadable'], + 'untrain': ['antirun', 'untrain', 'urinant'], + 'untread': ['daunter', 'unarted', 'unrated', 'untread'], + 'untreadable': ['untradeable', 'untreadable'], + 'untreatable': ['entablature', 'untreatable'], + 'untreed': ['denture', 'untreed'], + 'untriable': ['untirable', 'untriable'], + 'untribal': ['tribunal', 'turbinal', 'untribal'], + 'untriced': ['undirect', 'untriced'], + 'untried': ['intrude', 'turdine', 'untired', 'untried'], + 'untrig': ['ungirt', 'untrig'], + 'untrod': ['rotund', 'untrod'], + 'untropical': ['ponticular', 'untropical'], + 'untroubled': ['outblunder', 'untroubled'], + 'untrowed': ['undertow', 'untrowed'], + 'untruss': ['sturnus', 'untruss'], + 'untutored': ['outturned', 'untutored'], + 'unurn': ['unrun', 'unurn'], + 'unused': ['unsued', 'unused'], + 'unusurped': ['unpursued', 'unusurped'], + 'unusurping': ['unpursuing', 'unusurping'], + 'unvailable': ['invaluable', 'unvailable'], + 'unveering': ['unreeving', 'unveering'], + 'unveil': ['unevil', 'unlive', 'unveil'], + 'unveiled': ['unlevied', 'unveiled'], + 'unveined': ['unenvied', 'unveined'], + 'unvenerated': ['unenervated', 'unvenerated'], + 'unveniable': ['unenviable', 'unveniable'], + 'unveritable': ['unavertible', 'unveritable'], + 'unversed': ['unserved', 'unversed'], + 'unvessel': ['unvessel', 'usselven'], + 'unvest': ['unvest', 'venust'], + 'unvomited': ['unmotived', 'unvomited'], + 'unwagered': ['underwage', 'unwagered'], + 'unwan': ['unwan', 'wunna'], + 'unware': ['unware', 'wauner'], + 'unwarp': ['unwarp', 'unwrap'], + 'unwary': ['runway', 'unwary'], + 'unwavered': ['underwave', 'unwavered'], + 'unwept': ['unwept', 'upwent'], + 'unwon': ['unown', 'unwon'], + 'unwrap': ['unwarp', 'unwrap'], + 'unwrested': ['unstrewed', 'unwrested'], + 'unwronged': ['undergown', 'unwronged'], + 'unyoung': ['unyoung', 'youngun'], + 'unze': ['unze', 'zenu'], + 'up': ['pu', 'up'], + 'uparching': ['ungraphic', 'uparching'], + 'uparise': ['spuriae', 'uparise', 'upraise'], + 'uparna': ['purana', 'uparna'], + 'upas': ['apus', 'supa', 'upas'], + 'upblast': ['subplat', 'upblast'], + 'upblow': ['blowup', 'upblow'], + 'upbreak': ['breakup', 'upbreak'], + 'upbuild': ['buildup', 'upbuild'], + 'upcast': ['catsup', 'upcast'], + 'upcatch': ['catchup', 'upcatch'], + 'upclimb': ['plumbic', 'upclimb'], + 'upclose': ['culpose', 'ploceus', 'upclose'], + 'upcock': ['cockup', 'upcock'], + 'upcoil': ['oilcup', 'upcoil'], + 'upcourse': ['cupreous', 'upcourse'], + 'upcover': ['overcup', 'upcover'], + 'upcreep': ['prepuce', 'upcreep'], + 'upcurrent': ['puncturer', 'upcurrent'], + 'upcut': ['cutup', 'upcut'], + 'updo': ['doup', 'updo'], + 'updraw': ['updraw', 'upward'], + 'updry': ['prudy', 'purdy', 'updry'], + 'upeat': ['taupe', 'upeat'], + 'upflare': ['rapeful', 'upflare'], + 'upflower': ['powerful', 'upflower'], + 'upgale': ['plague', 'upgale'], + 'upget': ['getup', 'upget'], + 'upgirt': ['ripgut', 'upgirt'], + 'upgo': ['goup', 'ogpu', 'upgo'], + 'upgrade': ['guepard', 'upgrade'], + 'uphelm': ['phleum', 'uphelm'], + 'uphold': ['holdup', 'uphold'], + 'upholder': ['reuphold', 'upholder'], + 'upholsterer': ['reupholster', 'upholsterer'], + 'upla': ['paul', 'upla'], + 'upland': ['dunlap', 'upland'], + 'uplander': ['pendular', 'underlap', 'uplander'], + 'uplane': ['unpale', 'uplane'], + 'upleap': ['papule', 'upleap'], + 'uplift': ['tipful', 'uplift'], + 'uplifter': ['reuplift', 'uplifter'], + 'upline': ['lupine', 'unpile', 'upline'], + 'uplock': ['lockup', 'uplock'], + 'upon': ['noup', 'puno', 'upon'], + 'uppers': ['supper', 'uppers'], + 'uppish': ['hippus', 'uppish'], + 'upraise': ['spuriae', 'uparise', 'upraise'], + 'uprear': ['parure', 'uprear'], + 'uprein': ['purine', 'unripe', 'uprein'], + 'uprip': ['ripup', 'uprip'], + 'uprisal': ['parulis', 'spirula', 'uprisal'], + 'uprisement': ['episternum', 'uprisement'], + 'upriser': ['siruper', 'upriser'], + 'uprist': ['purist', 'spruit', 'uprist', 'upstir'], + 'uproad': ['podura', 'uproad'], + 'uproom': ['moorup', 'uproom'], + 'uprose': ['poseur', 'pouser', 'souper', 'uprose'], + 'upscale': ['capsule', 'specula', 'upscale'], + 'upseal': ['apulse', 'upseal'], + 'upsend': ['unsped', 'upsend'], + 'upset': ['setup', 'stupe', 'upset'], + 'upsettable': ['subpeltate', 'upsettable'], + 'upsetter': ['upsetter', 'upstreet'], + 'upshore': ['ephorus', 'orpheus', 'upshore'], + 'upshot': ['tophus', 'upshot'], + 'upshut': ['pushtu', 'upshut'], + 'upsilon': ['pulsion', 'unspoil', 'upsilon'], + 'upsit': ['puist', 'upsit'], + 'upslant': ['pulsant', 'upslant'], + 'upsmite': ['impetus', 'upsmite'], + 'upsoar': ['parous', 'upsoar'], + 'upstair': ['tapirus', 'upstair'], + 'upstand': ['dustpan', 'upstand'], + 'upstare': ['pasteur', 'pasture', 'upstare'], + 'upstater': ['stuprate', 'upstater'], + 'upsteal': ['pulsate', 'spatule', 'upsteal'], + 'upstem': ['septum', 'upstem'], + 'upstir': ['purist', 'spruit', 'uprist', 'upstir'], + 'upstraight': ['straightup', 'upstraight'], + 'upstreet': ['upsetter', 'upstreet'], + 'upstrive': ['spurtive', 'upstrive'], + 'upsun': ['sunup', 'upsun'], + 'upsway': ['upsway', 'upways'], + 'uptake': ['ketupa', 'uptake'], + 'uptend': ['pudent', 'uptend'], + 'uptilt': ['tiltup', 'uptilt'], + 'uptoss': ['tossup', 'uptoss'], + 'uptrace': ['capture', 'uptrace'], + 'uptrain': ['pintura', 'puritan', 'uptrain'], + 'uptree': ['repute', 'uptree'], + 'uptrend': ['prudent', 'prunted', 'uptrend'], + 'upturn': ['turnup', 'upturn'], + 'upward': ['updraw', 'upward'], + 'upwarp': ['upwarp', 'upwrap'], + 'upways': ['upsway', 'upways'], + 'upwent': ['unwept', 'upwent'], + 'upwind': ['upwind', 'windup'], + 'upwrap': ['upwarp', 'upwrap'], + 'ura': ['aru', 'rua', 'ura'], + 'uracil': ['curial', 'lauric', 'uracil', 'uralic'], + 'uraemic': ['maurice', 'uraemic'], + 'uraeus': ['aureus', 'uraeus'], + 'ural': ['alur', 'laur', 'lura', 'raul', 'ural'], + 'urali': ['rauli', 'urali', 'urial'], + 'uralian': ['lunaria', 'ulnaria', 'uralian'], + 'uralic': ['curial', 'lauric', 'uracil', 'uralic'], + 'uralite': ['laurite', 'uralite'], + 'uralitize': ['ritualize', 'uralitize'], + 'uramido': ['doarium', 'uramido'], + 'uramil': ['rimula', 'uramil'], + 'uramino': ['mainour', 'uramino'], + 'uran': ['raun', 'uran', 'urna'], + 'uranate': ['taurean', 'uranate'], + 'urania': ['anuria', 'urania'], + 'uranic': ['anuric', 'cinura', 'uranic'], + 'uranine': ['aneurin', 'uranine'], + 'uranism': ['surinam', 'uranism'], + 'uranite': ['ruinate', 'taurine', 'uranite', 'urinate'], + 'uranographist': ['guarantorship', 'uranographist'], + 'uranolite': ['outlinear', 'uranolite'], + 'uranoscope': ['oenocarpus', 'uranoscope'], + 'uranospinite': ['resupination', 'uranospinite'], + 'uranotil': ['rotulian', 'uranotil'], + 'uranous': ['anurous', 'uranous'], + 'uranyl': ['lunary', 'uranyl'], + 'uranylic': ['culinary', 'uranylic'], + 'urari': ['aurir', 'urari'], + 'urase': ['serau', 'urase'], + 'uratic': ['tauric', 'uratic', 'urtica'], + 'urazine': ['azurine', 'urazine'], + 'urban': ['buran', 'unbar', 'urban'], + 'urbane': ['eburna', 'unbare', 'unbear', 'urbane'], + 'urbanite': ['braunite', 'urbanite', 'urbinate'], + 'urbian': ['burian', 'urbian'], + 'urbification': ['rubification', 'urbification'], + 'urbify': ['rubify', 'urbify'], + 'urbinate': ['braunite', 'urbanite', 'urbinate'], + 'urceiform': ['eruciform', 'urceiform'], + 'urceole': ['urceole', 'urocele'], + 'urceolina': ['aleuronic', 'urceolina'], + 'urceolus': ['ulcerous', 'urceolus'], + 'urchin': ['unrich', 'urchin'], + 'urd': ['rud', 'urd'], + 'urde': ['duer', 'dure', 'rude', 'urde'], + 'urdee': ['redue', 'urdee'], + 'ure': ['rue', 'ure'], + 'ureal': ['alure', 'ureal'], + 'uredine': ['reindue', 'uredine'], + 'ureic': ['curie', 'ureic'], + 'uremia': ['aumrie', 'uremia'], + 'uremic': ['cerium', 'uremic'], + 'urena': ['urena', 'urnae'], + 'urent': ['enrut', 'tuner', 'urent'], + 'uresis': ['issuer', 'uresis'], + 'uretal': ['tulare', 'uretal'], + 'ureter': ['retrue', 'ureter'], + 'ureteropyelogram': ['pyeloureterogram', 'ureteropyelogram'], + 'urethan': ['haunter', 'nauther', 'unearth', 'unheart', 'urethan'], + 'urethrascope': ['heterocarpus', 'urethrascope'], + 'urethrocystitis': ['cystourethritis', 'urethrocystitis'], + 'urethylan': ['unearthly', 'urethylan'], + 'uretic': ['curite', 'teucri', 'uretic'], + 'urf': ['fur', 'urf'], + 'urge': ['grue', 'urge'], + 'urgent': ['gunter', 'gurnet', 'urgent'], + 'urger': ['regur', 'urger'], + 'uria': ['arui', 'uria'], + 'uriah': ['huari', 'uriah'], + 'urial': ['rauli', 'urali', 'urial'], + 'urian': ['aurin', 'urian'], + 'uric': ['cuir', 'uric'], + 'urinal': ['laurin', 'urinal'], + 'urinant': ['antirun', 'untrain', 'urinant'], + 'urinate': ['ruinate', 'taurine', 'uranite', 'urinate'], + 'urination': ['ruination', 'urination'], + 'urinator': ['ruinator', 'urinator'], + 'urine': ['inure', 'urine'], + 'urinogenitary': ['genitourinary', 'urinogenitary'], + 'urinous': ['ruinous', 'urinous'], + 'urinousness': ['ruinousness', 'urinousness'], + 'urite': ['urite', 'uteri'], + 'urlar': ['rural', 'urlar'], + 'urled': ['duler', 'urled'], + 'urling': ['ruling', 'urling'], + 'urman': ['muran', 'ruman', 'unarm', 'unram', 'urman'], + 'urn': ['run', 'urn'], + 'urna': ['raun', 'uran', 'urna'], + 'urnae': ['urena', 'urnae'], + 'urnal': ['lunar', 'ulnar', 'urnal'], + 'urnful': ['unfurl', 'urnful'], + 'urning': ['unring', 'urning'], + 'uro': ['our', 'uro'], + 'urocele': ['urceole', 'urocele'], + 'urodela': ['roulade', 'urodela'], + 'urodelan': ['unloader', 'urodelan'], + 'urogaster': ['surrogate', 'urogaster'], + 'urogenital': ['regulation', 'urogenital'], + 'uroglena': ['lagunero', 'organule', 'uroglena'], + 'urolithic': ['ulotrichi', 'urolithic'], + 'urometer': ['outremer', 'urometer'], + 'uronic': ['cuorin', 'uronic'], + 'uropsile': ['perilous', 'uropsile'], + 'uroseptic': ['crepitous', 'euproctis', 'uroseptic'], + 'urosomatic': ['mortacious', 'urosomatic'], + 'urosteon': ['outsnore', 'urosteon'], + 'urosternite': ['tenuiroster', 'urosternite'], + 'urosthenic': ['cetorhinus', 'urosthenic'], + 'urostyle': ['elytrous', 'urostyle'], + 'urs': ['rus', 'sur', 'urs'], + 'ursa': ['rusa', 'saur', 'sura', 'ursa', 'usar'], + 'ursal': ['larus', 'sural', 'ursal'], + 'ursidae': ['residua', 'ursidae'], + 'ursine': ['insure', 'rusine', 'ursine'], + 'ursone': ['souren', 'unsore', 'ursone'], + 'ursuk': ['kurus', 'ursuk'], + 'ursula': ['laurus', 'ursula'], + 'urtica': ['tauric', 'uratic', 'urtica'], + 'urticales': ['sterculia', 'urticales'], + 'urticant': ['taciturn', 'urticant'], + 'urticose': ['citreous', 'urticose'], + 'usability': ['suability', 'usability'], + 'usable': ['suable', 'usable'], + 'usager': ['sauger', 'usager'], + 'usance': ['uncase', 'usance'], + 'usar': ['rusa', 'saur', 'sura', 'ursa', 'usar'], + 'usara': ['arusa', 'saura', 'usara'], + 'use': ['sue', 'use'], + 'usent': ['unset', 'usent'], + 'user': ['ruse', 'suer', 'sure', 'user'], + 'ush': ['shu', 'ush'], + 'ushabti': ['habitus', 'ushabti'], + 'ushak': ['kusha', 'shaku', 'ushak'], + 'usher': ['shure', 'usher'], + 'usitate': ['situate', 'usitate'], + 'usnic': ['incus', 'usnic'], + 'usque': ['equus', 'usque'], + 'usselven': ['unvessel', 'usselven'], + 'ust': ['stu', 'ust'], + 'uster': ['serut', 'strue', 'turse', 'uster'], + 'ustion': ['outsin', 'ustion'], + 'ustorious': ['sutorious', 'ustorious'], + 'ustulina': ['lutianus', 'nautilus', 'ustulina'], + 'usucaption': ['uncaptious', 'usucaption'], + 'usure': ['eurus', 'usure'], + 'usurper': ['pursuer', 'usurper'], + 'ut': ['tu', 'ut'], + 'uta': ['tau', 'tua', 'uta'], + 'utas': ['saut', 'tasu', 'utas'], + 'utch': ['chut', 'tchu', 'utch'], + 'ute': ['tue', 'ute'], + 'uteri': ['urite', 'uteri'], + 'uterine': ['neurite', 'retinue', 'reunite', 'uterine'], + 'uterocervical': ['overcirculate', 'uterocervical'], + 'uterus': ['suture', 'uterus'], + 'utile': ['luite', 'utile'], + 'utilizable': ['latibulize', 'utilizable'], + 'utopian': ['opuntia', 'utopian'], + 'utopism': ['positum', 'utopism'], + 'utopist': ['outspit', 'utopist'], + 'utricular': ['turricula', 'utricular'], + 'utriculosaccular': ['sacculoutricular', 'utriculosaccular'], + 'utrum': ['murut', 'utrum'], + 'utterer': ['reutter', 'utterer'], + 'uva': ['uva', 'vau'], + 'uval': ['ulva', 'uval'], + 'uveal': ['uveal', 'value'], + 'uviol': ['uviol', 'vouli'], + 'vacate': ['cavate', 'caveat', 'vacate'], + 'vacation': ['octavian', 'octavina', 'vacation'], + 'vacationer': ['acervation', 'vacationer'], + 'vaccinal': ['clavacin', 'vaccinal'], + 'vacillate': ['laticlave', 'vacillate'], + 'vacillation': ['cavillation', 'vacillation'], + 'vacuolate': ['autoclave', 'vacuolate'], + 'vade': ['dave', 'deva', 'vade', 'veda'], + 'vady': ['davy', 'vady'], + 'vage': ['gave', 'vage', 'vega'], + 'vagile': ['glaive', 'vagile'], + 'vaginant': ['navigant', 'vaginant'], + 'vaginate': ['navigate', 'vaginate'], + 'vaginoabdominal': ['abdominovaginal', 'vaginoabdominal'], + 'vaginoperineal': ['perineovaginal', 'vaginoperineal'], + 'vaginovesical': ['vaginovesical', 'vesicovaginal'], + 'vaguity': ['gavyuti', 'vaguity'], + 'vai': ['iva', 'vai', 'via'], + 'vail': ['vail', 'vali', 'vial', 'vila'], + 'vain': ['ivan', 'vain', 'vina'], + 'vair': ['ravi', 'riva', 'vair', 'vari', 'vira'], + 'vakass': ['kavass', 'vakass'], + 'vale': ['lave', 'vale', 'veal', 'vela'], + 'valence': ['enclave', 'levance', 'valence'], + 'valencia': ['valencia', 'valiance'], + 'valent': ['levant', 'valent'], + 'valentine': ['levantine', 'valentine'], + 'valeria': ['reavail', 'valeria'], + 'valeriana': ['laverania', 'valeriana'], + 'valeric': ['caliver', 'caviler', 'claiver', 'clavier', 'valeric', 'velaric'], + 'valerie': ['realive', 'valerie'], + 'valerin': ['elinvar', 'ravelin', 'reanvil', 'valerin'], + 'valerone': ['overlean', 'valerone'], + 'valeryl': ['ravelly', 'valeryl'], + 'valeur': ['valeur', 'valuer'], + 'vali': ['vail', 'vali', 'vial', 'vila'], + 'valiance': ['valencia', 'valiance'], + 'valiant': ['latvian', 'valiant'], + 'valine': ['alevin', 'alvine', 'valine', 'veinal', 'venial', 'vineal'], + 'vallar': ['larval', 'vallar'], + 'vallidom': ['vallidom', 'villadom'], + 'vallota': ['lavolta', 'vallota'], + 'valonia': ['novalia', 'valonia'], + 'valor': ['valor', 'volar'], + 'valsa': ['salva', 'valsa', 'vasal'], + 'valse': ['salve', 'selva', 'slave', 'valse'], + 'value': ['uveal', 'value'], + 'valuer': ['valeur', 'valuer'], + 'vamper': ['revamp', 'vamper'], + 'vane': ['evan', 'nave', 'vane'], + 'vaned': ['daven', 'vaned'], + 'vangee': ['avenge', 'geneva', 'vangee'], + 'vangeli': ['leaving', 'vangeli'], + 'vanir': ['invar', 'ravin', 'vanir'], + 'vanisher': ['enravish', 'ravenish', 'vanisher'], + 'vansire': ['servian', 'vansire'], + 'vapid': ['pavid', 'vapid'], + 'vapidity': ['pavidity', 'vapidity'], + 'vaporarium': ['parovarium', 'vaporarium'], + 'vara': ['avar', 'vara'], + 'varan': ['navar', 'varan', 'varna'], + 'vare': ['aver', 'rave', 'vare', 'vera'], + 'varec': ['carve', 'crave', 'varec'], + 'vari': ['ravi', 'riva', 'vair', 'vari', 'vira'], + 'variate': ['variate', 'vateria'], + 'varices': ['varices', 'viscera'], + 'varicula': ['avicular', 'varicula'], + 'variegator': ['arrogative', 'variegator'], + 'varier': ['arrive', 'varier'], + 'varietal': ['lievaart', 'varietal'], + 'variola': ['ovarial', 'variola'], + 'various': ['saviour', 'various'], + 'varlet': ['travel', 'varlet'], + 'varletry': ['varletry', 'veratryl'], + 'varna': ['navar', 'varan', 'varna'], + 'varnish': ['shirvan', 'varnish'], + 'varnisher': ['revarnish', 'varnisher'], + 'varsha': ['avshar', 'varsha'], + 'vasal': ['salva', 'valsa', 'vasal'], + 'vase': ['aves', 'save', 'vase'], + 'vasoepididymostomy': ['epididymovasostomy', 'vasoepididymostomy'], + 'vat': ['tav', 'vat'], + 'vateria': ['variate', 'vateria'], + 'vaticide': ['cavitied', 'vaticide'], + 'vaticinate': ['inactivate', 'vaticinate'], + 'vaticination': ['inactivation', 'vaticination'], + 'vatter': ['tavert', 'vatter'], + 'vau': ['uva', 'vau'], + 'vaudois': ['avidous', 'vaudois'], + 'veal': ['lave', 'vale', 'veal', 'vela'], + 'vealer': ['laveer', 'leaver', 'reveal', 'vealer'], + 'vealiness': ['aliveness', 'vealiness'], + 'vealy': ['leavy', 'vealy'], + 'vector': ['covert', 'vector'], + 'veda': ['dave', 'deva', 'vade', 'veda'], + 'vedaic': ['advice', 'vedaic'], + 'vedaism': ['adevism', 'vedaism'], + 'vedana': ['nevada', 'vedana', 'venada'], + 'vedanta': ['vedanta', 'vetanda'], + 'vedantism': ['adventism', 'vedantism'], + 'vedantist': ['adventist', 'vedantist'], + 'vedist': ['divest', 'vedist'], + 'vedro': ['dover', 'drove', 'vedro'], + 'vee': ['eve', 'vee'], + 'veen': ['even', 'neve', 'veen'], + 'veer': ['ever', 'reve', 'veer'], + 'veery': ['every', 'veery'], + 'vega': ['gave', 'vage', 'vega'], + 'vegasite': ['estivage', 'vegasite'], + 'vegetarian': ['renavigate', 'vegetarian'], + 'vei': ['vei', 'vie'], + 'veil': ['evil', 'levi', 'live', 'veil', 'vile', 'vlei'], + 'veiler': ['levier', 'relive', 'reveil', 'revile', 'veiler'], + 'veiltail': ['illative', 'veiltail'], + 'vein': ['vein', 'vine'], + 'veinal': ['alevin', 'alvine', 'valine', 'veinal', 'venial', 'vineal'], + 'veined': ['endive', 'envied', 'veined'], + 'veiner': ['enrive', 'envier', 'veiner', 'verine'], + 'veinless': ['evilness', 'liveness', 'veinless', 'vileness', 'vineless'], + 'veinlet': ['veinlet', 'vinelet'], + 'veinous': ['envious', 'niveous', 'veinous'], + 'veinstone': ['veinstone', 'vonsenite'], + 'veinwise': ['veinwise', 'vinewise'], + 'vela': ['lave', 'vale', 'veal', 'vela'], + 'velar': ['arvel', 'larve', 'laver', 'ravel', 'velar'], + 'velaric': ['caliver', 'caviler', 'claiver', 'clavier', 'valeric', 'velaric'], + 'velation': ['olivetan', 'velation'], + 'velic': ['clive', 'velic'], + 'veliform': ['overfilm', 'veliform'], + 'velitation': ['levitation', 'tonalitive', 'velitation'], + 'velo': ['levo', 'love', 'velo', 'vole'], + 'velte': ['elvet', 'velte'], + 'venada': ['nevada', 'vedana', 'venada'], + 'venal': ['elvan', 'navel', 'venal'], + 'venality': ['natively', 'venality'], + 'venatic': ['catvine', 'venatic'], + 'venation': ['innovate', 'venation'], + 'venator': ['rotanev', 'venator'], + 'venatorial': ['venatorial', 'venoatrial'], + 'vendace': ['devance', 'vendace'], + 'vender': ['revend', 'vender'], + 'veneer': ['evener', 'veneer'], + 'veneerer': ['reveneer', 'veneerer'], + 'veneralia': ['ravenelia', 'veneralia'], + 'venerant': ['revenant', 'venerant'], + 'venerate': ['enervate', 'venerate'], + 'veneration': ['enervation', 'veneration'], + 'venerative': ['enervative', 'venerative'], + 'venerator': ['enervator', 'renovater', 'venerator'], + 'venerer': ['renerve', 'venerer'], + 'veneres': ['sevener', 'veneres'], + 'veneti': ['veneti', 'venite'], + 'venetian': ['aventine', 'venetian'], + 'venial': ['alevin', 'alvine', 'valine', 'veinal', 'venial', 'vineal'], + 'venice': ['cevine', 'evince', 'venice'], + 'venie': ['nieve', 'venie'], + 'venite': ['veneti', 'venite'], + 'venoatrial': ['venatorial', 'venoatrial'], + 'venom': ['novem', 'venom'], + 'venosinal': ['slovenian', 'venosinal'], + 'venter': ['revent', 'venter'], + 'ventrad': ['ventrad', 'verdant'], + 'ventricose': ['convertise', 'ventricose'], + 'ventrine': ['inventer', 'reinvent', 'ventrine', 'vintener'], + 'ventrodorsad': ['dorsoventrad', 'ventrodorsad'], + 'ventrodorsal': ['dorsoventral', 'ventrodorsal'], + 'ventrodorsally': ['dorsoventrally', 'ventrodorsally'], + 'ventrolateral': ['lateroventral', 'ventrolateral'], + 'ventromedial': ['medioventral', 'ventromedial'], + 'ventromesal': ['mesoventral', 'ventromesal'], + 'venular': ['unravel', 'venular'], + 'venus': ['nevus', 'venus'], + 'venust': ['unvest', 'venust'], + 'venutian': ['unnative', 'venutian'], + 'vera': ['aver', 'rave', 'vare', 'vera'], + 'veraciousness': ['oversauciness', 'veraciousness'], + 'veratroidine': ['rederivation', 'veratroidine'], + 'veratrole': ['relevator', 'revelator', 'veratrole'], + 'veratryl': ['varletry', 'veratryl'], + 'verbal': ['barvel', 'blaver', 'verbal'], + 'verbality': ['verbality', 'veritably'], + 'verbatim': ['ambivert', 'verbatim'], + 'verbena': ['enbrave', 'verbena'], + 'verberate': ['verberate', 'vertebrae'], + 'verbose': ['observe', 'obverse', 'verbose'], + 'verbosely': ['obversely', 'verbosely'], + 'verdant': ['ventrad', 'verdant'], + 'verdea': ['evader', 'verdea'], + 'verdelho': ['overheld', 'verdelho'], + 'verdin': ['driven', 'nervid', 'verdin'], + 'verditer': ['diverter', 'redivert', 'verditer'], + 'vergi': ['giver', 'vergi'], + 'veri': ['rive', 'veri', 'vier', 'vire'], + 'veridical': ['larvicide', 'veridical'], + 'veridicous': ['recidivous', 'veridicous'], + 'verily': ['livery', 'verily'], + 'verine': ['enrive', 'envier', 'veiner', 'verine'], + 'verism': ['verism', 'vermis'], + 'verist': ['stiver', 'strive', 'verist'], + 'veritable': ['avertible', 'veritable'], + 'veritably': ['verbality', 'veritably'], + 'vermian': ['minerva', 'vermian'], + 'verminal': ['minerval', 'verminal'], + 'vermis': ['verism', 'vermis'], + 'vernacularist': ['intervascular', 'vernacularist'], + 'vernal': ['nerval', 'vernal'], + 'vernation': ['nervation', 'vernation'], + 'vernicose': ['coversine', 'vernicose'], + 'vernine': ['innerve', 'nervine', 'vernine'], + 'veronese': ['overseen', 'veronese'], + 'veronica': ['corvinae', 'veronica'], + 'verpa': ['paver', 'verpa'], + 'verre': ['rever', 'verre'], + 'verrucous': ['recurvous', 'verrucous'], + 'verruga': ['gravure', 'verruga'], + 'versable': ['beslaver', 'servable', 'versable'], + 'versal': ['salver', 'serval', 'slaver', 'versal'], + 'versant': ['servant', 'versant'], + 'versate': ['evestar', 'versate'], + 'versation': ['overstain', 'servation', 'versation'], + 'verse': ['serve', 'sever', 'verse'], + 'verser': ['revers', 'server', 'verser'], + 'verset': ['revest', 'servet', 'sterve', 'verset', 'vester'], + 'versicule': ['reclusive', 'versicule'], + 'versine': ['inverse', 'versine'], + 'versioner': ['reversion', 'versioner'], + 'versionist': ['overinsist', 'versionist'], + 'verso': ['servo', 'verso'], + 'versta': ['starve', 'staver', 'strave', 'tavers', 'versta'], + 'vertebrae': ['verberate', 'vertebrae'], + 'vertebrocostal': ['costovertebral', 'vertebrocostal'], + 'vertebrosacral': ['sacrovertebral', 'vertebrosacral'], + 'vertebrosternal': ['sternovertebral', 'vertebrosternal'], + 'vertiginate': ['integrative', 'vertiginate', 'vinaigrette'], + 'vesicant': ['cistvaen', 'vesicant'], + 'vesicoabdominal': ['abdominovesical', 'vesicoabdominal'], + 'vesicocervical': ['cervicovesical', 'vesicocervical'], + 'vesicointestinal': ['intestinovesical', 'vesicointestinal'], + 'vesicorectal': ['rectovesical', 'vesicorectal'], + 'vesicovaginal': ['vaginovesical', 'vesicovaginal'], + 'vespa': ['spave', 'vespa'], + 'vespertine': ['presentive', 'pretensive', 'vespertine'], + 'vespine': ['pensive', 'vespine'], + 'vesta': ['stave', 'vesta'], + 'vestalia': ['salivate', 'vestalia'], + 'vestee': ['steeve', 'vestee'], + 'vester': ['revest', 'servet', 'sterve', 'verset', 'vester'], + 'vestibula': ['sublative', 'vestibula'], + 'veta': ['tave', 'veta'], + 'vetanda': ['vedanta', 'vetanda'], + 'veteran': ['nervate', 'veteran'], + 'veto': ['veto', 'voet', 'vote'], + 'vetoer': ['revote', 'vetoer'], + 'via': ['iva', 'vai', 'via'], + 'vial': ['vail', 'vali', 'vial', 'vila'], + 'vialful': ['fluavil', 'fluvial', 'vialful'], + 'viand': ['divan', 'viand'], + 'viander': ['invader', 'ravined', 'viander'], + 'viatic': ['avitic', 'viatic'], + 'viatica': ['aviatic', 'viatica'], + 'vibrate': ['vibrate', 'vrbaite'], + 'vicar': ['vicar', 'vraic'], + 'vice': ['cive', 'vice'], + 'vicegeral': ['vicegeral', 'viceregal'], + 'viceregal': ['vicegeral', 'viceregal'], + 'victoriate': ['recitativo', 'victoriate'], + 'victrola': ['victrola', 'vortical'], + 'victualer': ['lucrative', 'revictual', 'victualer'], + 'vidonia': ['ovidian', 'vidonia'], + 'viduinae': ['induviae', 'viduinae'], + 'viduine': ['univied', 'viduine'], + 'vie': ['vei', 'vie'], + 'vienna': ['avenin', 'vienna'], + 'vier': ['rive', 'veri', 'vier', 'vire'], + 'vierling': ['reviling', 'vierling'], + 'view': ['view', 'wive'], + 'viewer': ['review', 'viewer'], + 'vigilante': ['genitival', 'vigilante'], + 'vigor': ['vigor', 'virgo'], + 'vila': ['vail', 'vali', 'vial', 'vila'], + 'vile': ['evil', 'levi', 'live', 'veil', 'vile', 'vlei'], + 'vilehearted': ['evilhearted', 'vilehearted'], + 'vilely': ['evilly', 'lively', 'vilely'], + 'vileness': ['evilness', 'liveness', 'veinless', 'vileness', 'vineless'], + 'villadom': ['vallidom', 'villadom'], + 'villeiness': ['liveliness', 'villeiness'], + 'villous': ['ovillus', 'villous'], + 'vimana': ['maniva', 'vimana'], + 'vina': ['ivan', 'vain', 'vina'], + 'vinaigrette': ['integrative', 'vertiginate', 'vinaigrette'], + 'vinaigrous': ['vinaigrous', 'viraginous'], + 'vinal': ['alvin', 'anvil', 'nival', 'vinal'], + 'vinalia': ['lavinia', 'vinalia'], + 'vinata': ['avanti', 'vinata'], + 'vinculate': ['vinculate', 'vulcanite'], + 'vine': ['vein', 'vine'], + 'vinea': ['avine', 'naive', 'vinea'], + 'vineal': ['alevin', 'alvine', 'valine', 'veinal', 'venial', 'vineal'], + 'vineatic': ['antivice', 'inactive', 'vineatic'], + 'vinegarist': ['gainstrive', 'vinegarist'], + 'vineless': ['evilness', 'liveness', 'veinless', 'vileness', 'vineless'], + 'vinelet': ['veinlet', 'vinelet'], + 'viner': ['riven', 'viner'], + 'vinewise': ['veinwise', 'vinewise'], + 'vinosity': ['nivosity', 'vinosity'], + 'vintener': ['inventer', 'reinvent', 'ventrine', 'vintener'], + 'vintneress': ['inventress', 'vintneress'], + 'viola': ['oliva', 'viola'], + 'violability': ['obliviality', 'violability'], + 'violaceous': ['olivaceous', 'violaceous'], + 'violanin': ['livonian', 'violanin'], + 'violational': ['avolitional', 'violational'], + 'violer': ['oliver', 'violer', 'virole'], + 'violescent': ['olivescent', 'violescent'], + 'violet': ['olivet', 'violet'], + 'violette': ['olivette', 'violette'], + 'violine': ['olivine', 'violine'], + 'vipera': ['pavier', 'vipera'], + 'viperess': ['pressive', 'viperess'], + 'viperian': ['viperian', 'viperina'], + 'viperina': ['viperian', 'viperina'], + 'viperous': ['pervious', 'previous', 'viperous'], + 'viperously': ['perviously', 'previously', 'viperously'], + 'viperousness': ['perviousness', 'previousness', 'viperousness'], + 'vira': ['ravi', 'riva', 'vair', 'vari', 'vira'], + 'viraginian': ['irvingiana', 'viraginian'], + 'viraginous': ['vinaigrous', 'viraginous'], + 'viral': ['rival', 'viral'], + 'virales': ['revisal', 'virales'], + 'vire': ['rive', 'veri', 'vier', 'vire'], + 'virent': ['invert', 'virent'], + 'virgate': ['virgate', 'vitrage'], + 'virgin': ['irving', 'riving', 'virgin'], + 'virginly': ['rivingly', 'virginly'], + 'virgo': ['vigor', 'virgo'], + 'virile': ['livier', 'virile'], + 'virole': ['oliver', 'violer', 'virole'], + 'virose': ['rivose', 'virose'], + 'virtual': ['virtual', 'vitular'], + 'virtuose': ['virtuose', 'vitreous'], + 'virulence': ['cervuline', 'virulence'], + 'visa': ['avis', 'siva', 'visa'], + 'viscera': ['varices', 'viscera'], + 'visceration': ['insectivora', 'visceration'], + 'visceroparietal': ['parietovisceral', 'visceroparietal'], + 'visceropleural': ['pleurovisceral', 'visceropleural'], + 'viscometer': ['semivector', 'viscometer'], + 'viscontal': ['viscontal', 'volcanist'], + 'vishal': ['lavish', 'vishal'], + 'visioner': ['revision', 'visioner'], + 'visit': ['visit', 'vitis'], + 'visitant': ['nativist', 'visitant'], + 'visitee': ['evisite', 'visitee'], + 'visiter': ['revisit', 'visiter'], + 'visitor': ['ivorist', 'visitor'], + 'vistal': ['vistal', 'vitals'], + 'visto': ['ovist', 'visto'], + 'vitals': ['vistal', 'vitals'], + 'vitis': ['visit', 'vitis'], + 'vitochemical': ['chemicovital', 'vitochemical'], + 'vitrage': ['virgate', 'vitrage'], + 'vitrail': ['trivial', 'vitrail'], + 'vitrailist': ['trivialist', 'vitrailist'], + 'vitrain': ['vitrain', 'vitrina'], + 'vitrean': ['avertin', 'vitrean'], + 'vitreous': ['virtuose', 'vitreous'], + 'vitrina': ['vitrain', 'vitrina'], + 'vitrine': ['inviter', 'vitrine'], + 'vitrophyric': ['thyroprivic', 'vitrophyric'], + 'vitular': ['virtual', 'vitular'], + 'vituperate': ['reputative', 'vituperate'], + 'vlei': ['evil', 'levi', 'live', 'veil', 'vile', 'vlei'], + 'vocaller': ['overcall', 'vocaller'], + 'vocate': ['avocet', 'octave', 'vocate'], + 'voet': ['veto', 'voet', 'vote'], + 'voeten': ['voeten', 'voteen'], + 'vogue': ['vogue', 'vouge'], + 'voided': ['devoid', 'voided'], + 'voider': ['devoir', 'voider'], + 'voidless': ['dissolve', 'voidless'], + 'voile': ['olive', 'ovile', 'voile'], + 'volable': ['lovable', 'volable'], + 'volage': ['lovage', 'volage'], + 'volar': ['valor', 'volar'], + 'volata': ['tavola', 'volata'], + 'volatic': ['volatic', 'voltaic'], + 'volcae': ['alcove', 'coeval', 'volcae'], + 'volcanist': ['viscontal', 'volcanist'], + 'vole': ['levo', 'love', 'velo', 'vole'], + 'volery': ['overly', 'volery'], + 'volitate': ['volitate', 'voltaite'], + 'volley': ['lovely', 'volley'], + 'volscian': ['slavonic', 'volscian'], + 'volta': ['volta', 'votal'], + 'voltaic': ['volatic', 'voltaic'], + 'voltaite': ['volitate', 'voltaite'], + 'volucrine': ['involucre', 'volucrine'], + 'volunteerism': ['multinervose', 'volunteerism'], + 'vomer': ['mover', 'vomer'], + 'vomiter': ['revomit', 'vomiter'], + 'vonsenite': ['veinstone', 'vonsenite'], + 'vortical': ['victrola', 'vortical'], + 'votal': ['volta', 'votal'], + 'votary': ['travoy', 'votary'], + 'vote': ['veto', 'voet', 'vote'], + 'voteen': ['voeten', 'voteen'], + 'voter': ['overt', 'rovet', 'torve', 'trove', 'voter'], + 'vouge': ['vogue', 'vouge'], + 'vouli': ['uviol', 'vouli'], + 'vowed': ['devow', 'vowed'], + 'vowel': ['vowel', 'wolve'], + 'vraic': ['vicar', 'vraic'], + 'vrbaite': ['vibrate', 'vrbaite'], + 'vulcanite': ['vinculate', 'vulcanite'], + 'vulnerose': ['nervulose', 'unresolve', 'vulnerose'], + 'vulpic': ['pulvic', 'vulpic'], + 'vulpine': ['pluvine', 'vulpine'], + 'wa': ['aw', 'wa'], + 'waag': ['awag', 'waag'], + 'waasi': ['isawa', 'waasi'], + 'wab': ['baw', 'wab'], + 'wabi': ['biwa', 'wabi'], + 'wabster': ['bestraw', 'wabster'], + 'wac': ['caw', 'wac'], + 'wachna': ['chawan', 'chwana', 'wachna'], + 'wack': ['cawk', 'wack'], + 'wacker': ['awreck', 'wacker'], + 'wacky': ['cawky', 'wacky'], + 'wad': ['awd', 'daw', 'wad'], + 'wadder': ['edward', 'wadder', 'warded'], + 'waddler': ['dawdler', 'waddler'], + 'waddling': ['dawdling', 'waddling'], + 'waddlingly': ['dawdlingly', 'waddlingly'], + 'waddy': ['dawdy', 'waddy'], + 'wadna': ['adawn', 'wadna'], + 'wadset': ['wadset', 'wasted'], + 'wae': ['awe', 'wae', 'wea'], + 'waeg': ['waeg', 'wage', 'wega'], + 'waer': ['waer', 'ware', 'wear'], + 'waesome': ['awesome', 'waesome'], + 'wag': ['gaw', 'wag'], + 'wage': ['waeg', 'wage', 'wega'], + 'wagerer': ['rewager', 'wagerer'], + 'wages': ['swage', 'wages'], + 'waggel': ['waggel', 'waggle'], + 'waggle': ['waggel', 'waggle'], + 'wagnerite': ['wagnerite', 'winterage'], + 'wagon': ['gowan', 'wagon', 'wonga'], + 'wah': ['haw', 'hwa', 'wah', 'wha'], + 'wahehe': ['heehaw', 'wahehe'], + 'wail': ['wail', 'wali'], + 'wailer': ['lawrie', 'wailer'], + 'wain': ['awin', 'wain'], + 'wainer': ['newari', 'wainer'], + 'wairsh': ['rawish', 'wairsh', 'warish'], + 'waist': ['swati', 'waist'], + 'waister': ['swertia', 'waister'], + 'waiterage': ['garewaite', 'waiterage'], + 'waitress': ['starwise', 'waitress'], + 'waiwai': ['iwaiwa', 'waiwai'], + 'wake': ['wake', 'weak', 'weka'], + 'wakener': ['rewaken', 'wakener'], + 'waker': ['waker', 'wreak'], + 'wakes': ['askew', 'wakes'], + 'wale': ['wale', 'weal'], + 'waled': ['dwale', 'waled', 'weald'], + 'waler': ['lerwa', 'waler'], + 'wali': ['wail', 'wali'], + 'waling': ['lawing', 'waling'], + 'walk': ['lawk', 'walk'], + 'walkout': ['outwalk', 'walkout'], + 'walkover': ['overwalk', 'walkover'], + 'walkside': ['sidewalk', 'walkside'], + 'waller': ['rewall', 'waller'], + 'wallet': ['wallet', 'wellat'], + 'wallhick': ['hickwall', 'wallhick'], + 'walloper': ['preallow', 'walloper'], + 'wallower': ['rewallow', 'wallower'], + 'walsh': ['shawl', 'walsh'], + 'walt': ['twal', 'walt'], + 'walter': ['lawter', 'walter'], + 'wame': ['wame', 'weam'], + 'wamp': ['mawp', 'wamp'], + 'wan': ['awn', 'naw', 'wan'], + 'wand': ['dawn', 'wand'], + 'wander': ['andrew', 'redawn', 'wander', 'warden'], + 'wandle': ['delawn', 'lawned', 'wandle'], + 'wandlike': ['dawnlike', 'wandlike'], + 'wandy': ['dawny', 'wandy'], + 'wane': ['anew', 'wane', 'wean'], + 'waned': ['awned', 'dewan', 'waned'], + 'wang': ['gawn', 'gnaw', 'wang'], + 'wanghee': ['wanghee', 'whangee'], + 'wangler': ['wangler', 'wrangle'], + 'waning': ['awning', 'waning'], + 'wankle': ['knawel', 'wankle'], + 'wanly': ['lawny', 'wanly'], + 'want': ['nawt', 'tawn', 'want'], + 'wanty': ['tawny', 'wanty'], + 'wany': ['awny', 'wany', 'yawn'], + 'wap': ['paw', 'wap'], + 'war': ['raw', 'war'], + 'warble': ['bawler', 'brelaw', 'rebawl', 'warble'], + 'warbler': ['brawler', 'warbler'], + 'warbling': ['brawling', 'warbling'], + 'warblingly': ['brawlingly', 'warblingly'], + 'warbly': ['brawly', 'byrlaw', 'warbly'], + 'ward': ['draw', 'ward'], + 'wardable': ['drawable', 'wardable'], + 'warded': ['edward', 'wadder', 'warded'], + 'warden': ['andrew', 'redawn', 'wander', 'warden'], + 'warder': ['drawer', 'redraw', 'reward', 'warder'], + 'warderer': ['redrawer', 'rewarder', 'warderer'], + 'warding': ['drawing', 'ginward', 'warding'], + 'wardman': ['manward', 'wardman'], + 'wardmote': ['damewort', 'wardmote'], + 'wardrobe': ['drawbore', 'wardrobe'], + 'wardroom': ['roomward', 'wardroom'], + 'wardship': ['shipward', 'wardship'], + 'wardsman': ['manwards', 'wardsman'], + 'ware': ['waer', 'ware', 'wear'], + 'warehouse': ['housewear', 'warehouse'], + 'warf': ['warf', 'wraf'], + 'warish': ['rawish', 'wairsh', 'warish'], + 'warlock': ['lacwork', 'warlock'], + 'warmed': ['meward', 'warmed'], + 'warmer': ['rewarm', 'warmer'], + 'warmhouse': ['housewarm', 'warmhouse'], + 'warmish': ['warmish', 'wishram'], + 'warn': ['warn', 'wran'], + 'warnel': ['lawner', 'warnel'], + 'warner': ['rewarn', 'warner', 'warren'], + 'warp': ['warp', 'wrap'], + 'warper': ['prewar', 'rewrap', 'warper'], + 'warree': ['rewear', 'warree', 'wearer'], + 'warren': ['rewarn', 'warner', 'warren'], + 'warri': ['warri', 'wirra'], + 'warse': ['resaw', 'sawer', 'seraw', 'sware', 'swear', 'warse'], + 'warsel': ['swaler', 'warsel', 'warsle'], + 'warsle': ['swaler', 'warsel', 'warsle'], + 'warst': ['straw', 'swart', 'warst'], + 'warth': ['thraw', 'warth', 'whart', 'wrath'], + 'warua': ['warua', 'waura'], + 'warve': ['warve', 'waver'], + 'wary': ['awry', 'wary'], + 'was': ['saw', 'swa', 'was'], + 'wasel': ['swale', 'sweal', 'wasel'], + 'wash': ['shaw', 'wash'], + 'washen': ['washen', 'whenas'], + 'washer': ['hawser', 'rewash', 'washer'], + 'washington': ['nowanights', 'washington'], + 'washland': ['landwash', 'washland'], + 'washoan': ['shawano', 'washoan'], + 'washout': ['outwash', 'washout'], + 'washy': ['shawy', 'washy'], + 'wasnt': ['stawn', 'wasnt'], + 'wasp': ['swap', 'wasp'], + 'waspily': ['slipway', 'waspily'], + 'wast': ['sawt', 'staw', 'swat', 'taws', 'twas', 'wast'], + 'waste': ['awest', 'sweat', 'tawse', 'waste'], + 'wasted': ['wadset', 'wasted'], + 'wasteful': ['sweatful', 'wasteful'], + 'wasteless': ['sweatless', 'wasteless'], + 'wasteproof': ['sweatproof', 'wasteproof'], + 'wastrel': ['wastrel', 'wrastle'], + 'wat': ['taw', 'twa', 'wat'], + 'watchdog': ['dogwatch', 'watchdog'], + 'watchout': ['outwatch', 'watchout'], + 'water': ['tawer', 'water', 'wreat'], + 'waterbrain': ['brainwater', 'waterbrain'], + 'watered': ['dewater', 'tarweed', 'watered'], + 'waterer': ['rewater', 'waterer'], + 'waterflood': ['floodwater', 'toadflower', 'waterflood'], + 'waterhead': ['headwater', 'waterhead'], + 'wateriness': ['earwitness', 'wateriness'], + 'waterlog': ['galewort', 'waterlog'], + 'watershed': ['drawsheet', 'watershed'], + 'watery': ['tawery', 'watery'], + 'wath': ['thaw', 'wath', 'what'], + 'watt': ['twat', 'watt'], + 'wauf': ['awfu', 'wauf'], + 'wauner': ['unware', 'wauner'], + 'waura': ['warua', 'waura'], + 'waver': ['warve', 'waver'], + 'waxer': ['rewax', 'waxer'], + 'way': ['way', 'yaw'], + 'wayback': ['backway', 'wayback'], + 'waygang': ['gangway', 'waygang'], + 'waygate': ['gateway', 'getaway', 'waygate'], + 'wayman': ['manway', 'wayman'], + 'ways': ['sway', 'ways', 'yaws'], + 'wayside': ['sideway', 'wayside'], + 'wea': ['awe', 'wae', 'wea'], + 'weak': ['wake', 'weak', 'weka'], + 'weakener': ['reweaken', 'weakener'], + 'weakliness': ['weakliness', 'weaselskin'], + 'weal': ['wale', 'weal'], + 'weald': ['dwale', 'waled', 'weald'], + 'weam': ['wame', 'weam'], + 'wean': ['anew', 'wane', 'wean'], + 'weanel': ['leewan', 'weanel'], + 'wear': ['waer', 'ware', 'wear'], + 'wearer': ['rewear', 'warree', 'wearer'], + 'weasand': ['sandawe', 'weasand'], + 'weaselskin': ['weakliness', 'weaselskin'], + 'weather': ['weather', 'whereat', 'wreathe'], + 'weathered': ['heartweed', 'weathered'], + 'weaver': ['rewave', 'weaver'], + 'webster': ['bestrew', 'webster'], + 'wed': ['dew', 'wed'], + 'wede': ['wede', 'weed'], + 'wedge': ['gweed', 'wedge'], + 'wedger': ['edgrew', 'wedger'], + 'wedset': ['stewed', 'wedset'], + 'wee': ['ewe', 'wee'], + 'weed': ['wede', 'weed'], + 'weedhook': ['hookweed', 'weedhook'], + 'weedy': ['dewey', 'weedy'], + 'ween': ['ween', 'wene'], + 'weeps': ['sweep', 'weeps'], + 'weet': ['twee', 'weet'], + 'wega': ['waeg', 'wage', 'wega'], + 'wegotism': ['twigsome', 'wegotism'], + 'weigher': ['reweigh', 'weigher'], + 'weir': ['weir', 'weri', 'wire'], + 'weirangle': ['weirangle', 'wierangle'], + 'weird': ['weird', 'wired', 'wride', 'wried'], + 'weka': ['wake', 'weak', 'weka'], + 'weld': ['lewd', 'weld'], + 'weldable': ['ballweed', 'weldable'], + 'welder': ['reweld', 'welder'], + 'weldor': ['lowder', 'weldor', 'wordle'], + 'welf': ['flew', 'welf'], + 'welkin': ['welkin', 'winkel', 'winkle'], + 'well': ['llew', 'well'], + 'wellat': ['wallet', 'wellat'], + 'wels': ['slew', 'wels'], + 'welshry': ['shrewly', 'welshry'], + 'welting': ['twingle', 'welting', 'winglet'], + 'wem': ['mew', 'wem'], + 'wen': ['new', 'wen'], + 'wende': ['endew', 'wende'], + 'wendi': ['dwine', 'edwin', 'wendi', 'widen', 'wined'], + 'wene': ['ween', 'wene'], + 'went': ['newt', 'went'], + 'were': ['ewer', 'were'], + 'weri': ['weir', 'weri', 'wire'], + 'werther': ['werther', 'wherret'], + 'wes': ['sew', 'wes'], + 'weskit': ['weskit', 'wisket'], + 'west': ['stew', 'west'], + 'weste': ['sweet', 'weste'], + 'westering': ['swingtree', 'westering'], + 'westy': ['stewy', 'westy'], + 'wet': ['tew', 'wet'], + 'weta': ['tewa', 'twae', 'weta'], + 'wetly': ['tewly', 'wetly'], + 'wey': ['wey', 'wye', 'yew'], + 'wha': ['haw', 'hwa', 'wah', 'wha'], + 'whack': ['chawk', 'whack'], + 'whale': ['whale', 'wheal'], + 'wham': ['hawm', 'wham'], + 'whame': ['whame', 'wheam'], + 'whangee': ['wanghee', 'whangee'], + 'whare': ['hawer', 'whare'], + 'whart': ['thraw', 'warth', 'whart', 'wrath'], + 'whase': ['hawse', 'shewa', 'whase'], + 'what': ['thaw', 'wath', 'what'], + 'whatreck': ['thwacker', 'whatreck'], + 'whats': ['swath', 'whats'], + 'wheal': ['whale', 'wheal'], + 'wheam': ['whame', 'wheam'], + 'wheat': ['awhet', 'wheat'], + 'wheatear': ['aweather', 'wheatear'], + 'wheedle': ['wheedle', 'wheeled'], + 'wheel': ['hewel', 'wheel'], + 'wheeled': ['wheedle', 'wheeled'], + 'wheelroad': ['rowelhead', 'wheelroad'], + 'wheer': ['hewer', 'wheer', 'where'], + 'whein': ['whein', 'whine'], + 'when': ['hewn', 'when'], + 'whenas': ['washen', 'whenas'], + 'whenso': ['whenso', 'whosen'], + 'where': ['hewer', 'wheer', 'where'], + 'whereat': ['weather', 'whereat', 'wreathe'], + 'whereon': ['nowhere', 'whereon'], + 'wherret': ['werther', 'wherret'], + 'wherrit': ['wherrit', 'whirret', 'writher'], + 'whet': ['hewt', 'thew', 'whet'], + 'whichever': ['everwhich', 'whichever'], + 'whicken': ['chewink', 'whicken'], + 'whilter': ['whilter', 'whirtle'], + 'whine': ['whein', 'whine'], + 'whipper': ['prewhip', 'whipper'], + 'whirler': ['rewhirl', 'whirler'], + 'whirret': ['wherrit', 'whirret', 'writher'], + 'whirtle': ['whilter', 'whirtle'], + 'whisperer': ['rewhisper', 'whisperer'], + 'whisson': ['snowish', 'whisson'], + 'whist': ['swith', 'whist', 'whits', 'wisht'], + 'whister': ['swither', 'whister', 'withers'], + 'whit': ['whit', 'with'], + 'white': ['white', 'withe'], + 'whiten': ['whiten', 'withen'], + 'whitener': ['rewhiten', 'whitener'], + 'whitepot': ['whitepot', 'whitetop'], + 'whites': ['swithe', 'whites'], + 'whitetop': ['whitepot', 'whitetop'], + 'whitewood': ['whitewood', 'withewood'], + 'whitleather': ['therewithal', 'whitleather'], + 'whitmanese': ['anthemwise', 'whitmanese'], + 'whits': ['swith', 'whist', 'whits', 'wisht'], + 'whity': ['whity', 'withy'], + 'who': ['how', 'who'], + 'whoever': ['everwho', 'however', 'whoever'], + 'whole': ['howel', 'whole'], + 'whomsoever': ['howsomever', 'whomsoever', 'whosomever'], + 'whoreship': ['horsewhip', 'whoreship'], + 'whort': ['throw', 'whort', 'worth', 'wroth'], + 'whosen': ['whenso', 'whosen'], + 'whosomever': ['howsomever', 'whomsoever', 'whosomever'], + 'wicht': ['tchwi', 'wicht', 'witch'], + 'widdle': ['widdle', 'wilded'], + 'widely': ['dewily', 'widely', 'wieldy'], + 'widen': ['dwine', 'edwin', 'wendi', 'widen', 'wined'], + 'widener': ['rewiden', 'widener'], + 'wideness': ['dewiness', 'wideness'], + 'widgeon': ['gowdnie', 'widgeon'], + 'wieldy': ['dewily', 'widely', 'wieldy'], + 'wierangle': ['weirangle', 'wierangle'], + 'wigan': ['awing', 'wigan'], + 'wiggler': ['wiggler', 'wriggle'], + 'wilded': ['widdle', 'wilded'], + 'wildness': ['wildness', 'windless'], + 'winchester': ['trenchwise', 'winchester'], + 'windbreak': ['breakwind', 'windbreak'], + 'winder': ['rewind', 'winder'], + 'windgall': ['dingwall', 'windgall'], + 'windles': ['swindle', 'windles'], + 'windless': ['wildness', 'windless'], + 'windstorm': ['stormwind', 'windstorm'], + 'windup': ['upwind', 'windup'], + 'wined': ['dwine', 'edwin', 'wendi', 'widen', 'wined'], + 'winer': ['erwin', 'rewin', 'winer'], + 'winglet': ['twingle', 'welting', 'winglet'], + 'winkel': ['welkin', 'winkel', 'winkle'], + 'winkle': ['welkin', 'winkel', 'winkle'], + 'winklet': ['twinkle', 'winklet'], + 'winnard': ['indrawn', 'winnard'], + 'winnel': ['winnel', 'winnle'], + 'winnle': ['winnel', 'winnle'], + 'winsome': ['owenism', 'winsome'], + 'wint': ['twin', 'wint'], + 'winter': ['twiner', 'winter'], + 'winterage': ['wagnerite', 'winterage'], + 'wintered': ['interwed', 'wintered'], + 'winterish': ['interwish', 'winterish'], + 'winze': ['winze', 'wizen'], + 'wips': ['wips', 'wisp'], + 'wire': ['weir', 'weri', 'wire'], + 'wired': ['weird', 'wired', 'wride', 'wried'], + 'wirer': ['wirer', 'wrier'], + 'wirra': ['warri', 'wirra'], + 'wiselike': ['likewise', 'wiselike'], + 'wiseman': ['manwise', 'wiseman'], + 'wisen': ['sinew', 'swine', 'wisen'], + 'wiser': ['swire', 'wiser'], + 'wisewoman': ['wisewoman', 'womanwise'], + 'wisher': ['rewish', 'wisher'], + 'wishmay': ['wishmay', 'yahwism'], + 'wishram': ['warmish', 'wishram'], + 'wisht': ['swith', 'whist', 'whits', 'wisht'], + 'wisket': ['weskit', 'wisket'], + 'wisp': ['wips', 'wisp'], + 'wispy': ['swipy', 'wispy'], + 'wit': ['twi', 'wit'], + 'witan': ['atwin', 'twain', 'witan'], + 'witch': ['tchwi', 'wicht', 'witch'], + 'witchetty': ['twitchety', 'witchetty'], + 'with': ['whit', 'with'], + 'withdrawer': ['rewithdraw', 'withdrawer'], + 'withe': ['white', 'withe'], + 'withen': ['whiten', 'withen'], + 'wither': ['wither', 'writhe'], + 'withered': ['redwithe', 'withered'], + 'withering': ['withering', 'wrightine'], + 'withers': ['swither', 'whister', 'withers'], + 'withewood': ['whitewood', 'withewood'], + 'within': ['inwith', 'within'], + 'without': ['outwith', 'without'], + 'withy': ['whity', 'withy'], + 'wive': ['view', 'wive'], + 'wiver': ['wiver', 'wrive'], + 'wizen': ['winze', 'wizen'], + 'wo': ['ow', 'wo'], + 'woader': ['redowa', 'woader'], + 'wob': ['bow', 'wob'], + 'wod': ['dow', 'owd', 'wod'], + 'woe': ['owe', 'woe'], + 'woibe': ['bowie', 'woibe'], + 'wold': ['dowl', 'wold'], + 'wolf': ['flow', 'fowl', 'wolf'], + 'wolfer': ['flower', 'fowler', 'reflow', 'wolfer'], + 'wolter': ['rowlet', 'trowel', 'wolter'], + 'wolve': ['vowel', 'wolve'], + 'womanpost': ['postwoman', 'womanpost'], + 'womanwise': ['wisewoman', 'womanwise'], + 'won': ['now', 'own', 'won'], + 'wonder': ['downer', 'wonder', 'worden'], + 'wonderful': ['underflow', 'wonderful'], + 'wone': ['enow', 'owen', 'wone'], + 'wong': ['gown', 'wong'], + 'wonga': ['gowan', 'wagon', 'wonga'], + 'wonner': ['renown', 'wonner'], + 'wont': ['nowt', 'town', 'wont'], + 'wonted': ['towned', 'wonted'], + 'woodbark': ['bookward', 'woodbark'], + 'woodbind': ['bindwood', 'woodbind'], + 'woodbush': ['bushwood', 'woodbush'], + 'woodchat': ['chatwood', 'woodchat'], + 'wooden': ['enwood', 'wooden'], + 'woodfish': ['fishwood', 'woodfish'], + 'woodhack': ['hackwood', 'woodhack'], + 'woodhorse': ['horsewood', 'woodhorse'], + 'woodness': ['sowdones', 'woodness'], + 'woodpecker': ['peckerwood', 'woodpecker'], + 'woodrock': ['corkwood', 'rockwood', 'woodrock'], + 'woodsilver': ['silverwood', 'woodsilver'], + 'woodstone': ['stonewood', 'woodstone'], + 'woodworm': ['woodworm', 'wormwood'], + 'wooled': ['dewool', 'elwood', 'wooled'], + 'woons': ['swoon', 'woons'], + 'woosh': ['howso', 'woosh'], + 'wop': ['pow', 'wop'], + 'worble': ['blower', 'bowler', 'reblow', 'worble'], + 'word': ['drow', 'word'], + 'wordage': ['dowager', 'wordage'], + 'worden': ['downer', 'wonder', 'worden'], + 'worder': ['reword', 'worder'], + 'wordily': ['rowdily', 'wordily'], + 'wordiness': ['rowdiness', 'wordiness'], + 'wordle': ['lowder', 'weldor', 'wordle'], + 'wordsman': ['sandworm', 'swordman', 'wordsman'], + 'wordsmanship': ['swordmanship', 'wordsmanship'], + 'wordy': ['dowry', 'rowdy', 'wordy'], + 'wore': ['ower', 'wore'], + 'workbasket': ['basketwork', 'workbasket'], + 'workbench': ['benchwork', 'workbench'], + 'workbook': ['bookwork', 'workbook'], + 'workbox': ['boxwork', 'workbox'], + 'workday': ['daywork', 'workday'], + 'worker': ['rework', 'worker'], + 'workhand': ['handwork', 'workhand'], + 'workhouse': ['housework', 'workhouse'], + 'working': ['kingrow', 'working'], + 'workmaster': ['masterwork', 'workmaster'], + 'workout': ['outwork', 'workout'], + 'workpiece': ['piecework', 'workpiece'], + 'workship': ['shipwork', 'workship'], + 'workshop': ['shopwork', 'workshop'], + 'worktime': ['timework', 'worktime'], + 'wormed': ['deworm', 'wormed'], + 'wormer': ['merrow', 'wormer'], + 'wormroot': ['moorwort', 'rootworm', 'tomorrow', 'wormroot'], + 'wormship': ['shipworm', 'wormship'], + 'wormwood': ['woodworm', 'wormwood'], + 'worse': ['owser', 'resow', 'serow', 'sower', 'swore', 'worse'], + 'worset': ['restow', 'stower', 'towser', 'worset'], + 'worst': ['strow', 'worst'], + 'wort': ['trow', 'wort'], + 'worth': ['throw', 'whort', 'worth', 'wroth'], + 'worthful': ['worthful', 'wrothful'], + 'worthily': ['worthily', 'wrothily'], + 'worthiness': ['worthiness', 'wrothiness'], + 'worthy': ['worthy', 'wrothy'], + 'wot': ['tow', 'two', 'wot'], + 'wots': ['sowt', 'stow', 'swot', 'wots'], + 'wounder': ['rewound', 'unrowed', 'wounder'], + 'woy': ['woy', 'yow'], + 'wraf': ['warf', 'wraf'], + 'wrainbolt': ['browntail', 'wrainbolt'], + 'wraitly': ['wraitly', 'wrytail'], + 'wran': ['warn', 'wran'], + 'wrangle': ['wangler', 'wrangle'], + 'wrap': ['warp', 'wrap'], + 'wrapper': ['prewrap', 'wrapper'], + 'wrastle': ['wastrel', 'wrastle'], + 'wrath': ['thraw', 'warth', 'whart', 'wrath'], + 'wreak': ['waker', 'wreak'], + 'wreat': ['tawer', 'water', 'wreat'], + 'wreath': ['rethaw', 'thawer', 'wreath'], + 'wreathe': ['weather', 'whereat', 'wreathe'], + 'wrest': ['strew', 'trews', 'wrest'], + 'wrester': ['strewer', 'wrester'], + 'wrestle': ['swelter', 'wrestle'], + 'wride': ['weird', 'wired', 'wride', 'wried'], + 'wried': ['weird', 'wired', 'wride', 'wried'], + 'wrier': ['wirer', 'wrier'], + 'wriggle': ['wiggler', 'wriggle'], + 'wrightine': ['withering', 'wrightine'], + 'wrinklet': ['twinkler', 'wrinklet'], + 'write': ['twire', 'write'], + 'writhe': ['wither', 'writhe'], + 'writher': ['wherrit', 'whirret', 'writher'], + 'written': ['twinter', 'written'], + 'wrive': ['wiver', 'wrive'], + 'wro': ['row', 'wro'], + 'wroken': ['knower', 'reknow', 'wroken'], + 'wrong': ['grown', 'wrong'], + 'wrote': ['rowet', 'tower', 'wrote'], + 'wroth': ['throw', 'whort', 'worth', 'wroth'], + 'wrothful': ['worthful', 'wrothful'], + 'wrothily': ['worthily', 'wrothily'], + 'wrothiness': ['worthiness', 'wrothiness'], + 'wrothy': ['worthy', 'wrothy'], + 'wrytail': ['wraitly', 'wrytail'], + 'wunna': ['unwan', 'wunna'], + 'wyde': ['dewy', 'wyde'], + 'wye': ['wey', 'wye', 'yew'], + 'wype': ['pewy', 'wype'], + 'wyson': ['snowy', 'wyson'], + 'xanthein': ['xanthein', 'xanthine'], + 'xanthine': ['xanthein', 'xanthine'], + 'xanthopurpurin': ['purpuroxanthin', 'xanthopurpurin'], + 'xema': ['amex', 'exam', 'xema'], + 'xenia': ['axine', 'xenia'], + 'xenial': ['alexin', 'xenial'], + 'xenoparasite': ['exasperation', 'xenoparasite'], + 'xeres': ['resex', 'xeres'], + 'xerophytic': ['hypertoxic', 'xerophytic'], + 'xerotic': ['excitor', 'xerotic'], + 'xylic': ['cylix', 'xylic'], + 'xylitone': ['xylitone', 'xylonite'], + 'xylonite': ['xylitone', 'xylonite'], + 'xylophone': ['oxyphenol', 'xylophone'], + 'xylose': ['lyxose', 'xylose'], + 'xyst': ['styx', 'xyst'], + 'xyster': ['sextry', 'xyster'], + 'xysti': ['sixty', 'xysti'], + 'ya': ['ay', 'ya'], + 'yaba': ['baya', 'yaba'], + 'yabber': ['babery', 'yabber'], + 'yacht': ['cathy', 'cyath', 'yacht'], + 'yachtist': ['chastity', 'yachtist'], + 'yad': ['ady', 'day', 'yad'], + 'yaff': ['affy', 'yaff'], + 'yagnob': ['boyang', 'yagnob'], + 'yah': ['hay', 'yah'], + 'yahwism': ['wishmay', 'yahwism'], + 'yair': ['airy', 'yair'], + 'yaird': ['dairy', 'diary', 'yaird'], + 'yak': ['kay', 'yak'], + 'yakan': ['kayan', 'yakan'], + 'yakima': ['kamiya', 'yakima'], + 'yakka': ['kayak', 'yakka'], + 'yalb': ['ably', 'blay', 'yalb'], + 'yali': ['ilya', 'yali'], + 'yalla': ['allay', 'yalla'], + 'yallaer': ['allayer', 'yallaer'], + 'yam': ['amy', 'may', 'mya', 'yam'], + 'yamel': ['mealy', 'yamel'], + 'yamen': ['maney', 'yamen'], + 'yamilke': ['maylike', 'yamilke'], + 'yamph': ['phyma', 'yamph'], + 'yan': ['any', 'nay', 'yan'], + 'yana': ['anay', 'yana'], + 'yander': ['denary', 'yander'], + 'yap': ['pay', 'pya', 'yap'], + 'yapness': ['synapse', 'yapness'], + 'yapper': ['papery', 'prepay', 'yapper'], + 'yapster': ['atrepsy', 'yapster'], + 'yar': ['ary', 'ray', 'yar'], + 'yarb': ['bray', 'yarb'], + 'yard': ['adry', 'dray', 'yard'], + 'yardage': ['drayage', 'yardage'], + 'yarder': ['dreary', 'yarder'], + 'yardman': ['drayman', 'yardman'], + 'yare': ['aery', 'eyra', 'yare', 'year'], + 'yark': ['kyar', 'yark'], + 'yarl': ['aryl', 'lyra', 'ryal', 'yarl'], + 'yarm': ['army', 'mary', 'myra', 'yarm'], + 'yarn': ['nary', 'yarn'], + 'yarr': ['arry', 'yarr'], + 'yarrow': ['arrowy', 'yarrow'], + 'yaruran': ['unarray', 'yaruran'], + 'yas': ['say', 'yas'], + 'yasht': ['hasty', 'yasht'], + 'yat': ['tay', 'yat'], + 'yate': ['yate', 'yeat', 'yeta'], + 'yatter': ['attery', 'treaty', 'yatter'], + 'yaw': ['way', 'yaw'], + 'yawler': ['lawyer', 'yawler'], + 'yawn': ['awny', 'wany', 'yawn'], + 'yaws': ['sway', 'ways', 'yaws'], + 'ye': ['ey', 'ye'], + 'yea': ['aye', 'yea'], + 'yeah': ['ahey', 'eyah', 'yeah'], + 'year': ['aery', 'eyra', 'yare', 'year'], + 'yeard': ['deary', 'deray', 'rayed', 'ready', 'yeard'], + 'yearly': ['layery', 'yearly'], + 'yearn': ['enray', 'yearn'], + 'yearth': ['earthy', 'hearty', 'yearth'], + 'yeast': ['teasy', 'yeast'], + 'yeat': ['yate', 'yeat', 'yeta'], + 'yeather': ['erythea', 'hetaery', 'yeather'], + 'yed': ['dey', 'dye', 'yed'], + 'yede': ['eyed', 'yede'], + 'yee': ['eye', 'yee'], + 'yeel': ['eely', 'yeel'], + 'yees': ['yees', 'yese'], + 'yegg': ['eggy', 'yegg'], + 'yelk': ['kyle', 'yelk'], + 'yelm': ['elmy', 'yelm'], + 'yelmer': ['merely', 'yelmer'], + 'yelper': ['peerly', 'yelper'], + 'yemen': ['enemy', 'yemen'], + 'yemeni': ['menyie', 'yemeni'], + 'yen': ['eyn', 'nye', 'yen'], + 'yender': ['redeny', 'yender'], + 'yeo': ['yeo', 'yoe'], + 'yeorling': ['legionry', 'yeorling'], + 'yer': ['rye', 'yer'], + 'yerb': ['brey', 'byre', 'yerb'], + 'yerba': ['barye', 'beray', 'yerba'], + 'yerd': ['dyer', 'yerd'], + 'yere': ['eyer', 'eyre', 'yere'], + 'yern': ['ryen', 'yern'], + 'yes': ['sey', 'sye', 'yes'], + 'yese': ['yees', 'yese'], + 'yest': ['stey', 'yest'], + 'yester': ['reesty', 'yester'], + 'yestern': ['streyne', 'styrene', 'yestern'], + 'yet': ['tye', 'yet'], + 'yeta': ['yate', 'yeat', 'yeta'], + 'yeth': ['they', 'yeth'], + 'yether': ['theyre', 'yether'], + 'yetlin': ['lenity', 'yetlin'], + 'yew': ['wey', 'wye', 'yew'], + 'yielden': ['needily', 'yielden'], + 'yielder': ['reedily', 'reyield', 'yielder'], + 'yildun': ['unidly', 'yildun'], + 'yill': ['illy', 'lily', 'yill'], + 'yirm': ['miry', 'rimy', 'yirm'], + 'ym': ['my', 'ym'], + 'yock': ['coky', 'yock'], + 'yodel': ['doyle', 'yodel'], + 'yoe': ['yeo', 'yoe'], + 'yoghurt': ['troughy', 'yoghurt'], + 'yogin': ['goyin', 'yogin'], + 'yoi': ['iyo', 'yoi'], + 'yoker': ['rokey', 'yoker'], + 'yolk': ['kylo', 'yolk'], + 'yom': ['moy', 'yom'], + 'yomud': ['moudy', 'yomud'], + 'yon': ['noy', 'yon'], + 'yond': ['ondy', 'yond'], + 'yonder': ['rodney', 'yonder'], + 'yont': ['tony', 'yont'], + 'yor': ['ory', 'roy', 'yor'], + 'yore': ['oyer', 'roey', 'yore'], + 'york': ['kory', 'roky', 'york'], + 'yot': ['toy', 'yot'], + 'yote': ['eyot', 'yote'], + 'youngun': ['unyoung', 'youngun'], + 'yours': ['soury', 'yours'], + 'yoursel': ['elusory', 'yoursel'], + 'yoven': ['envoy', 'nevoy', 'yoven'], + 'yow': ['woy', 'yow'], + 'yowl': ['lowy', 'owly', 'yowl'], + 'yowler': ['lowery', 'owlery', 'rowley', 'yowler'], + 'yowt': ['towy', 'yowt'], + 'yox': ['oxy', 'yox'], + 'yttrious': ['touristy', 'yttrious'], + 'yuca': ['cuya', 'yuca'], + 'yuckel': ['yuckel', 'yuckle'], + 'yuckle': ['yuckel', 'yuckle'], + 'yulan': ['unlay', 'yulan'], + 'yurok': ['rouky', 'yurok'], + 'zabian': ['banzai', 'zabian'], + 'zabra': ['braza', 'zabra'], + 'zacate': ['azteca', 'zacate'], + 'zad': ['adz', 'zad'], + 'zag': ['gaz', 'zag'], + 'zain': ['nazi', 'zain'], + 'zaman': ['namaz', 'zaman'], + 'zamenis': ['sizeman', 'zamenis'], + 'zaparoan': ['parazoan', 'zaparoan'], + 'zaratite': ['tatarize', 'zaratite'], + 'zati': ['itza', 'tiza', 'zati'], + 'zeal': ['laze', 'zeal'], + 'zealotism': ['solmizate', 'zealotism'], + 'zebra': ['braze', 'zebra'], + 'zein': ['inez', 'zein'], + 'zelanian': ['annalize', 'zelanian'], + 'zelatrice': ['cartelize', 'zelatrice'], + 'zemmi': ['zemmi', 'zimme'], + 'zendic': ['dezinc', 'zendic'], + 'zenick': ['zenick', 'zincke'], + 'zenu': ['unze', 'zenu'], + 'zequin': ['quinze', 'zequin'], + 'zerda': ['adzer', 'zerda'], + 'zerma': ['mazer', 'zerma'], + 'ziarat': ['atazir', 'ziarat'], + 'zibet': ['bizet', 'zibet'], + 'ziega': ['gaize', 'ziega'], + 'zimme': ['zemmi', 'zimme'], + 'zincite': ['citizen', 'zincite'], + 'zincke': ['zenick', 'zincke'], + 'zinco': ['zinco', 'zonic'], + 'zion': ['nozi', 'zion'], + 'zira': ['izar', 'zira'], + 'zirconate': ['narcotize', 'zirconate'], + 'zoa': ['azo', 'zoa'], + 'zoanthidae': ['zoanthidae', 'zoanthidea'], + 'zoanthidea': ['zoanthidae', 'zoanthidea'], + 'zoarite': ['azorite', 'zoarite'], + 'zobo': ['bozo', 'zobo'], + 'zoeal': ['azole', 'zoeal'], + 'zogan': ['gazon', 'zogan'], + 'zolotink': ['zolotink', 'zolotnik'], + 'zolotnik': ['zolotink', 'zolotnik'], + 'zonaria': ['arizona', 'azorian', 'zonaria'], + 'zoned': ['dozen', 'zoned'], + 'zonic': ['zinco', 'zonic'], + 'zonotrichia': ['chorization', 'rhizoctonia', 'zonotrichia'], + 'zoonal': ['alonzo', 'zoonal'], + 'zoonic': ['ozonic', 'zoonic'], + 'zoonomic': ['monozoic', 'zoonomic'], + 'zoopathy': ['phytozoa', 'zoopathy', 'zoophyta'], + 'zoophilic': ['philozoic', 'zoophilic'], + 'zoophilist': ['philozoist', 'zoophilist'], + 'zoophyta': ['phytozoa', 'zoopathy', 'zoophyta'], + 'zoospermatic': ['spermatozoic', 'zoospermatic'], + 'zoosporic': ['sporozoic', 'zoosporic'], + 'zootype': ['ozotype', 'zootype'], + 'zyga': ['gazy', 'zyga'], + 'zygal': ['glazy', 'zygal']} \ No newline at end of file From ed4c92d98af4b96605a0463bc94143b9c771a7cd Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj Date: Mon, 8 Nov 2021 23:48:30 +0530 Subject: [PATCH 221/726] [mypy] Type annotations for graphs directory (#5798) * Type annotations for `breadth_first_search.py` * Type annotations for `breadth_first_search_2.py` * Remove from excluded in mypy.ini * Add doctest.testmod() * Type annotations for `graphs/check_cycle.py` * Type annotations for `graphs/greedy_min_vertex_cover.py` * Remove from excluded in mypy.ini --- graphs/breadth_first_search.py | 2 +- graphs/breadth_first_search_2.py | 5 ++++- graphs/check_cycle.py | 6 ++---- graphs/greedy_min_vertex_cover.py | 9 ++++----- mypy.ini | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/graphs/breadth_first_search.py b/graphs/breadth_first_search.py index 9264f57b4..171d3875f 100644 --- a/graphs/breadth_first_search.py +++ b/graphs/breadth_first_search.py @@ -53,7 +53,7 @@ class Graph: visited = set() # create a first in first out queue to store all the vertices for BFS - queue = Queue() + queue: Queue = Queue() # mark the source node as visited and enqueue it visited.add(start_vertex) diff --git a/graphs/breadth_first_search_2.py b/graphs/breadth_first_search_2.py index 4c8b69faf..2f060a90d 100644 --- a/graphs/breadth_first_search_2.py +++ b/graphs/breadth_first_search_2.py @@ -32,7 +32,7 @@ def breadth_first_search(graph: dict, start: str) -> set[str]: 'ABCDEF' """ explored = {start} - queue = Queue() + queue: Queue = Queue() queue.put(start) while not queue.empty(): v = queue.get() @@ -44,4 +44,7 @@ def breadth_first_search(graph: dict, start: str) -> set[str]: if __name__ == "__main__": + import doctest + + doctest.testmod() print(breadth_first_search(G, "A")) diff --git a/graphs/check_cycle.py b/graphs/check_cycle.py index 71d42b468..dcc864988 100644 --- a/graphs/check_cycle.py +++ b/graphs/check_cycle.py @@ -6,16 +6,15 @@ Program to check if a cycle is present in a given graph def check_cycle(graph: dict) -> bool: """ Returns True if graph is cyclic else False - >>> check_cycle(graph={0:[], 1:[0, 3], 2:[0, 4], 3:[5], 4:[5], 5:[]}) False >>> check_cycle(graph={0:[1, 2], 1:[2], 2:[0, 3], 3:[3]}) True """ # Keep track of visited nodes - visited = set() + visited: set[int] = set() # To detect a back edge, keep track of vertices currently in the recursion stack - rec_stk = set() + rec_stk: set[int] = set() for node in graph: if node not in visited: if depth_first_search(graph, node, visited, rec_stk): @@ -27,7 +26,6 @@ def depth_first_search(graph: dict, vertex: int, visited: set, rec_stk: set) -> """ Recur for all neighbours. If any neighbour is visited and in rec_stk then graph is cyclic. - >>> graph = {0:[], 1:[0, 3], 2:[0, 4], 3:[5], 4:[5], 5:[]} >>> vertex, visited, rec_stk = 0, set(), set() >>> depth_first_search(graph, vertex, visited, rec_stk) diff --git a/graphs/greedy_min_vertex_cover.py b/graphs/greedy_min_vertex_cover.py index 056c5b89b..cdef69141 100644 --- a/graphs/greedy_min_vertex_cover.py +++ b/graphs/greedy_min_vertex_cover.py @@ -2,7 +2,6 @@ * Author: Manuel Di Lullo (https://github.com/manueldilullo) * Description: Approximization algorithm for minimum vertex cover problem. Greedy Approach. Uses graphs represented with an adjacency list - URL: https://mathworld.wolfram.com/MinimumVertexCover.html URL: https://cs.stackexchange.com/questions/129017/greedy-algorithm-for-vertex-cover """ @@ -10,7 +9,7 @@ URL: https://cs.stackexchange.com/questions/129017/greedy-algorithm-for-vertex-c import heapq -def greedy_min_vertex_cover(graph: dict) -> set: +def greedy_min_vertex_cover(graph: dict) -> set[int]: """ Greedy APX Algorithm for min Vertex Cover @input: graph (graph stored in an adjacency list where each vertex @@ -21,7 +20,7 @@ def greedy_min_vertex_cover(graph: dict) -> set: {0, 1, 2, 4} """ # queue used to store nodes and their rank - queue = [] + queue: list[list] = [] # for each node and his adjacency list add them and the rank of the node to queue # using heapq module the queue will be filled like a Priority Queue @@ -61,5 +60,5 @@ if __name__ == "__main__": doctest.testmod() - # graph = {0: [1, 3], 1: [0, 3], 2: [0, 3, 4], 3: [0, 1, 2], 4: [2, 3]} - # print(f"Minimum vertex cover:\n{greedy_min_vertex_cover(graph)}") + graph = {0: [1, 3], 1: [0, 3], 2: [0, 3, 4], 3: [0, 1, 2], 4: [2, 3]} + print(f"Minimum vertex cover:\n{greedy_min_vertex_cover(graph)}") diff --git a/mypy.ini b/mypy.ini index 429c6804d..ce7c262ab 100644 --- a/mypy.ini +++ b/mypy.ini @@ -2,4 +2,4 @@ ignore_missing_imports = True install_types = True non_interactive = True -exclude = (graphs/breadth_first_search.py|graphs/breadth_first_search_2.py|graphs/check_cycle.py|graphs/greedy_min_vertex_cover.py|matrix_operation.py|other/least_recently_used.py|other/lfu_cache.py|other/lru_cache.py|searches/simulated_annealing.py|searches/ternary_search.py) +exclude = (matrix_operation.py|other/least_recently_used.py|other/lfu_cache.py|other/lru_cache.py|searches/simulated_annealing.py|searches/ternary_search.py) From 0b8d6d70cea06eabc19b40a4e583efe62c2c0c2e Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Tue, 9 Nov 2021 17:25:29 +0300 Subject: [PATCH 222/726] Add Project Euler problem 205 solution 1 (#5781) * updating DIRECTORY.md * Add solution * updating DIRECTORY.md * Fix * Fix Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 2 + project_euler/problem_205/__init__.py | 0 project_euler/problem_205/sol1.py | 75 +++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 project_euler/problem_205/__init__.py create mode 100644 project_euler/problem_205/sol1.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 228d95472..a2f229a9e 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -865,6 +865,8 @@ * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_191/sol1.py) * Problem 203 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_203/sol1.py) + * Problem 205 + * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_205/sol1.py) * Problem 206 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_206/sol1.py) * Problem 207 diff --git a/project_euler/problem_205/__init__.py b/project_euler/problem_205/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_205/sol1.py b/project_euler/problem_205/sol1.py new file mode 100644 index 000000000..7249df488 --- /dev/null +++ b/project_euler/problem_205/sol1.py @@ -0,0 +1,75 @@ +""" +Project Euler Problem 205: https://projecteuler.net/problem=205 + +Peter has nine four-sided (pyramidal) dice, each with faces numbered 1, 2, 3, 4. +Colin has six six-sided (cubic) dice, each with faces numbered 1, 2, 3, 4, 5, 6. + +Peter and Colin roll their dice and compare totals: the highest total wins. +The result is a draw if the totals are equal. + +What is the probability that Pyramidal Peter beats Cubic Colin? +Give your answer rounded to seven decimal places in the form 0.abcdefg +""" + +from itertools import product + + +def total_frequency_distribution(sides_number: int, dice_number: int) -> list[int]: + """ + Returns frequency distribution of total + + >>> total_frequency_distribution(sides_number=6, dice_number=1) + [0, 1, 1, 1, 1, 1, 1] + + >>> total_frequency_distribution(sides_number=4, dice_number=2) + [0, 0, 1, 2, 3, 4, 3, 2, 1] + """ + + max_face_number = sides_number + max_total = max_face_number * dice_number + totals_frequencies = [0] * (max_total + 1) + + min_face_number = 1 + faces_numbers = range(min_face_number, max_face_number + 1) + for dice_numbers in product(faces_numbers, repeat=dice_number): + total = sum(dice_numbers) + totals_frequencies[total] += 1 + + return totals_frequencies + + +def solution() -> float: + """ + Returns probability that Pyramidal Peter beats Cubic Colin + rounded to seven decimal places in the form 0.abcdefg + + >>> solution() + 0.5731441 + """ + + peter_totals_frequencies = total_frequency_distribution( + sides_number=4, dice_number=9 + ) + colin_totals_frequencies = total_frequency_distribution( + sides_number=6, dice_number=6 + ) + + peter_wins_count = 0 + min_peter_total = 9 + max_peter_total = 4 * 9 + min_colin_total = 6 + for peter_total in range(min_peter_total, max_peter_total + 1): + peter_wins_count += peter_totals_frequencies[peter_total] * sum( + colin_totals_frequencies[min_colin_total:peter_total] + ) + + total_games_number = (4 ** 9) * (6 ** 6) + peter_win_probability = peter_wins_count / total_games_number + + rounded_peter_win_probability = round(peter_win_probability, ndigits=7) + + return rounded_peter_win_probability + + +if __name__ == "__main__": + print(f"{solution() = }") From c3d1ff0ebd034eeb6105ef8bad6a3c962efa56f2 Mon Sep 17 00:00:00 2001 From: Nivas Manduva <53264470+eviltypha@users.noreply.github.com> Date: Tue, 9 Nov 2021 20:10:57 +0530 Subject: [PATCH 223/726] Add Jacobi Iteration Method (#5113) * Added Jacobi Iteration Method Added this method in arithmetic_analysis folder. This method is used to solve system of linear equations. * Added comments * Added reference link * Update jacobi_iteration_method.py * Changes for codespell test * Update jacobi_iteration_method.py * Update jacobi_iteration_method.py * Update arithmetic_analysis/jacobi_iteration_method.py Co-authored-by: Christian Clauss * updating DIRECTORY.md * Update arithmetic_analysis/jacobi_iteration_method.py Co-authored-by: Christian Clauss * Update arithmetic_analysis/jacobi_iteration_method.py Co-authored-by: Christian Clauss * Update arithmetic_analysis/jacobi_iteration_method.py Co-authored-by: Christian Clauss * Update arithmetic_analysis/jacobi_iteration_method.py Co-authored-by: Christian Clauss * Update arithmetic_analysis/jacobi_iteration_method.py Co-authored-by: Christian Clauss * Update arithmetic_analysis/jacobi_iteration_method.py Co-authored-by: Christian Clauss * Update jacobi_iteration_method.py * Update jacobi_iteration_method.py * Update jacobi_iteration_method.py * fix styles Co-authored-by: Christian Clauss Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: John Law --- DIRECTORY.md | 1 + .../jacobi_iteration_method.py | 163 ++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 arithmetic_analysis/jacobi_iteration_method.py diff --git a/DIRECTORY.md b/DIRECTORY.md index a2f229a9e..883b81b24 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -4,6 +4,7 @@ * [Gaussian Elimination](https://github.com/TheAlgorithms/Python/blob/master/arithmetic_analysis/gaussian_elimination.py) * [In Static Equilibrium](https://github.com/TheAlgorithms/Python/blob/master/arithmetic_analysis/in_static_equilibrium.py) * [Intersection](https://github.com/TheAlgorithms/Python/blob/master/arithmetic_analysis/intersection.py) + * [Jacobi Iteration Method](https://github.com/TheAlgorithms/Python/blob/master/arithmetic_analysis/jacobi_iteration_method.py) * [Lu Decomposition](https://github.com/TheAlgorithms/Python/blob/master/arithmetic_analysis/lu_decomposition.py) * [Newton Forward Interpolation](https://github.com/TheAlgorithms/Python/blob/master/arithmetic_analysis/newton_forward_interpolation.py) * [Newton Method](https://github.com/TheAlgorithms/Python/blob/master/arithmetic_analysis/newton_method.py) diff --git a/arithmetic_analysis/jacobi_iteration_method.py b/arithmetic_analysis/jacobi_iteration_method.py new file mode 100644 index 000000000..667482425 --- /dev/null +++ b/arithmetic_analysis/jacobi_iteration_method.py @@ -0,0 +1,163 @@ +""" +Jacobi Iteration Method - https://en.wikipedia.org/wiki/Jacobi_method +""" +from __future__ import annotations + +import numpy as np + + +# Method to find solution of system of linear equations +def jacobi_iteration_method( + coefficient_matrix: np.ndarray, + constant_matrix: np.ndarray, + init_val: list, + iterations: int, +) -> list[float]: + """ + Jacobi Iteration Method: + An iterative algorithm to determine the solutions of strictly diagonally dominant + system of linear equations + + 4x1 + x2 + x3 = 2 + x1 + 5x2 + 2x3 = -6 + x1 + 2x2 + 4x3 = -4 + + x_init = [0.5, -0.5 , -0.5] + + Examples: + + >>> coefficient = np.array([[4, 1, 1], [1, 5, 2], [1, 2, 4]]) + >>> constant = np.array([[2], [-6], [-4]]) + >>> init_val = [0.5, -0.5, -0.5] + >>> iterations = 3 + >>> jacobi_iteration_method(coefficient, constant, init_val, iterations) + [0.909375, -1.14375, -0.7484375] + + + >>> coefficient = np.array([[4, 1, 1], [1, 5, 2]]) + >>> constant = np.array([[2], [-6], [-4]]) + >>> init_val = [0.5, -0.5, -0.5] + >>> iterations = 3 + >>> jacobi_iteration_method(coefficient, constant, init_val, iterations) + Traceback (most recent call last): + ... + ValueError: Coefficient matrix dimensions must be nxn but received 2x3 + + >>> coefficient = np.array([[4, 1, 1], [1, 5, 2], [1, 2, 4]]) + >>> constant = np.array([[2], [-6]]) + >>> init_val = [0.5, -0.5, -0.5] + >>> iterations = 3 + >>> jacobi_iteration_method(coefficient, constant, init_val, iterations) + Traceback (most recent call last): + ... + ValueError: Coefficient and constant matrices dimensions must be nxn and nx1 but + received 3x3 and 2x1 + + >>> coefficient = np.array([[4, 1, 1], [1, 5, 2], [1, 2, 4]]) + >>> constant = np.array([[2], [-6], [-4]]) + >>> init_val = [0.5, -0.5] + >>> iterations = 3 + >>> jacobi_iteration_method(coefficient, constant, init_val, iterations) + Traceback (most recent call last): + ... + ValueError: Number of initial values must be equal to number of rows in coefficient + matrix but received 2 and 3 + + >>> coefficient = np.array([[4, 1, 1], [1, 5, 2], [1, 2, 4]]) + >>> constant = np.array([[2], [-6], [-4]]) + >>> init_val = [0.5, -0.5, -0.5] + >>> iterations = 0 + >>> jacobi_iteration_method(coefficient, constant, init_val, iterations) + Traceback (most recent call last): + ... + ValueError: Iterations must be at least 1 + """ + + rows1, cols1 = coefficient_matrix.shape + rows2, cols2 = constant_matrix.shape + + if rows1 != cols1: + raise ValueError( + f"Coefficient matrix dimensions must be nxn but received {rows1}x{cols1}" + ) + + if cols2 != 1: + raise ValueError(f"Constant matrix must be nx1 but received {rows2}x{cols2}") + + if rows1 != rows2: + raise ValueError( + f"""Coefficient and constant matrices dimensions must be nxn and nx1 but + received {rows1}x{cols1} and {rows2}x{cols2}""" + ) + + if len(init_val) != rows1: + raise ValueError( + f"""Number of initial values must be equal to number of rows in coefficient + matrix but received {len(init_val)} and {rows1}""" + ) + + if iterations <= 0: + raise ValueError("Iterations must be at least 1") + + table = np.concatenate((coefficient_matrix, constant_matrix), axis=1) + + rows, cols = table.shape + + strictly_diagonally_dominant(table) + + # Iterates the whole matrix for given number of times + for i in range(iterations): + new_val = [] + for row in range(rows): + temp = 0 + for col in range(cols): + if col == row: + denom = table[row][col] + elif col == cols - 1: + val = table[row][col] + else: + temp += (-1) * table[row][col] * init_val[col] + temp = (temp + val) / denom + new_val.append(temp) + init_val = new_val + + return [float(i) for i in new_val] + + +# Checks if the given matrix is strictly diagonally dominant +def strictly_diagonally_dominant(table: np.ndarray) -> bool: + """ + >>> table = np.array([[4, 1, 1, 2], [1, 5, 2, -6], [1, 2, 4, -4]]) + >>> strictly_diagonally_dominant(table) + True + + >>> table = np.array([[4, 1, 1, 2], [1, 5, 2, -6], [1, 2, 3, -4]]) + >>> strictly_diagonally_dominant(table) + Traceback (most recent call last): + ... + ValueError: Coefficient matrix is not strictly diagonally dominant + """ + + rows, cols = table.shape + + is_diagonally_dominant = True + + for i in range(0, rows): + sum = 0 + for j in range(0, cols - 1): + if i == j: + continue + else: + sum += table[i][j] + + if table[i][i] <= sum: + raise ValueError("Coefficient matrix is not strictly diagonally dominant") + + return is_diagonally_dominant + + +# Test Cases +if __name__ == "__main__": + import doctest + + doctest.testmod() From 745f9e2bc37280368ae007d1a30ffc217e4a5b81 Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj Date: Tue, 9 Nov 2021 21:18:30 +0530 Subject: [PATCH 224/726] [mypy] Type annotations for searches directory (#5799) * Update ternary_search.py * Update mypy.ini * Update simulated_annealing.py * Update ternary_search.py * formatting * formatting * Update matrix_operation.py * Update matrix_operation.py * Update matrix_operation.py --- mypy.ini | 2 +- searches/simulated_annealing.py | 3 ++- searches/ternary_search.py | 12 ++++++++---- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/mypy.ini b/mypy.ini index ce7c262ab..94fb125fb 100644 --- a/mypy.ini +++ b/mypy.ini @@ -2,4 +2,4 @@ ignore_missing_imports = True install_types = True non_interactive = True -exclude = (matrix_operation.py|other/least_recently_used.py|other/lfu_cache.py|other/lru_cache.py|searches/simulated_annealing.py|searches/ternary_search.py) +exclude = (matrix_operation.py|other/least_recently_used.py|other/lfu_cache.py|other/lru_cache.py) diff --git a/searches/simulated_annealing.py b/searches/simulated_annealing.py index 2aa980be7..ad29559f1 100644 --- a/searches/simulated_annealing.py +++ b/searches/simulated_annealing.py @@ -1,6 +1,7 @@ # https://en.wikipedia.org/wiki/Simulated_annealing import math import random +from typing import Any from .hill_climbing import SearchProblem @@ -16,7 +17,7 @@ def simulated_annealing( start_temperate: float = 100, rate_of_decrease: float = 0.01, threshold_temp: float = 1, -) -> SearchProblem: +) -> Any: """ Implementation of the simulated annealing algorithm. We start with a given state, find all its neighbors. Pick a random neighbor, if that neighbor improves the diff --git a/searches/ternary_search.py b/searches/ternary_search.py index 01e437723..9830cce36 100644 --- a/searches/ternary_search.py +++ b/searches/ternary_search.py @@ -89,8 +89,8 @@ def ite_ternary_search(array: list[int], target: int) -> int: if right - left < precision: return lin_search(left, right, array, target) - one_third = (left + right) / 3 + 1 - two_third = 2 * (left + right) / 3 + 1 + one_third = (left + right) // 3 + 1 + two_third = 2 * (left + right) // 3 + 1 if array[one_third] == target: return one_third @@ -138,8 +138,8 @@ def rec_ternary_search(left: int, right: int, array: list[int], target: int) -> if left < right: if right - left < precision: return lin_search(left, right, array, target) - one_third = (left + right) / 3 + 1 - two_third = 2 * (left + right) / 3 + 1 + one_third = (left + right) // 3 + 1 + two_third = 2 * (left + right) // 3 + 1 if array[one_third] == target: return one_third @@ -157,6 +157,10 @@ def rec_ternary_search(left: int, right: int, array: list[int], target: int) -> if __name__ == "__main__": + import doctest + + doctest.testmod() + user_input = input("Enter numbers separated by comma:\n").strip() collection = [int(item.strip()) for item in user_input.split(",")] assert collection == sorted(collection), f"List must be ordered.\n{collection}." From d6a1623448f2494fbb21116b6bc699dccb0401b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl-Henrik=20=C3=85keson?= <80765479+chakeson@users.noreply.github.com> Date: Wed, 10 Nov 2021 11:22:27 +0100 Subject: [PATCH 225/726] Add solution for Project Euler problem 145 (#5173) * Added solution for Project Euler problem 145 * Updated spelling of comments Updated spelling inline with codespell * Removed trailing whitespaces in comments * Added default values. * nr -> number Co-authored-by: John Law * nr -> number * Update sol1.py * Update sol1.py Co-authored-by: John Law --- project_euler/problem_145/__init__.py | 0 project_euler/problem_145/sol1.py | 87 +++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 project_euler/problem_145/__init__.py create mode 100644 project_euler/problem_145/sol1.py diff --git a/project_euler/problem_145/__init__.py b/project_euler/problem_145/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_145/sol1.py b/project_euler/problem_145/sol1.py new file mode 100644 index 000000000..5ba3af86a --- /dev/null +++ b/project_euler/problem_145/sol1.py @@ -0,0 +1,87 @@ +""" +Problem 145: https://projecteuler.net/problem=145 + +Name: How many reversible numbers are there below one-billion? + +Some positive integers n have the property that the +sum [ n + reverse(n) ] consists entirely of odd (decimal) digits. +For instance, 36 + 63 = 99 and 409 + 904 = 1313. +We will call such numbers reversible; so 36, 63, 409, and 904 are reversible. +Leading zeroes are not allowed in either n or reverse(n). + +There are 120 reversible numbers below one-thousand. + +How many reversible numbers are there below one-billion (10^9)? + + +Solution: + +Here a brute force solution is used to find and count the reversible numbers. + +""" +from __future__ import annotations + + +def check_if_odd(sum: int = 36) -> int: + """ + Check if the last digit in the sum is even or odd. If even return 0. + If odd then floor division by 10 is used to remove the last number. + Process continues until sum becomes 0 because no more numbers. + >>> check_if_odd(36) + 0 + >>> check_if_odd(33) + 1 + """ + while sum > 0: + if (sum % 10) % 2 == 0: + return 0 + sum = sum // 10 + return 1 + + +def find_reverse_number(number: int = 36) -> int: + """ + Reverses the given number. Does not work with number that end in zero. + >>> find_reverse_number(36) + 63 + >>> find_reverse_number(409) + 904 + """ + reverse = 0 + + while number > 0: + temp = number % 10 + reverse = reverse * 10 + temp + number = number // 10 + + return reverse + + +def solution(number: int = 1000000000) -> int: + """ + Loops over the range of numbers. + Checks if they have ending zeros which disqualifies them from being reversible. + If that condition is passed it generates the reversed number. + Then sum up n and reverse(n). + Then check if all the numbers in the sum are odd. If true add to the answer. + >>> solution(1000000000) + 608720 + >>> solution(1000000) + 18720 + >>> solution(1000000) + 18720 + >>> solution(1000) + 120 + """ + answer = 0 + for x in range(1, number): + if x % 10 != 0: + reversed_number = find_reverse_number(x) + sum = x + reversed_number + answer += check_if_odd(sum) + + return answer + + +if __name__ == "__main__": + print(f"{solution() = }") From e9882e41ba7a1d1fbdc12362a522a1b646497192 Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj Date: Wed, 10 Nov 2021 20:52:52 +0530 Subject: [PATCH 226/726] [mypy] Fix `matrix_operation.py` (#5808) * Update matrix_operation.py * Update mypy.ini * Update DIRECTORY.md * formatting * Update matrix_operation.py * doctest for exception * A bit more... --- DIRECTORY.md | 2 ++ matrix/matrix_operation.py | 33 ++++++++++++++++++++++++--------- mypy.ini | 2 +- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 883b81b24..c46d81ab7 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -854,6 +854,8 @@ * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_135/sol1.py) * Problem 144 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_144/sol1.py) + * Problem 145 + * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_145/sol1.py) * Problem 173 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_173/sol1.py) * Problem 174 diff --git a/matrix/matrix_operation.py b/matrix/matrix_operation.py index dca01f9c3..6d0cd4e65 100644 --- a/matrix/matrix_operation.py +++ b/matrix/matrix_operation.py @@ -13,11 +13,16 @@ def add(*matrix_s: list[list]) -> list[list]: [[3.2, 5.4], [7, 9]] >>> add([[1, 2], [4, 5]], [[3, 7], [3, 4]], [[3, 5], [5, 7]]) [[7, 14], [12, 16]] + >>> add([3], [4, 5]) + Traceback (most recent call last): + ... + TypeError: Expected a matrix, got int/list instead """ if all(_check_not_integer(m) for m in matrix_s): for i in matrix_s[1:]: _verify_matrix_sizes(matrix_s[0], i) return [[sum(t) for t in zip(*m)] for m in zip(*matrix_s)] + raise TypeError("Expected a matrix, got int/list instead") def subtract(matrix_a: list[list], matrix_b: list[list]) -> list[list]: @@ -26,6 +31,10 @@ def subtract(matrix_a: list[list], matrix_b: list[list]) -> list[list]: [[-1, -1], [-1, -1]] >>> subtract([[1,2.5],[3,4]],[[2,3],[4,5.5]]) [[-1, -0.5], [-1, -1.5]] + >>> subtract([3], [4, 5]) + Traceback (most recent call last): + ... + TypeError: Expected a matrix, got int/list instead """ if ( _check_not_integer(matrix_a) @@ -33,9 +42,10 @@ def subtract(matrix_a: list[list], matrix_b: list[list]) -> list[list]: and _verify_matrix_sizes(matrix_a, matrix_b) ): return [[i - j for i, j in zip(*m)] for m in zip(matrix_a, matrix_b)] + raise TypeError("Expected a matrix, got int/list instead") -def scalar_multiply(matrix: list[list], n: int) -> list[list]: +def scalar_multiply(matrix: list[list], n: int | float) -> list[list]: """ >>> scalar_multiply([[1,2],[3,4]],5) [[5, 10], [15, 20]] @@ -79,18 +89,23 @@ def identity(n: int) -> list[list]: return [[int(row == column) for column in range(n)] for row in range(n)] -def transpose(matrix: list[list], return_map: bool = True) -> list[list]: +def transpose(matrix: list[list], return_map: bool = True) -> list[list] | map[list]: """ >>> transpose([[1,2],[3,4]]) # doctest: +ELLIPSIS >> transpose([[1,2],[3,4]], return_map=False) [[1, 3], [2, 4]] + >>> transpose([1, [2, 3]]) + Traceback (most recent call last): + ... + TypeError: Expected a matrix, got int/list instead """ if _check_not_integer(matrix): if return_map: return map(list, zip(*matrix)) else: return list(map(list, zip(*matrix))) + raise TypeError("Expected a matrix, got int/list instead") def minor(matrix: list[list], row: int, column: int) -> list[list]: @@ -118,7 +133,7 @@ def determinant(matrix: list[list]) -> int: ) -def inverse(matrix: list[list]) -> list[list]: +def inverse(matrix: list[list]) -> list[list] | None: """ >>> inverse([[1, 2], [3, 4]]) [[-2.0, 1.0], [1.5, -0.5]] @@ -138,21 +153,21 @@ def inverse(matrix: list[list]) -> list[list]: [x * (-1) ** (row + col) for col, x in enumerate(matrix_minor[row])] for row in range(len(matrix)) ] - adjugate = transpose(cofactors) + adjugate = list(transpose(cofactors)) return scalar_multiply(adjugate, 1 / det) def _check_not_integer(matrix: list[list]) -> bool: - if not isinstance(matrix, int) and not isinstance(matrix[0], int): - return True - raise TypeError("Expected a matrix, got int/list instead") + return not isinstance(matrix, int) and not isinstance(matrix[0], int) -def _shape(matrix: list[list]) -> list: +def _shape(matrix: list[list]) -> tuple[int, int]: return len(matrix), len(matrix[0]) -def _verify_matrix_sizes(matrix_a: list[list], matrix_b: list[list]) -> tuple[list]: +def _verify_matrix_sizes( + matrix_a: list[list], matrix_b: list[list] +) -> tuple[tuple, tuple]: shape = _shape(matrix_a) + _shape(matrix_b) if shape[0] != shape[3] or shape[1] != shape[2]: raise ValueError( diff --git a/mypy.ini b/mypy.ini index 94fb125fb..f00b3eeb6 100644 --- a/mypy.ini +++ b/mypy.ini @@ -2,4 +2,4 @@ ignore_missing_imports = True install_types = True non_interactive = True -exclude = (matrix_operation.py|other/least_recently_used.py|other/lfu_cache.py|other/lru_cache.py) +exclude = (other/least_recently_used.py|other/lfu_cache.py|other/lru_cache.py) From 7e81551d7b54f121458bd8e6a67b7ca86156815c Mon Sep 17 00:00:00 2001 From: Joyce Date: Thu, 11 Nov 2021 03:55:23 +0800 Subject: [PATCH 227/726] [mypy] fix type annotations for other/least-recently-used.py (#5811) --- other/least_recently_used.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/other/least_recently_used.py b/other/least_recently_used.py index d0e27efc6..9d6b6d7cb 100644 --- a/other/least_recently_used.py +++ b/other/least_recently_used.py @@ -1,5 +1,4 @@ import sys -from abc import abstractmethod from collections import deque @@ -10,7 +9,6 @@ class LRUCache: key_reference_map = object() # References of the keys in cache _MAX_CAPACITY: int = 10 # Maximum capacity of cache - @abstractmethod def __init__(self, n: int): """Creates an empty store and map for the keys. The LRUCache is set the size n. From f36ee034f1f5c65cc89ed1fadea29a28e744a297 Mon Sep 17 00:00:00 2001 From: Andrew Grangaard Date: Wed, 10 Nov 2021 14:21:16 -0800 Subject: [PATCH 228/726] [mypy] Annotate other/lru_cache and other/lfu_cache (#5755) * Adds repr and doctest of current behavior linkedlist in other/lru_cache * Blocks removal of head or tail of double linked list * clarifies add() logic for double linked list in other/lru_cache * expands doctests to compare cache and lru cache * [mypy] annotates vars for other/lru_cache * [mypy] Annotates lru_cache decorator for other/lru_cache * Higher order functions require a verbose Callable annotation * [mypy] Makes LRU_Cache generic over key and value types for other/lru_cache + no reason to force int -> int * [mypy] makes decorator a classmethod for access to class generic types * breaks two long lines in doctest for other/lru_cache * simplifies boundary test remove() for other/lru_cache * [mypy] Annotates, adds doctests, and makes Generic other/lfu_cache See also commits to other/lru_cache which guided these * [mypy] annotates cls var in other/lfu_cache * cleans up items from code review for lfu_cache and lru_cache * [mypy] runs mypy on lfu_cache and lru_cache --- mypy.ini | 2 +- other/lfu_cache.py | 232 ++++++++++++++++++++++++++++++++++---------- other/lru_cache.py | 235 +++++++++++++++++++++++++++++++++++---------- 3 files changed, 366 insertions(+), 103 deletions(-) diff --git a/mypy.ini b/mypy.ini index f00b3eeb6..7dbc7c4ff 100644 --- a/mypy.ini +++ b/mypy.ini @@ -2,4 +2,4 @@ ignore_missing_imports = True install_types = True non_interactive = True -exclude = (other/least_recently_used.py|other/lfu_cache.py|other/lru_cache.py) +exclude = (other/least_recently_used.py) diff --git a/other/lfu_cache.py b/other/lfu_cache.py index 88167ac1f..e955973c9 100644 --- a/other/lfu_cache.py +++ b/other/lfu_cache.py @@ -1,61 +1,165 @@ from __future__ import annotations -from typing import Callable +from typing import Callable, Generic, TypeVar + +T = TypeVar("T") +U = TypeVar("U") -class DoubleLinkedListNode: +class DoubleLinkedListNode(Generic[T, U]): """ Double Linked List Node built specifically for LFU Cache + + >>> node = DoubleLinkedListNode(1,1) + >>> node + Node: key: 1, val: 1, freq: 0, has next: False, has prev: False """ - def __init__(self, key: int, val: int): + def __init__(self, key: T | None, val: U | None): self.key = key self.val = val - self.freq = 0 - self.next = None - self.prev = None + self.freq: int = 0 + self.next: DoubleLinkedListNode[T, U] | None = None + self.prev: DoubleLinkedListNode[T, U] | None = None + + def __repr__(self) -> str: + return "Node: key: {}, val: {}, freq: {}, has next: {}, has prev: {}".format( + self.key, self.val, self.freq, self.next is not None, self.prev is not None + ) -class DoubleLinkedList: +class DoubleLinkedList(Generic[T, U]): """ Double Linked List built specifically for LFU Cache + + >>> dll: DoubleLinkedList = DoubleLinkedList() + >>> dll + DoubleLinkedList, + Node: key: None, val: None, freq: 0, has next: True, has prev: False, + Node: key: None, val: None, freq: 0, has next: False, has prev: True + + >>> first_node = DoubleLinkedListNode(1,10) + >>> first_node + Node: key: 1, val: 10, freq: 0, has next: False, has prev: False + + + >>> dll.add(first_node) + >>> dll + DoubleLinkedList, + Node: key: None, val: None, freq: 0, has next: True, has prev: False, + Node: key: 1, val: 10, freq: 1, has next: True, has prev: True, + Node: key: None, val: None, freq: 0, has next: False, has prev: True + + >>> # node is mutated + >>> first_node + Node: key: 1, val: 10, freq: 1, has next: True, has prev: True + + >>> second_node = DoubleLinkedListNode(2,20) + >>> second_node + Node: key: 2, val: 20, freq: 0, has next: False, has prev: False + + >>> dll.add(second_node) + >>> dll + DoubleLinkedList, + Node: key: None, val: None, freq: 0, has next: True, has prev: False, + Node: key: 1, val: 10, freq: 1, has next: True, has prev: True, + Node: key: 2, val: 20, freq: 1, has next: True, has prev: True, + Node: key: None, val: None, freq: 0, has next: False, has prev: True + + >>> removed_node = dll.remove(first_node) + >>> assert removed_node == first_node + >>> dll + DoubleLinkedList, + Node: key: None, val: None, freq: 0, has next: True, has prev: False, + Node: key: 2, val: 20, freq: 1, has next: True, has prev: True, + Node: key: None, val: None, freq: 0, has next: False, has prev: True + + + >>> # Attempt to remove node not on list + >>> removed_node = dll.remove(first_node) + >>> removed_node is None + True + + >>> # Attempt to remove head or rear + >>> dll.head + Node: key: None, val: None, freq: 0, has next: True, has prev: False + >>> dll.remove(dll.head) is None + True + + >>> # Attempt to remove head or rear + >>> dll.rear + Node: key: None, val: None, freq: 0, has next: False, has prev: True + >>> dll.remove(dll.rear) is None + True + + """ - def __init__(self): - self.head = DoubleLinkedListNode(None, None) - self.rear = DoubleLinkedListNode(None, None) + def __init__(self) -> None: + self.head: DoubleLinkedListNode[T, U] = DoubleLinkedListNode(None, None) + self.rear: DoubleLinkedListNode[T, U] = DoubleLinkedListNode(None, None) self.head.next, self.rear.prev = self.rear, self.head - def add(self, node: DoubleLinkedListNode) -> None: + def __repr__(self) -> str: + rep = ["DoubleLinkedList"] + node = self.head + while node.next is not None: + rep.append(str(node)) + node = node.next + rep.append(str(self.rear)) + return ",\n ".join(rep) + + def add(self, node: DoubleLinkedListNode[T, U]) -> None: """ - Adds the given node at the head of the list and shifting it to proper position + Adds the given node at the tail of the list and shifting it to proper position """ - temp = self.rear.prev + previous = self.rear.prev - self.rear.prev, node.next = node, self.rear - temp.next, node.prev = node, temp + # All nodes other than self.head are guaranteed to have non-None previous + assert previous is not None + + previous.next = node + node.prev = previous + self.rear.prev = node + node.next = self.rear node.freq += 1 self._position_node(node) - def _position_node(self, node: DoubleLinkedListNode) -> None: - while node.prev.key and node.prev.freq > node.freq: - node1, node2 = node, node.prev - node1.prev, node2.next = node2.prev, node1.prev - node1.next, node2.prev = node2, node1 + def _position_node(self, node: DoubleLinkedListNode[T, U]) -> None: + """ + Moves node forward to maintain invariant of sort by freq value + """ - def remove(self, node: DoubleLinkedListNode) -> DoubleLinkedListNode: + while node.prev is not None and node.prev.freq > node.freq: + # swap node with previous node + previous_node = node.prev + + node.prev = previous_node.prev + previous_node.next = node.prev + node.next = previous_node + previous_node.prev = node + + def remove( + self, node: DoubleLinkedListNode[T, U] + ) -> DoubleLinkedListNode[T, U] | None: """ Removes and returns the given node from the list + + Returns None if node.prev or node.next is None """ - temp_last, temp_next = node.prev, node.next - node.prev, node.next = None, None - temp_last.next, temp_next.prev = temp_next, temp_last + if node.prev is None or node.next is None: + return None + + node.prev.next = node.next + node.next.prev = node.prev + node.prev = None + node.next = None return node -class LFUCache: +class LFUCache(Generic[T, U]): """ LFU Cache to store a given capacity of data. Can be used as a stand-alone object or as a function decorator. @@ -66,9 +170,11 @@ class LFUCache: >>> cache.get(1) 1 >>> cache.set(3, 3) - >>> cache.get(2) # None is returned + >>> cache.get(2) is None + True >>> cache.set(4, 4) - >>> cache.get(1) # None is returned + >>> cache.get(1) is None + True >>> cache.get(3) 3 >>> cache.get(4) @@ -89,15 +195,15 @@ class LFUCache: """ # class variable to map the decorator functions to their respective instance - decorator_function_to_instance_map = {} + decorator_function_to_instance_map: dict[Callable[[T], U], LFUCache[T, U]] = {} def __init__(self, capacity: int): - self.list = DoubleLinkedList() + self.list: DoubleLinkedList[T, U] = DoubleLinkedList() self.capacity = capacity self.num_keys = 0 self.hits = 0 self.miss = 0 - self.cache = {} + self.cache: dict[T, DoubleLinkedListNode[T, U]] = {} def __repr__(self) -> str: """ @@ -110,40 +216,57 @@ class LFUCache: f"capacity={self.capacity}, current_size={self.num_keys})" ) - def __contains__(self, key: int) -> bool: + def __contains__(self, key: T) -> bool: """ >>> cache = LFUCache(1) + >>> 1 in cache False + >>> cache.set(1, 1) >>> 1 in cache True """ + return key in self.cache - def get(self, key: int) -> int | None: + def get(self, key: T) -> U | None: """ Returns the value for the input key and updates the Double Linked List. Returns - None if key is not present in cache + Returns None if key is not present in cache """ if key in self.cache: self.hits += 1 - self.list.add(self.list.remove(self.cache[key])) - return self.cache[key].val + value_node: DoubleLinkedListNode[T, U] = self.cache[key] + node = self.list.remove(self.cache[key]) + assert node == value_node + + # node is guaranteed not None because it is in self.cache + assert node is not None + self.list.add(node) + return node.val self.miss += 1 return None - def set(self, key: int, value: int) -> None: + def set(self, key: T, value: U) -> None: """ Sets the value for the input key and updates the Double Linked List """ if key not in self.cache: if self.num_keys >= self.capacity: - key_to_delete = self.list.head.next.key - self.list.remove(self.cache[key_to_delete]) - del self.cache[key_to_delete] + # delete first node when over capacity + first_node = self.list.head.next + + # guaranteed to have a non-None first node when num_keys > 0 + # explain to type checker via assertions + assert first_node is not None + assert first_node.key is not None + assert self.list.remove(first_node) is not None + # first_node guaranteed to be in list + + del self.cache[first_node.key] self.num_keys -= 1 self.cache[key] = DoubleLinkedListNode(key, value) self.list.add(self.cache[key]) @@ -151,32 +274,35 @@ class LFUCache: else: node = self.list.remove(self.cache[key]) + assert node is not None # node guaranteed to be in list node.val = value self.list.add(node) - @staticmethod - def decorator(size: int = 128): + @classmethod + def decorator( + cls: type[LFUCache[T, U]], size: int = 128 + ) -> Callable[[Callable[[T], U]], Callable[..., U]]: """ Decorator version of LFU Cache + + Decorated function must be function of T -> U """ - def cache_decorator_inner(func: Callable): - def cache_decorator_wrapper(*args, **kwargs): - if func not in LFUCache.decorator_function_to_instance_map: - LFUCache.decorator_function_to_instance_map[func] = LFUCache(size) + def cache_decorator_inner(func: Callable[[T], U]) -> Callable[..., U]: + def cache_decorator_wrapper(*args: T) -> U: + if func not in cls.decorator_function_to_instance_map: + cls.decorator_function_to_instance_map[func] = LFUCache(size) - result = LFUCache.decorator_function_to_instance_map[func].get(args[0]) + result = cls.decorator_function_to_instance_map[func].get(args[0]) if result is None: - result = func(*args, **kwargs) - LFUCache.decorator_function_to_instance_map[func].set( - args[0], result - ) + result = func(*args) + cls.decorator_function_to_instance_map[func].set(args[0], result) return result - def cache_info(): - return LFUCache.decorator_function_to_instance_map[func] + def cache_info() -> LFUCache[T, U]: + return cls.decorator_function_to_instance_map[func] - cache_decorator_wrapper.cache_info = cache_info + setattr(cache_decorator_wrapper, "cache_info", cache_info) return cache_decorator_wrapper diff --git a/other/lru_cache.py b/other/lru_cache.py index b74c0a45c..98051f89d 100644 --- a/other/lru_cache.py +++ b/other/lru_cache.py @@ -1,52 +1,147 @@ from __future__ import annotations -from typing import Callable +from typing import Callable, Generic, TypeVar + +T = TypeVar("T") +U = TypeVar("U") -class DoubleLinkedListNode: +class DoubleLinkedListNode(Generic[T, U]): """ Double Linked List Node built specifically for LRU Cache + + >>> DoubleLinkedListNode(1,1) + Node: key: 1, val: 1, has next: False, has prev: False """ - def __init__(self, key: int, val: int): + def __init__(self, key: T | None, val: U | None): self.key = key self.val = val - self.next = None - self.prev = None + self.next: DoubleLinkedListNode[T, U] | None = None + self.prev: DoubleLinkedListNode[T, U] | None = None + + def __repr__(self) -> str: + return "Node: key: {}, val: {}, has next: {}, has prev: {}".format( + self.key, self.val, self.next is not None, self.prev is not None + ) -class DoubleLinkedList: +class DoubleLinkedList(Generic[T, U]): """ Double Linked List built specifically for LRU Cache + + >>> dll: DoubleLinkedList = DoubleLinkedList() + >>> dll + DoubleLinkedList, + Node: key: None, val: None, has next: True, has prev: False, + Node: key: None, val: None, has next: False, has prev: True + + >>> first_node = DoubleLinkedListNode(1,10) + >>> first_node + Node: key: 1, val: 10, has next: False, has prev: False + + + >>> dll.add(first_node) + >>> dll + DoubleLinkedList, + Node: key: None, val: None, has next: True, has prev: False, + Node: key: 1, val: 10, has next: True, has prev: True, + Node: key: None, val: None, has next: False, has prev: True + + >>> # node is mutated + >>> first_node + Node: key: 1, val: 10, has next: True, has prev: True + + >>> second_node = DoubleLinkedListNode(2,20) + >>> second_node + Node: key: 2, val: 20, has next: False, has prev: False + + >>> dll.add(second_node) + >>> dll + DoubleLinkedList, + Node: key: None, val: None, has next: True, has prev: False, + Node: key: 1, val: 10, has next: True, has prev: True, + Node: key: 2, val: 20, has next: True, has prev: True, + Node: key: None, val: None, has next: False, has prev: True + + >>> removed_node = dll.remove(first_node) + >>> assert removed_node == first_node + >>> dll + DoubleLinkedList, + Node: key: None, val: None, has next: True, has prev: False, + Node: key: 2, val: 20, has next: True, has prev: True, + Node: key: None, val: None, has next: False, has prev: True + + + >>> # Attempt to remove node not on list + >>> removed_node = dll.remove(first_node) + >>> removed_node is None + True + + >>> # Attempt to remove head or rear + >>> dll.head + Node: key: None, val: None, has next: True, has prev: False + >>> dll.remove(dll.head) is None + True + + >>> # Attempt to remove head or rear + >>> dll.rear + Node: key: None, val: None, has next: False, has prev: True + >>> dll.remove(dll.rear) is None + True + + """ - def __init__(self): - self.head = DoubleLinkedListNode(None, None) - self.rear = DoubleLinkedListNode(None, None) + def __init__(self) -> None: + self.head: DoubleLinkedListNode[T, U] = DoubleLinkedListNode(None, None) + self.rear: DoubleLinkedListNode[T, U] = DoubleLinkedListNode(None, None) self.head.next, self.rear.prev = self.rear, self.head - def add(self, node: DoubleLinkedListNode) -> None: + def __repr__(self) -> str: + rep = ["DoubleLinkedList"] + node = self.head + while node.next is not None: + rep.append(str(node)) + node = node.next + rep.append(str(self.rear)) + return ",\n ".join(rep) + + def add(self, node: DoubleLinkedListNode[T, U]) -> None: """ Adds the given node to the end of the list (before rear) """ - temp = self.rear.prev - temp.next, node.prev = node, temp - self.rear.prev, node.next = node, self.rear + previous = self.rear.prev - def remove(self, node: DoubleLinkedListNode) -> DoubleLinkedListNode: + # All nodes other than self.head are guaranteed to have non-None previous + assert previous is not None + + previous.next = node + node.prev = previous + self.rear.prev = node + node.next = self.rear + + def remove( + self, node: DoubleLinkedListNode[T, U] + ) -> DoubleLinkedListNode[T, U] | None: """ Removes and returns the given node from the list + + Returns None if node.prev or node.next is None """ - temp_last, temp_next = node.prev, node.next - node.prev, node.next = None, None - temp_last.next, temp_next.prev = temp_next, temp_last + if node.prev is None or node.next is None: + return None + node.prev.next = node.next + node.next.prev = node.prev + node.prev = None + node.next = None return node -class LRUCache: +class LRUCache(Generic[T, U]): """ LRU Cache to store a given capacity of data. Can be used as a stand-alone object or as a function decorator. @@ -54,19 +149,41 @@ class LRUCache: >>> cache = LRUCache(2) >>> cache.set(1, 1) - >>> cache.set(2, 2) - >>> cache.get(1) 1 + >>> cache.list + DoubleLinkedList, + Node: key: None, val: None, has next: True, has prev: False, + Node: key: 2, val: 2, has next: True, has prev: True, + Node: key: 1, val: 1, has next: True, has prev: True, + Node: key: None, val: None, has next: False, has prev: True + + >>> cache.cache # doctest: +NORMALIZE_WHITESPACE + {1: Node: key: 1, val: 1, has next: True, has prev: True, \ + 2: Node: key: 2, val: 2, has next: True, has prev: True} + >>> cache.set(3, 3) - >>> cache.get(2) # None returned + >>> cache.list + DoubleLinkedList, + Node: key: None, val: None, has next: True, has prev: False, + Node: key: 1, val: 1, has next: True, has prev: True, + Node: key: 3, val: 3, has next: True, has prev: True, + Node: key: None, val: None, has next: False, has prev: True + + >>> cache.cache # doctest: +NORMALIZE_WHITESPACE + {1: Node: key: 1, val: 1, has next: True, has prev: True, \ + 3: Node: key: 3, val: 3, has next: True, has prev: True} + + >>> cache.get(2) is None + True >>> cache.set(4, 4) - >>> cache.get(1) # None returned + >>> cache.get(1) is None + True >>> cache.get(3) 3 @@ -91,15 +208,15 @@ class LRUCache: """ # class variable to map the decorator functions to their respective instance - decorator_function_to_instance_map = {} + decorator_function_to_instance_map: dict[Callable[[T], U], LRUCache[T, U]] = {} def __init__(self, capacity: int): - self.list = DoubleLinkedList() + self.list: DoubleLinkedList[T, U] = DoubleLinkedList() self.capacity = capacity self.num_keys = 0 self.hits = 0 self.miss = 0 - self.cache = {} + self.cache: dict[T, DoubleLinkedListNode[T, U]] = {} def __repr__(self) -> str: """ @@ -112,7 +229,7 @@ class LRUCache: f"capacity={self.capacity}, current size={self.num_keys})" ) - def __contains__(self, key: int) -> bool: + def __contains__(self, key: T) -> bool: """ >>> cache = LRUCache(1) @@ -127,62 +244,82 @@ class LRUCache: return key in self.cache - def get(self, key: int) -> int | None: + def get(self, key: T) -> U | None: """ - Returns the value for the input key and updates the Double Linked List. Returns - None if key is not present in cache + Returns the value for the input key and updates the Double Linked List. + Returns None if key is not present in cache """ + # Note: pythonic interface would throw KeyError rather than return None if key in self.cache: self.hits += 1 - self.list.add(self.list.remove(self.cache[key])) - return self.cache[key].val + value_node: DoubleLinkedListNode[T, U] = self.cache[key] + node = self.list.remove(self.cache[key]) + assert node == value_node + + # node is guaranteed not None because it is in self.cache + assert node is not None + self.list.add(node) + return node.val self.miss += 1 return None - def set(self, key: int, value: int) -> None: + def set(self, key: T, value: U) -> None: """ Sets the value for the input key and updates the Double Linked List """ if key not in self.cache: if self.num_keys >= self.capacity: - key_to_delete = self.list.head.next.key - self.list.remove(self.cache[key_to_delete]) - del self.cache[key_to_delete] + # delete first node (oldest) when over capacity + first_node = self.list.head.next + + # guaranteed to have a non-None first node when num_keys > 0 + # explain to type checker via assertions + assert first_node is not None + assert first_node.key is not None + assert ( + self.list.remove(first_node) is not None + ) # node guaranteed to be in list assert node.key is not None + + del self.cache[first_node.key] self.num_keys -= 1 self.cache[key] = DoubleLinkedListNode(key, value) self.list.add(self.cache[key]) self.num_keys += 1 else: + # bump node to the end of the list, update value node = self.list.remove(self.cache[key]) + assert node is not None # node guaranteed to be in list node.val = value self.list.add(node) - @staticmethod - def decorator(size: int = 128): + @classmethod + def decorator( + cls, size: int = 128 + ) -> Callable[[Callable[[T], U]], Callable[..., U]]: """ Decorator version of LRU Cache + + Decorated function must be function of T -> U """ - def cache_decorator_inner(func: Callable): - def cache_decorator_wrapper(*args, **kwargs): - if func not in LRUCache.decorator_function_to_instance_map: - LRUCache.decorator_function_to_instance_map[func] = LRUCache(size) + def cache_decorator_inner(func: Callable[[T], U]) -> Callable[..., U]: + def cache_decorator_wrapper(*args: T) -> U: + if func not in cls.decorator_function_to_instance_map: + cls.decorator_function_to_instance_map[func] = LRUCache(size) - result = LRUCache.decorator_function_to_instance_map[func].get(args[0]) + result = cls.decorator_function_to_instance_map[func].get(args[0]) if result is None: - result = func(*args, **kwargs) - LRUCache.decorator_function_to_instance_map[func].set( - args[0], result - ) + result = func(*args) + cls.decorator_function_to_instance_map[func].set(args[0], result) return result - def cache_info(): - return LRUCache.decorator_function_to_instance_map[func] + def cache_info() -> LRUCache[T, U]: + return cls.decorator_function_to_instance_map[func] - cache_decorator_wrapper.cache_info = cache_info + setattr(cache_decorator_wrapper, "cache_info", cache_info) return cache_decorator_wrapper From 6314195bb1e6001ddd0a11a59c41f1d0b9eeb722 Mon Sep 17 00:00:00 2001 From: Leoriem-code <73761711+Leoriem-code@users.noreply.github.com> Date: Thu, 11 Nov 2021 14:39:54 +0100 Subject: [PATCH 229/726] Add README files 2/8 (#5766) * add 5 README files * empty commit to (hopefully) get rid of the `test-are-failling` label * Update ciphers/README.md Co-authored-by: John Law * Update conversions/README.md Co-authored-by: John Law * Update cellular_automata/README.md Co-authored-by: John Law * Update computer_vision/README.md Co-authored-by: John Law * Update conversions/README.md Co-authored-by: John Law * Update compression/README.md Co-authored-by: John Law --- cellular_automata/README.md | 8 ++++++-- ciphers/README.md | 7 +++++++ compression/README.md | 10 ++++++++++ computer_vision/README.md | 10 +++++++--- conversions/README.md | 6 ++++++ 5 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 ciphers/README.md create mode 100644 compression/README.md create mode 100644 conversions/README.md diff --git a/cellular_automata/README.md b/cellular_automata/README.md index c3fa0516f..c5681b339 100644 --- a/cellular_automata/README.md +++ b/cellular_automata/README.md @@ -1,4 +1,8 @@ # Cellular Automata -* https://en.wikipedia.org/wiki/Cellular_automaton -* https://mathworld.wolfram.com/ElementaryCellularAutomaton.html +Cellular automata are a way to simulate the behavior of "life", no matter if it is a robot or cell. +They usually follow simple rules but can lead to the creation of complex forms. +The most popular cellular automaton is Conway's [Game of Life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life). + +* +* diff --git a/ciphers/README.md b/ciphers/README.md new file mode 100644 index 000000000..fa09874f3 --- /dev/null +++ b/ciphers/README.md @@ -0,0 +1,7 @@ +# Ciphers + +Ciphers are used to protect data from people that are not allowed to have it. They are everywhere on the internet to protect your connections. + +* +* +* diff --git a/compression/README.md b/compression/README.md new file mode 100644 index 000000000..cf54ea986 --- /dev/null +++ b/compression/README.md @@ -0,0 +1,10 @@ +# Compression + +Data compression is everywhere, you need it to store data without taking too much space. +Either the compression lose some data (then we talk about lossy compression, such as .jpg) or it does not (and then it is lossless compression, such as .png) + +Lossless compression is mainly used for archive purpose as it allow storing data without losing information about the file archived. On the other hand, lossy compression is used for transfer of file where quality isn't necessarily what is required (i.e: images on Twitter). + +* +* +* diff --git a/computer_vision/README.md b/computer_vision/README.md index 94ee49308..8d2f4a130 100644 --- a/computer_vision/README.md +++ b/computer_vision/README.md @@ -1,7 +1,11 @@ -### Computer Vision +# Computer Vision + +Computer vision is a field of computer science that works on enabling computers to see, identify and process images in the same way that human does, and provide appropriate output. -Computer vision is a field of computer science that works on enabling computers to see, -identify and process images in the same way that human vision does, and then provide appropriate output. It is like imparting human intelligence and instincts to a computer. Image processing and computer vision are a little different from each other. Image processing means applying some algorithms for transforming image from one form to the other like smoothing, contrasting, stretching, etc. + While computer vision comes from modelling image processing using the techniques of machine learning, computer vision applies machine learning to recognize patterns for interpretation of images (much like the process of visual reasoning of human vision). + +* +* diff --git a/conversions/README.md b/conversions/README.md new file mode 100644 index 000000000..ec3d931fd --- /dev/null +++ b/conversions/README.md @@ -0,0 +1,6 @@ +# Conversion + +Conversion programs convert a type of data, a number from a numerical base or unit into one of another type, base or unit, e.g. binary to decimal, integer to string or foot to meters. + +* +* From 9b9405fdcdc5ba9fc16a53f8ae6be081d4f5582a Mon Sep 17 00:00:00 2001 From: Bartechnika <48760796+Bartechnika@users.noreply.github.com> Date: Sat, 13 Nov 2021 09:32:44 +0000 Subject: [PATCH 230/726] Add new persistence algorithm (#4751) * Created new persistence algorithm * Update persistence.py * Added another persistence function --- maths/persistence.py | 82 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 maths/persistence.py diff --git a/maths/persistence.py b/maths/persistence.py new file mode 100644 index 000000000..607641e67 --- /dev/null +++ b/maths/persistence.py @@ -0,0 +1,82 @@ +def multiplicative_persistence(num: int) -> int: + """ + Return the persistence of a given number. + + https://en.wikipedia.org/wiki/Persistence_of_a_number + + >>> multiplicative_persistence(217) + 2 + >>> multiplicative_persistence(-1) + Traceback (most recent call last): + ... + ValueError: multiplicative_persistence() does not accept negative values + >>> multiplicative_persistence("long number") + Traceback (most recent call last): + ... + ValueError: multiplicative_persistence() only accepts integral values + """ + + if not isinstance(num, int): + raise ValueError("multiplicative_persistence() only accepts integral values") + if num < 0: + raise ValueError("multiplicative_persistence() does not accept negative values") + + steps = 0 + num_string = str(num) + + while len(num_string) != 1: + numbers = [int(i) for i in num_string] + + total = 1 + for i in range(0, len(numbers)): + total *= numbers[i] + + num_string = str(total) + + steps += 1 + return steps + + +def additive_persistence(num: int) -> int: + """ + Return the persistence of a given number. + + https://en.wikipedia.org/wiki/Persistence_of_a_number + + >>> additive_persistence(199) + 3 + >>> additive_persistence(-1) + Traceback (most recent call last): + ... + ValueError: additive_persistence() does not accept negative values + >>> additive_persistence("long number") + Traceback (most recent call last): + ... + ValueError: additive_persistence() only accepts integral values + """ + + if not isinstance(num, int): + raise ValueError("additive_persistence() only accepts integral values") + if num < 0: + raise ValueError("additive_persistence() does not accept negative values") + + steps = 0 + num_string = str(num) + + while len(num_string) != 1: + numbers = [int(i) for i in num_string] + + total = 0 + for i in range(0, len(numbers)): + total += numbers[i] + + num_string = str(total) + + steps += 1 + return steps + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 551c65766d1594ecd7e127ac288ed23b9e89b8c3 Mon Sep 17 00:00:00 2001 From: Andrew Grangaard Date: Tue, 16 Nov 2021 06:01:17 -0800 Subject: [PATCH 231/726] [Mypy] fix other/least_recently_used (#5814) * makes LRUCache constructor concrete * fixes bug in dq_removal in other/least_recently_used + deque.remove() operates by value not index * [mypy] Annotates other/least_recently_used over generic type + clean-up: rename key_reference to match type. * [mypy] updates example to demonstrate LRUCache with complex type * Adds doctest to other/least_recently_used * mypy.ini: Remove exclude = (other/least_recently_used.py) * Various mypy configs * Delete mypy.ini * Add mypy to .pre-commit-config.yaml * mypy --ignore-missing-imports --install-types --non-interactive . * mypy v0.910 * Pillow=8.3.7 * Pillow==8.3.7 * Pillow==8.3.2 * Update .pre-commit-config.yaml * Update requirements.txt * Update pre-commit.yml * --install-types # See mirrors-mypy README.md Co-authored-by: Christian Clauss --- .github/workflows/build.yml | 2 +- .github/workflows/pre-commit.yml | 2 + .pre-commit-config.yaml | 23 +++++++---- mypy.ini | 5 --- other/least_recently_used.py | 70 +++++++++++++++++++++++--------- requirements.txt | 1 - 6 files changed, 68 insertions(+), 35 deletions(-) delete mode 100644 mypy.ini diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e5f8d6b39..df000cda5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,7 +21,7 @@ jobs: run: | python -m pip install --upgrade pip setuptools six wheel python -m pip install mypy pytest-cov -r requirements.txt - - run: mypy . # See `mypy.ini` for configuration settings. + - run: mypy --ignore-missing-imports --install-types --non-interactive . - name: Run tests run: pytest --doctest-modules --ignore=project_euler/ --ignore=scripts/validate_solutions.py --cov-report=term-missing:skip-covered --cov=. . - if: ${{ success() }} diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 27a5a97c0..19196098b 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -14,6 +14,8 @@ jobs: ~/.cache/pip key: ${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} - uses: actions/setup-python@v2 + with: + python-version: 3.9 - uses: psf/black@21.4b0 - name: Install pre-commit run: | diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e60003051..0ebd6dfa0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,22 +12,26 @@ repos: data_structures/heap/binomial_heap.py )$ - id: requirements-txt-fixer + - repo: https://github.com/psf/black rev: 21.4b0 hooks: - id: black + - repo: https://github.com/PyCQA/isort rev: 5.8.0 hooks: - id: isort args: - --profile=black + - repo: https://github.com/asottile/pyupgrade rev: v2.29.0 hooks: - id: pyupgrade args: - --py39-plus + - repo: https://gitlab.com/pycqa/flake8 rev: 3.9.1 hooks: @@ -36,13 +40,16 @@ repos: - --ignore=E203,W503 - --max-complexity=25 - --max-line-length=88 -# FIXME: fix mypy errors and then uncomment this -# - repo: https://github.com/pre-commit/mirrors-mypy -# rev: v0.782 -# hooks: -# - id: mypy -# args: -# - --ignore-missing-imports + + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v0.910 + hooks: + - id: mypy + args: + - --ignore-missing-imports + - --install-types # See mirrors-mypy README.md + - --non-interactive + - repo: https://github.com/codespell-project/codespell rev: v2.0.0 hooks: @@ -50,13 +57,13 @@ repos: args: - --ignore-words-list=ans,crate,fo,followings,hist,iff,mater,secant,som,tim - --skip="./.*,./strings/dictionary.txt,./strings/words.txt,./project_euler/problem_022/p022_names.txt" - - --quiet-level=2 exclude: | (?x)^( strings/dictionary.txt | strings/words.txt | project_euler/problem_022/p022_names.txt )$ + - repo: local hooks: - id: validate-filenames diff --git a/mypy.ini b/mypy.ini deleted file mode 100644 index 7dbc7c4ff..000000000 --- a/mypy.ini +++ /dev/null @@ -1,5 +0,0 @@ -[mypy] -ignore_missing_imports = True -install_types = True -non_interactive = True -exclude = (other/least_recently_used.py) diff --git a/other/least_recently_used.py b/other/least_recently_used.py index 9d6b6d7cb..cb692bb1b 100644 --- a/other/least_recently_used.py +++ b/other/least_recently_used.py @@ -1,20 +1,45 @@ +from __future__ import annotations + import sys from collections import deque +from typing import Generic, TypeVar + +T = TypeVar("T") -class LRUCache: - """Page Replacement Algorithm, Least Recently Used (LRU) Caching.""" +class LRUCache(Generic[T]): + """ + Page Replacement Algorithm, Least Recently Used (LRU) Caching. - dq_store = object() # Cache store of keys - key_reference_map = object() # References of the keys in cache + >>> lru_cache: LRUCache[str | int] = LRUCache(4) + >>> lru_cache.refer("A") + >>> lru_cache.refer(2) + >>> lru_cache.refer(3) + + >>> lru_cache + LRUCache(4) => [3, 2, 'A'] + + >>> lru_cache.refer("A") + >>> lru_cache + LRUCache(4) => ['A', 3, 2] + + >>> lru_cache.refer(4) + >>> lru_cache.refer(5) + >>> lru_cache + LRUCache(4) => [5, 4, 'A', 3] + + """ + + dq_store: deque[T] # Cache store of keys + key_reference: set[T] # References of the keys in cache _MAX_CAPACITY: int = 10 # Maximum capacity of cache - def __init__(self, n: int): + def __init__(self, n: int) -> None: """Creates an empty store and map for the keys. The LRUCache is set the size n. """ self.dq_store = deque() - self.key_reference_map = set() + self.key_reference = set() if not n: LRUCache._MAX_CAPACITY = sys.maxsize elif n < 0: @@ -22,41 +47,46 @@ class LRUCache: else: LRUCache._MAX_CAPACITY = n - def refer(self, x): + def refer(self, x: T) -> None: """ Looks for a page in the cache store and adds reference to the set. Remove the least recently used key if the store is full. Update store to reflect recent access. """ - if x not in self.key_reference_map: + if x not in self.key_reference: if len(self.dq_store) == LRUCache._MAX_CAPACITY: last_element = self.dq_store.pop() - self.key_reference_map.remove(last_element) + self.key_reference.remove(last_element) else: - index_remove = 0 - for idx, key in enumerate(self.dq_store): - if key == x: - index_remove = idx - break - self.dq_store.remove(index_remove) + self.dq_store.remove(x) self.dq_store.appendleft(x) - self.key_reference_map.add(x) + self.key_reference.add(x) - def display(self): + def display(self) -> None: """ Prints all the elements in the store. """ for k in self.dq_store: print(k) + def __repr__(self) -> str: + return f"LRUCache({self._MAX_CAPACITY}) => {list(self.dq_store)}" + if __name__ == "__main__": - lru_cache = LRUCache(4) - lru_cache.refer(1) + import doctest + + doctest.testmod() + + lru_cache: LRUCache[str | int] = LRUCache(4) + lru_cache.refer("A") lru_cache.refer(2) lru_cache.refer(3) - lru_cache.refer(1) + lru_cache.refer("A") lru_cache.refer(4) lru_cache.refer(5) lru_cache.display() + + print(lru_cache) + assert str(lru_cache) == "LRUCache(4) => [5, 4, 'A', 3]" diff --git a/requirements.txt b/requirements.txt index e01d87cff..9a26dcc21 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,5 +16,4 @@ sympy tensorflow texttable tweepy -types-requests xgboost From d848bfbf3229f2a3240a298a583f6b80a9efc1fd Mon Sep 17 00:00:00 2001 From: Navaneeth Sharma <63489382+Navaneeth-Sharma@users.noreply.github.com> Date: Wed, 17 Nov 2021 04:28:47 +0530 Subject: [PATCH 232/726] Adding Pooling Algorithms (#5826) * adding pooling algorithms * pooling.py: Adding pooling algorithms to computer vision pull_number= * pooling.py: Adding pooling algorithms to computer vision * pooling_functions.py: Adding pooling algorithms to computer vision * pooling.py: Adding Pooling Algorithms * pooling_functions.py Add and Update * Update pooling_functions.py * Update computer_vision/pooling_functions.py Co-authored-by: Christian Clauss * Update computer_vision/pooling_functions.py Co-authored-by: Christian Clauss * Update computer_vision/pooling_functions.py Co-authored-by: Christian Clauss * Update computer_vision/pooling_functions.py Co-authored-by: Christian Clauss * Update pooling_functions.py * Formatting pooling.py Co-authored-by: Christian Clauss --- computer_vision/pooling_functions.py | 135 +++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 computer_vision/pooling_functions.py diff --git a/computer_vision/pooling_functions.py b/computer_vision/pooling_functions.py new file mode 100644 index 000000000..09beabcba --- /dev/null +++ b/computer_vision/pooling_functions.py @@ -0,0 +1,135 @@ +# Source : https://computersciencewiki.org/index.php/Max-pooling_/_Pooling +# Importing the libraries +import numpy as np +from PIL import Image + + +# Maxpooling Function +def maxpooling(arr: np.ndarray, size: int, stride: int) -> np.ndarray: + """ + This function is used to perform maxpooling on the input array of 2D matrix(image) + Args: + arr: numpy array + size: size of pooling matrix + stride: the number of pixels shifts over the input matrix + Returns: + numpy array of maxpooled matrix + Sample Input Output: + >>> maxpooling([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]], 2, 2) + array([[ 6., 8.], + [14., 16.]]) + >>> maxpooling([[147, 180, 122],[241, 76, 32],[126, 13, 157]], 2, 1) + array([[241., 180.], + [241., 157.]]) + """ + arr = np.array(arr) + if arr.shape[0] != arr.shape[1]: + raise ValueError("The input array is not a square matrix") + i = 0 + j = 0 + mat_i = 0 + mat_j = 0 + + # compute the shape of the output matrix + maxpool_shape = (arr.shape[0] - size) // stride + 1 + # initialize the output matrix with zeros of shape maxpool_shape + updated_arr = np.zeros((maxpool_shape, maxpool_shape)) + + while i < arr.shape[0]: + if i + size > arr.shape[0]: + # if the end of the matrix is reached, break + break + while j < arr.shape[1]: + # if the end of the matrix is reached, break + if j + size > arr.shape[1]: + break + # compute the maximum of the pooling matrix + updated_arr[mat_i][mat_j] = np.max(arr[i : i + size, j : j + size]) + # shift the pooling matrix by stride of column pixels + j += stride + mat_j += 1 + + # shift the pooling matrix by stride of row pixels + i += stride + mat_i += 1 + + # reset the column index to 0 + j = 0 + mat_j = 0 + + return updated_arr + + +# Averagepooling Function +def avgpooling(arr: np.ndarray, size: int, stride: int) -> np.ndarray: + """ + This function is used to perform avgpooling on the input array of 2D matrix(image) + Args: + arr: numpy array + size: size of pooling matrix + stride: the number of pixels shifts over the input matrix + Returns: + numpy array of avgpooled matrix + Sample Input Output: + >>> avgpooling([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]], 2, 2) + array([[ 3., 5.], + [11., 13.]]) + >>> avgpooling([[147, 180, 122],[241, 76, 32],[126, 13, 157]], 2, 1) + array([[161., 102.], + [114., 69.]]) + """ + arr = np.array(arr) + if arr.shape[0] != arr.shape[1]: + raise ValueError("The input array is not a square matrix") + i = 0 + j = 0 + mat_i = 0 + mat_j = 0 + + # compute the shape of the output matrix + avgpool_shape = (arr.shape[0] - size) // stride + 1 + # initialize the output matrix with zeros of shape avgpool_shape + updated_arr = np.zeros((avgpool_shape, avgpool_shape)) + + while i < arr.shape[0]: + # if the end of the matrix is reached, break + if i + size > arr.shape[0]: + break + while j < arr.shape[1]: + # if the end of the matrix is reached, break + if j + size > arr.shape[1]: + break + # compute the average of the pooling matrix + updated_arr[mat_i][mat_j] = int(np.average(arr[i : i + size, j : j + size])) + # shift the pooling matrix by stride of column pixels + j += stride + mat_j += 1 + + # shift the pooling matrix by stride of row pixels + i += stride + mat_i += 1 + # reset the column index to 0 + j = 0 + mat_j = 0 + + return updated_arr + + +# Main Function +if __name__ == "__main__": + from doctest import testmod + + testmod(name="avgpooling", verbose=True) + + # Loading the image + image = Image.open("path_to_image") + + # Converting the image to numpy array and maxpooling, displaying the result + # Ensure that the image is a square matrix + + Image.fromarray(maxpooling(np.array(image), size=3, stride=2)).show() + + # Converting the image to numpy array and averagepooling, displaying the result + # Ensure that the image is a square matrix + + Image.fromarray(avgpooling(np.array(image), size=3, stride=2)).show() From 1ae5abfc3ca5dcf89b7e378735ceb9ef41769cbf Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 17 Nov 2021 04:43:02 +0100 Subject: [PATCH 233/726] Replace typing.optional with new annotations syntax (#5829) * Replace typing.optional with new annotations syntax * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 1 + data_structures/linked_list/__init__.py | 5 +++-- data_structures/linked_list/circular_linked_list.py | 6 ++++-- data_structures/linked_list/has_loop.py | 6 ++++-- .../linked_list/middle_element_of_linked_list.py | 4 ++-- maths/pollard_rho.py | 5 +++-- 6 files changed, 17 insertions(+), 10 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index c46d81ab7..16244e6ad 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -525,6 +525,7 @@ * [Perfect Cube](https://github.com/TheAlgorithms/Python/blob/master/maths/perfect_cube.py) * [Perfect Number](https://github.com/TheAlgorithms/Python/blob/master/maths/perfect_number.py) * [Perfect Square](https://github.com/TheAlgorithms/Python/blob/master/maths/perfect_square.py) + * [Persistence](https://github.com/TheAlgorithms/Python/blob/master/maths/persistence.py) * [Pi Monte Carlo Estimation](https://github.com/TheAlgorithms/Python/blob/master/maths/pi_monte_carlo_estimation.py) * [Pollard Rho](https://github.com/TheAlgorithms/Python/blob/master/maths/pollard_rho.py) * [Polynomial Evaluation](https://github.com/TheAlgorithms/Python/blob/master/maths/polynomial_evaluation.py) diff --git a/data_structures/linked_list/__init__.py b/data_structures/linked_list/__init__.py index 8ae171d71..6ba660231 100644 --- a/data_structures/linked_list/__init__.py +++ b/data_structures/linked_list/__init__.py @@ -5,8 +5,9 @@ Nodes contain data and also may link to other nodes: head node gives us access of the complete list - Last node: points to null """ +from __future__ import annotations -from typing import Any, Optional +from typing import Any class Node: @@ -17,7 +18,7 @@ class Node: class LinkedList: def __init__(self) -> None: - self.head: Optional[Node] = None + self.head: Node | None = None self.size = 0 def add(self, item: Any) -> None: diff --git a/data_structures/linked_list/circular_linked_list.py b/data_structures/linked_list/circular_linked_list.py index 42794ba79..121d934c6 100644 --- a/data_structures/linked_list/circular_linked_list.py +++ b/data_structures/linked_list/circular_linked_list.py @@ -1,10 +1,12 @@ -from typing import Any, Iterator, Optional +from __future__ import annotations + +from typing import Any, Iterator class Node: def __init__(self, data: Any): self.data: Any = data - self.next: Optional[Node] = None + self.next: Node | None = None class CircularLinkedList: diff --git a/data_structures/linked_list/has_loop.py b/data_structures/linked_list/has_loop.py index a155ab4c7..bc06ffe15 100644 --- a/data_structures/linked_list/has_loop.py +++ b/data_structures/linked_list/has_loop.py @@ -1,4 +1,6 @@ -from typing import Any, Optional +from __future__ import annotations + +from typing import Any class ContainsLoopError(Exception): @@ -8,7 +10,7 @@ class ContainsLoopError(Exception): class Node: def __init__(self, data: Any) -> None: self.data: Any = data - self.next_node: Optional[Node] = None + self.next_node: Node | None = None def __iter__(self): node = self diff --git a/data_structures/linked_list/middle_element_of_linked_list.py b/data_structures/linked_list/middle_element_of_linked_list.py index 296696897..0c6250f3b 100644 --- a/data_structures/linked_list/middle_element_of_linked_list.py +++ b/data_structures/linked_list/middle_element_of_linked_list.py @@ -1,4 +1,4 @@ -from typing import Optional +from __future__ import annotations class Node: @@ -17,7 +17,7 @@ class LinkedList: self.head = new_node return self.head.data - def middle_element(self) -> Optional[int]: + def middle_element(self) -> int | None: """ >>> link = LinkedList() >>> link.middle_element() diff --git a/maths/pollard_rho.py b/maths/pollard_rho.py index df020c63f..0fc80cd42 100644 --- a/maths/pollard_rho.py +++ b/maths/pollard_rho.py @@ -1,5 +1,6 @@ +from __future__ import annotations + from math import gcd -from typing import Union def pollard_rho( @@ -7,7 +8,7 @@ def pollard_rho( seed: int = 2, step: int = 1, attempts: int = 3, -) -> Union[int, None]: +) -> int | None: """ Use Pollard's Rho algorithm to return a nontrivial factor of ``num``. The returned factor may be composite and require further factorization. From f4a16f607b996b030347fadf011b57320b5624b2 Mon Sep 17 00:00:00 2001 From: Goodness Ezeh <88127727+GoodnessEzeh@users.noreply.github.com> Date: Wed, 24 Nov 2021 23:23:44 +0900 Subject: [PATCH 234/726] Lowercase g --> Capital G (#5845) * Updated the comments in the code * Update .gitignore * Update .gitignore * Update .gitignore Co-authored-by: Christian Clauss --- other/password_generator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/other/password_generator.py b/other/password_generator.py index cf7250c81..c09afd7e6 100644 --- a/other/password_generator.py +++ b/other/password_generator.py @@ -1,4 +1,4 @@ -"""Password generator allows you to generate a random password of length N.""" +"""Password Generator allows you to generate a random password of length N.""" from random import choice, shuffle from string import ascii_letters, digits, punctuation @@ -24,7 +24,7 @@ def password_generator(length=8): # ctbi= characters that must be in password # i= how many letters or characters the password length will be def alternative_password_generator(ctbi, i): - # Password generator = full boot with random_number, random_letters, and + # Password Generator = full boot with random_number, random_letters, and # random_character FUNCTIONS # Put your code here... i = i - len(ctbi) From 65d3cfff2fb6f75999fff7918bccb463593f939d Mon Sep 17 00:00:00 2001 From: Jaydeep Das Date: Sun, 28 Nov 2021 23:50:18 +0530 Subject: [PATCH 235/726] Added memoization function in fibonacci (#5856) * Added memoization function in fibonacci * Minor changes --- maths/fibonacci.py | 48 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/maths/fibonacci.py b/maths/fibonacci.py index 9b193b74a..ca4f4a236 100644 --- a/maths/fibonacci.py +++ b/maths/fibonacci.py @@ -1,13 +1,19 @@ # fibonacci.py """ -Calculates the Fibonacci sequence using iteration, recursion, and a simplified -form of Binet's formula +Calculates the Fibonacci sequence using iteration, recursion, memoization, +and a simplified form of Binet's formula -NOTE 1: the iterative and recursive functions are more accurate than the Binet's -formula function because the iterative function doesn't use floats +NOTE 1: the iterative, recursive, memoization functions are more accurate than +the Binet's formula function because the Binet formula function uses floats NOTE 2: the Binet's formula function is much more limited in the size of inputs that it can handle due to the size limitations of Python floats + +RESULTS: (n = 20) +fib_iterative runtime: 0.0055 ms +fib_recursive runtime: 6.5627 ms +fib_memoization runtime: 0.0107 ms +fib_binet runtime: 0.0174 ms """ from math import sqrt @@ -86,6 +92,39 @@ def fib_recursive(n: int) -> list[int]: return [fib_recursive_term(i) for i in range(n + 1)] +def fib_memoization(n: int) -> list[int]: + """ + Calculates the first n (0-indexed) Fibonacci numbers using memoization + >>> fib_memoization(0) + [0] + >>> fib_memoization(1) + [0, 1] + >>> fib_memoization(5) + [0, 1, 1, 2, 3, 5] + >>> fib_memoization(10) + [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55] + >>> fib_iterative(-1) + Traceback (most recent call last): + ... + Exception: n is negative + """ + if n < 0: + raise Exception("n is negative") + # Cache must be outside recursuive function + # other it will reset every time it calls itself. + cache: dict[int, int] = {0: 0, 1: 1, 2: 1} # Prefilled cache + + def rec_fn_memoized(num: int) -> int: + if num in cache: + return cache[num] + + value = rec_fn_memoized(num - 1) + rec_fn_memoized(num - 2) + cache[num] = value + return value + + return [rec_fn_memoized(i) for i in range(n + 1)] + + def fib_binet(n: int) -> list[int]: """ Calculates the first n (0-indexed) Fibonacci numbers using a simplified form @@ -127,4 +166,5 @@ if __name__ == "__main__": num = 20 time_func(fib_iterative, num) time_func(fib_recursive, num) + time_func(fib_memoization, num) time_func(fib_binet, num) From 6680e435a7983c3691f2bb9399e675cc5dc632db Mon Sep 17 00:00:00 2001 From: yellowsto <79023119+yellowsto@users.noreply.github.com> Date: Thu, 16 Dec 2021 10:27:15 +0100 Subject: [PATCH 236/726] Update merge_insertion_sort.py (#5833) * Update merge_insertion_sort.py Fixes #5774 merge_insertion_sort Co-Authored-By: AilisOsswald <44617437+AilisOsswald@users.noreply.github.com> * Update merge_insertion_sort.py Fixes #5774 merge_insertion_sort Co-Authored-By: AilisOsswald <44617437+AilisOsswald@users.noreply.github.com> * Update merge_insertion_sort.py Fixes #5774 added permutation range from 0 to 4 Co-Authored-By: AilisOsswald <44617437+AilisOsswald@users.noreply.github.com> * Use `all()` Co-authored-by: AilisOsswald <44617437+AilisOsswald@users.noreply.github.com> Co-authored-by: John Law --- sorts/merge_insertion_sort.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sorts/merge_insertion_sort.py b/sorts/merge_insertion_sort.py index fb71d84a3..ecaa53545 100644 --- a/sorts/merge_insertion_sort.py +++ b/sorts/merge_insertion_sort.py @@ -30,6 +30,12 @@ def merge_insertion_sort(collection: list[int]) -> list[int]: >>> merge_insertion_sort([-2, -5, -45]) [-45, -5, -2] + + Testing with all permutations on range(0,5): + >>> import itertools + >>> permutations = list(itertools.permutations([0, 1, 2, 3, 4])) + >>> all(merge_insertion_sort(p) == [0, 1, 2, 3, 4] for p in permutations) + True """ def binary_search_insertion(sorted_list, item): @@ -160,7 +166,7 @@ def merge_insertion_sort(collection: list[int]) -> list[int]: """ is_last_odd_item_inserted_before_this_index = False for i in range(len(sorted_list_2d) - 1): - if result[i] == collection[-i]: + if result[i] == collection[-1] and has_last_odd_item: is_last_odd_item_inserted_before_this_index = True pivot = sorted_list_2d[i][1] # If last_odd_item is inserted before the item's index, From 9af2eef9b3761bf51580dedfb6fa7136ca0c5c2c Mon Sep 17 00:00:00 2001 From: RenatoLopes771 <52989307+RenatoLopes771@users.noreply.github.com> Date: Thu, 16 Dec 2021 06:28:31 -0300 Subject: [PATCH 237/726] =?UTF-8?q?Improve=20Quine=E2=80=93McCluskey=20alg?= =?UTF-8?q?orithm=20(#4935)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Syntax improvements (I hope) to boolean algebra * Reverted certain index variables to i * remove extra line on decimal_to_binary * Update quine_mc_cluskey.py Co-authored-by: John Law --- boolean_algebra/quine_mc_cluskey.py | 44 ++++++++++++++--------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/boolean_algebra/quine_mc_cluskey.py b/boolean_algebra/quine_mc_cluskey.py index 0342e5c67..fb23c8c2e 100644 --- a/boolean_algebra/quine_mc_cluskey.py +++ b/boolean_algebra/quine_mc_cluskey.py @@ -1,5 +1,7 @@ from __future__ import annotations +from typing import Sequence + def compare_string(string1: str, string2: str) -> str: """ @@ -9,17 +11,17 @@ def compare_string(string1: str, string2: str) -> str: >>> compare_string('0110','1101') 'X' """ - l1 = list(string1) - l2 = list(string2) + list1 = list(string1) + list2 = list(string2) count = 0 - for i in range(len(l1)): - if l1[i] != l2[i]: + for i in range(len(list1)): + if list1[i] != list2[i]: count += 1 - l1[i] = "_" + list1[i] = "_" if count > 1: return "X" else: - return "".join(l1) + return "".join(list1) def check(binary: list[str]) -> list[str]: @@ -28,7 +30,7 @@ def check(binary: list[str]) -> list[str]: ['0.00.01.5'] """ pi = [] - while 1: + while True: check1 = ["$"] * len(binary) temp = [] for i in range(len(binary)): @@ -46,19 +48,18 @@ 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: Sequence[float]) -> list[str]: """ >>> decimal_to_binary(3,[1.5]) ['0.00.01.5'] """ temp = [] - s = "" - for m in minterms: + for minterm in minterms: + string = "" for i in range(no_of_variable): - s = str(m % 2) + s - m //= 2 - temp.append(s) - s = "" + string = str(minterm % 2) + string + minterm //= 2 + temp.append(string) return temp @@ -70,16 +71,13 @@ def is_for_table(string1: str, string2: str, count: int) -> bool: >>> is_for_table('01_','001',1) False """ - l1 = list(string1) - l2 = list(string2) + list1 = list(string1) + list2 = list(string2) count_n = 0 - for i in range(len(l1)): - if l1[i] != l2[i]: + for i in range(len(list1)): + if list1[i] != list2[i]: count_n += 1 - if count_n == count: - return True - else: - return False + return count_n == count def selection(chart: list[list[int]], prime_implicants: list[str]) -> list[str]: @@ -108,7 +106,7 @@ def selection(chart: list[list[int]], prime_implicants: list[str]) -> list[str]: for k in range(len(chart)): chart[k][j] = 0 temp.append(prime_implicants[i]) - while 1: + while True: max_n = 0 rem = -1 count_n = 0 From 7423875cef469c57abdb2be2c2b1b39490141d89 Mon Sep 17 00:00:00 2001 From: Michael Currin <18750745+MichaelCurrin@users.noreply.github.com> Date: Wed, 26 Jan 2022 17:35:51 +0200 Subject: [PATCH 238/726] ci: add mkdir step for mypy (#5927) * ci: add mkdir step for mypy * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .github/workflows/build.yml | 4 +++- DIRECTORY.md | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index df000cda5..4f270ea55 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,7 +21,9 @@ jobs: run: | python -m pip install --upgrade pip setuptools six wheel python -m pip install mypy pytest-cov -r requirements.txt - - run: mypy --ignore-missing-imports --install-types --non-interactive . + - run: | + mkdir -p .mypy_cache + mypy --ignore-missing-imports --install-types --non-interactive . - name: Run tests run: pytest --doctest-modules --ignore=project_euler/ --ignore=scripts/validate_solutions.py --cov-report=term-missing:skip-covered --cov=. . - if: ${{ success() }} diff --git a/DIRECTORY.md b/DIRECTORY.md index 16244e6ad..550920c0f 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -114,6 +114,7 @@ * [Harris Corner](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/harris_corner.py) * [Mean Threshold](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/mean_threshold.py) * [Mosaic Augmentation](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/mosaic_augmentation.py) + * [Pooling Functions](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/pooling_functions.py) ## Conversions * [Binary To Decimal](https://github.com/TheAlgorithms/Python/blob/master/conversions/binary_to_decimal.py) From c15a4d5af6ade25c967a226877ba567166707aac Mon Sep 17 00:00:00 2001 From: Michael Currin <18750745+MichaelCurrin@users.noreply.github.com> Date: Fri, 28 Jan 2022 08:52:42 +0200 Subject: [PATCH 239/726] Refactor currency_converter.py (#5917) * Update currency_converter.py * refactor: add types and remove reserved keyword "from" usage * feat: update text * Update web_programming/currency_converter.py Co-authored-by: xcodz-dot <71920621+xcodz-dot@users.noreply.github.com> * Update web_programming/currency_converter.py Co-authored-by: xcodz-dot <71920621+xcodz-dot@users.noreply.github.com> * fix: update currency_converter.py * updating DIRECTORY.md * Update currency_converter.py Co-authored-by: xcodz-dot <71920621+xcodz-dot@users.noreply.github.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss --- web_programming/currency_converter.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/web_programming/currency_converter.py b/web_programming/currency_converter.py index 447595b0b..6fcc60e8f 100644 --- a/web_programming/currency_converter.py +++ b/web_programming/currency_converter.py @@ -10,9 +10,11 @@ import requests URL_BASE = "https://www.amdoren.com/api/currency.php" TESTING = os.getenv("CI", False) API_KEY = os.getenv("AMDOREN_API_KEY", "") -if not API_KEY and not TESTING: - raise KeyError("Please put your API key in an environment variable.") +if not API_KEY and not TESTING: + raise KeyError( + "API key must be provided in the 'AMDOREN_API_KEY' environment variable." + ) # Currency and their description list_of_currencies = """ From 24d3cf82445e3f4a2e5287829395a3bf1353a8a3 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sun, 30 Jan 2022 20:29:54 +0100 Subject: [PATCH 240/726] The black formatter is no longer beta (#5960) * The black formatter is no longer beta * pre-commit autoupdate * pre-commit autoupdate * Remove project_euler/problem_145 which is killing our CI tests * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .pre-commit-config.yaml | 16 ++-- DIRECTORY.md | 2 - arithmetic_analysis/bisection.py | 4 +- arithmetic_analysis/in_static_equilibrium.py | 2 +- arithmetic_analysis/intersection.py | 2 +- arithmetic_analysis/newton_method.py | 6 +- arithmetic_analysis/newton_raphson.py | 2 +- ciphers/deterministic_miller_rabin.py | 2 +- ciphers/rabin_miller.py | 2 +- ciphers/rsa_cipher.py | 4 +- ciphers/rsa_factorization.py | 2 +- computer_vision/harris_corner.py | 8 +- .../filters/gabor_filter.py | 2 +- digital_image_processing/index_calculation.py | 6 +- electronics/carrier_concentration.py | 4 +- electronics/coulombs_law.py | 6 +- graphics/bezier_curve.py | 2 +- graphs/bidirectional_a_star.py | 2 +- hashes/chaos_machine.py | 4 +- hashes/hamming_code.py | 2 +- hashes/md5.py | 6 +- linear_algebra/src/lib.py | 2 +- machine_learning/k_means_clust.py | 2 +- .../local_weighted_learning.py | 2 +- .../sequential_minimum_optimization.py | 8 +- maths/area.py | 12 +-- maths/area_under_curve.py | 2 +- maths/armstrong_numbers.py | 4 +- maths/basic_maths.py | 4 +- maths/binomial_distribution.py | 2 +- maths/fibonacci.py | 2 +- maths/gaussian.py | 2 +- maths/karatsuba.py | 4 +- maths/monte_carlo.py | 2 +- maths/numerical_integration.py | 2 +- maths/perfect_square.py | 4 +- maths/pi_monte_carlo_estimation.py | 2 +- maths/polynomial_evaluation.py | 2 +- maths/radix2_fft.py | 2 +- maths/segmented_sieve.py | 2 +- maths/sum_of_geometric_progression.py | 2 +- physics/n_body_simulation.py | 6 +- project_euler/problem_006/sol1.py | 4 +- project_euler/problem_007/sol2.py | 2 +- project_euler/problem_009/sol1.py | 4 +- project_euler/problem_010/sol3.py | 2 +- project_euler/problem_016/sol1.py | 4 +- project_euler/problem_016/sol2.py | 2 +- project_euler/problem_023/sol1.py | 2 +- project_euler/problem_027/sol1.py | 2 +- project_euler/problem_028/sol1.py | 2 +- project_euler/problem_029/sol1.py | 2 +- project_euler/problem_048/sol1.py | 2 +- project_euler/problem_050/sol1.py | 2 +- project_euler/problem_051/sol1.py | 2 +- project_euler/problem_056/sol1.py | 2 +- project_euler/problem_062/sol1.py | 2 +- project_euler/problem_063/sol1.py | 2 +- project_euler/problem_064/sol1.py | 2 +- project_euler/problem_069/sol1.py | 2 +- project_euler/problem_077/sol1.py | 2 +- project_euler/problem_086/sol1.py | 2 +- project_euler/problem_092/sol1.py | 2 +- project_euler/problem_097/sol1.py | 2 +- project_euler/problem_101/sol1.py | 18 ++-- project_euler/problem_125/sol1.py | 6 +- project_euler/problem_144/sol1.py | 6 +- project_euler/problem_145/__init__.py | 0 project_euler/problem_145/sol1.py | 87 ------------------- project_euler/problem_173/sol1.py | 4 +- project_euler/problem_180/sol1.py | 2 +- project_euler/problem_188/sol1.py | 2 +- project_euler/problem_203/sol1.py | 4 +- project_euler/problem_205/sol1.py | 2 +- project_euler/problem_207/sol1.py | 2 +- project_euler/problem_234/sol1.py | 8 +- project_euler/problem_301/sol1.py | 4 +- project_euler/problem_551/sol1.py | 6 +- quantum/deutsch_jozsa.py | 2 +- searches/hill_climbing.py | 4 +- searches/simulated_annealing.py | 4 +- 81 files changed, 139 insertions(+), 228 deletions(-) delete mode 100644 project_euler/problem_145/__init__.py delete mode 100644 project_euler/problem_145/sol1.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0ebd6dfa0..33069a807 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.4.0 + rev: v4.1.0 hooks: - id: check-executables-have-shebangs - id: check-yaml @@ -14,26 +14,26 @@ repos: - id: requirements-txt-fixer - repo: https://github.com/psf/black - rev: 21.4b0 + rev: 22.1.0 hooks: - id: black - repo: https://github.com/PyCQA/isort - rev: 5.8.0 + rev: 5.10.1 hooks: - id: isort args: - --profile=black - repo: https://github.com/asottile/pyupgrade - rev: v2.29.0 + rev: v2.31.0 hooks: - id: pyupgrade args: - --py39-plus - repo: https://gitlab.com/pycqa/flake8 - rev: 3.9.1 + rev: 3.9.2 hooks: - id: flake8 args: @@ -42,7 +42,7 @@ repos: - --max-line-length=88 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.910 + rev: v0.931 hooks: - id: mypy args: @@ -51,11 +51,11 @@ repos: - --non-interactive - repo: https://github.com/codespell-project/codespell - rev: v2.0.0 + rev: v2.1.0 hooks: - id: codespell args: - - --ignore-words-list=ans,crate,fo,followings,hist,iff,mater,secant,som,tim + - --ignore-words-list=ans,crate,fo,followings,hist,iff,mater,secant,som,sur,tim - --skip="./.*,./strings/dictionary.txt,./strings/words.txt,./project_euler/problem_022/p022_names.txt" exclude: | (?x)^( diff --git a/DIRECTORY.md b/DIRECTORY.md index 550920c0f..b5ddb9fcb 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -856,8 +856,6 @@ * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_135/sol1.py) * Problem 144 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_144/sol1.py) - * Problem 145 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_145/sol1.py) * Problem 173 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_173/sol1.py) * Problem 174 diff --git a/arithmetic_analysis/bisection.py b/arithmetic_analysis/bisection.py index 0ef691678..1feb4a8cf 100644 --- a/arithmetic_analysis/bisection.py +++ b/arithmetic_analysis/bisection.py @@ -32,7 +32,7 @@ def bisection(function: Callable[[float], float], a: float, b: float) -> float: raise ValueError("could not find root in given interval.") else: mid: float = start + (end - start) / 2.0 - while abs(start - mid) > 10 ** -7: # until precisely equals to 10^-7 + while abs(start - mid) > 10**-7: # until precisely equals to 10^-7 if function(mid) == 0: return mid elif function(mid) * function(start) < 0: @@ -44,7 +44,7 @@ def bisection(function: Callable[[float], float], a: float, b: float) -> float: def f(x: float) -> float: - return x ** 3 - 2 * x - 5 + return x**3 - 2 * x - 5 if __name__ == "__main__": diff --git a/arithmetic_analysis/in_static_equilibrium.py b/arithmetic_analysis/in_static_equilibrium.py index 6e8d1d043..6fe84b454 100644 --- a/arithmetic_analysis/in_static_equilibrium.py +++ b/arithmetic_analysis/in_static_equilibrium.py @@ -23,7 +23,7 @@ def polar_force( def in_static_equilibrium( - forces: ndarray, location: ndarray, eps: float = 10 ** -1 + forces: ndarray, location: ndarray, eps: float = 10**-1 ) -> bool: """ Check if a system is in equilibrium. diff --git a/arithmetic_analysis/intersection.py b/arithmetic_analysis/intersection.py index 204dd5d8a..9d4651144 100644 --- a/arithmetic_analysis/intersection.py +++ b/arithmetic_analysis/intersection.py @@ -35,7 +35,7 @@ def intersection(function: Callable[[float], float], x0: float, x1: float) -> fl x_n2: float = x_n1 - ( function(x_n1) / ((function(x_n1) - function(x_n)) / (x_n1 - x_n)) ) - if abs(x_n2 - x_n1) < 10 ** -5: + if abs(x_n2 - x_n1) < 10**-5: return x_n2 x_n = x_n1 x_n1 = x_n2 diff --git a/arithmetic_analysis/newton_method.py b/arithmetic_analysis/newton_method.py index a9a943726..f0cf4eaa6 100644 --- a/arithmetic_analysis/newton_method.py +++ b/arithmetic_analysis/newton_method.py @@ -37,17 +37,17 @@ def newton( next_guess = prev_guess - function(prev_guess) / derivative(prev_guess) except ZeroDivisionError: raise ZeroDivisionError("Could not find root") from None - if abs(prev_guess - next_guess) < 10 ** -5: + if abs(prev_guess - next_guess) < 10**-5: return next_guess prev_guess = next_guess def f(x: float) -> float: - return (x ** 3) - (2 * x) - 5 + return (x**3) - (2 * x) - 5 def f1(x: float) -> float: - return 3 * (x ** 2) - 2 + return 3 * (x**2) - 2 if __name__ == "__main__": diff --git a/arithmetic_analysis/newton_raphson.py b/arithmetic_analysis/newton_raphson.py index 1a8205386..86ff9d350 100644 --- a/arithmetic_analysis/newton_raphson.py +++ b/arithmetic_analysis/newton_raphson.py @@ -11,7 +11,7 @@ from sympy import diff def newton_raphson( - func: str, a: 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/ciphers/deterministic_miller_rabin.py b/ciphers/deterministic_miller_rabin.py index d7fcb67e9..2191caf63 100644 --- a/ciphers/deterministic_miller_rabin.py +++ b/ciphers/deterministic_miller_rabin.py @@ -73,7 +73,7 @@ def miller_rabin(n: int, allow_probable: bool = False) -> bool: for prime in plist: pr = False for r in range(s): - m = pow(prime, d * 2 ** r, n) + m = pow(prime, d * 2**r, n) # see article for analysis explanation for m if (r == 0 and m == 1) or ((m + 1) % n == 0): pr = True diff --git a/ciphers/rabin_miller.py b/ciphers/rabin_miller.py index 65c162984..c42ad2f59 100644 --- a/ciphers/rabin_miller.py +++ b/ciphers/rabin_miller.py @@ -21,7 +21,7 @@ def rabinMiller(num: int) -> bool: return False else: i = i + 1 - v = (v ** 2) % num + v = (v**2) % num return True diff --git a/ciphers/rsa_cipher.py b/ciphers/rsa_cipher.py index b1e8a73f3..5bb9f9916 100644 --- a/ciphers/rsa_cipher.py +++ b/ciphers/rsa_cipher.py @@ -29,8 +29,8 @@ def get_text_from_blocks( block_message: list[str] = [] for i in range(block_size - 1, -1, -1): if len(message) + i < message_length: - ascii_number = block_int // (BYTE_SIZE ** i) - block_int = block_int % (BYTE_SIZE ** i) + ascii_number = block_int // (BYTE_SIZE**i) + block_int = block_int % (BYTE_SIZE**i) block_message.insert(0, chr(ascii_number)) message.extend(block_message) return "".join(message) diff --git a/ciphers/rsa_factorization.py b/ciphers/rsa_factorization.py index 6df32b6cc..de4df2777 100644 --- a/ciphers/rsa_factorization.py +++ b/ciphers/rsa_factorization.py @@ -40,7 +40,7 @@ def rsafactor(d: int, e: int, N: int) -> list[int]: while True: if t % 2 == 0: t = t // 2 - x = (g ** t) % N + x = (g**t) % N y = math.gcd(x - 1, N) if x > 1 and y > 1: p = y diff --git a/computer_vision/harris_corner.py b/computer_vision/harris_corner.py index 02deb5408..886ff52ea 100644 --- a/computer_vision/harris_corner.py +++ b/computer_vision/harris_corner.py @@ -39,8 +39,8 @@ class Harris_Corner: color_img = img.copy() color_img = cv2.cvtColor(color_img, cv2.COLOR_GRAY2RGB) dy, dx = np.gradient(img) - ixx = dx ** 2 - iyy = dy ** 2 + ixx = dx**2 + iyy = dy**2 ixy = dx * dy k = 0.04 offset = self.window_size // 2 @@ -56,9 +56,9 @@ class Harris_Corner: y - offset : y + offset + 1, x - offset : x + offset + 1 ].sum() - det = (wxx * wyy) - (wxy ** 2) + det = (wxx * wyy) - (wxy**2) trace = wxx + wyy - r = det - k * (trace ** 2) + r = det - k * (trace**2) # Can change the value if r > 0.5: corner_list.append([x, y, r]) diff --git a/digital_image_processing/filters/gabor_filter.py b/digital_image_processing/filters/gabor_filter.py index 90aa049c2..8f9212a35 100644 --- a/digital_image_processing/filters/gabor_filter.py +++ b/digital_image_processing/filters/gabor_filter.py @@ -49,7 +49,7 @@ def gabor_filter_kernel( # fill kernel gabor[y, x] = np.exp( - -(_x ** 2 + gamma ** 2 * _y ** 2) / (2 * sigma ** 2) + -(_x**2 + gamma**2 * _y**2) / (2 * sigma**2) ) * np.cos(2 * np.pi * _x / lambd + psi) return gabor diff --git a/digital_image_processing/index_calculation.py b/digital_image_processing/index_calculation.py index 4350b8603..033334af8 100644 --- a/digital_image_processing/index_calculation.py +++ b/digital_image_processing/index_calculation.py @@ -203,7 +203,7 @@ class IndexCalculation: https://www.indexdatabase.de/db/i-single.php?id=391 :return: index """ - return self.nir * (self.red / (self.green ** 2)) + return self.nir * (self.red / (self.green**2)) def GLI(self): """ @@ -295,7 +295,7 @@ class IndexCalculation: """ return a * ( (self.nir - a * self.red - b) - / (a * self.nir + self.red - a * b + X * (1 + a ** 2)) + / (a * self.nir + self.red - a * b + X * (1 + a**2)) ) def BWDRVI(self): @@ -363,7 +363,7 @@ class IndexCalculation: https://www.indexdatabase.de/db/i-single.php?id=25 :return: index """ - n = (2 * (self.nir ** 2 - self.red ** 2) + 1.5 * self.nir + 0.5 * self.red) / ( + n = (2 * (self.nir**2 - self.red**2) + 1.5 * self.nir + 0.5 * self.red) / ( self.nir + self.red + 0.5 ) return n * (1 - 0.25 * n) - (self.red - 0.125) / (1 - self.red) diff --git a/electronics/carrier_concentration.py b/electronics/carrier_concentration.py index 87bcad8df..03482f1e3 100644 --- a/electronics/carrier_concentration.py +++ b/electronics/carrier_concentration.py @@ -53,12 +53,12 @@ def carrier_concentration( elif electron_conc == 0: return ( "electron_conc", - intrinsic_conc ** 2 / hole_conc, + intrinsic_conc**2 / hole_conc, ) elif hole_conc == 0: return ( "hole_conc", - intrinsic_conc ** 2 / electron_conc, + intrinsic_conc**2 / electron_conc, ) elif intrinsic_conc == 0: return ( diff --git a/electronics/coulombs_law.py b/electronics/coulombs_law.py index e4c8391c9..e41c0410c 100644 --- a/electronics/coulombs_law.py +++ b/electronics/coulombs_law.py @@ -66,13 +66,13 @@ def couloumbs_law( if distance < 0: raise ValueError("Distance cannot be negative") if force == 0: - force = COULOMBS_CONSTANT * charge_product / (distance ** 2) + force = COULOMBS_CONSTANT * charge_product / (distance**2) return {"force": force} elif charge1 == 0: - charge1 = abs(force) * (distance ** 2) / (COULOMBS_CONSTANT * charge2) + charge1 = abs(force) * (distance**2) / (COULOMBS_CONSTANT * charge2) return {"charge1": charge1} elif charge2 == 0: - charge2 = abs(force) * (distance ** 2) / (COULOMBS_CONSTANT * charge1) + charge2 = abs(force) * (distance**2) / (COULOMBS_CONSTANT * charge1) return {"charge2": charge2} elif distance == 0: distance = (COULOMBS_CONSTANT * charge_product / abs(force)) ** 0.5 diff --git a/graphics/bezier_curve.py b/graphics/bezier_curve.py index 2bb764fdc..7c22329ad 100644 --- a/graphics/bezier_curve.py +++ b/graphics/bezier_curve.py @@ -40,7 +40,7 @@ class BezierCurve: for i in range(len(self.list_of_points)): # basis function for each i output_values.append( - comb(self.degree, i) * ((1 - t) ** (self.degree - i)) * (t ** i) + comb(self.degree, i) * ((1 - t) ** (self.degree - i)) * (t**i) ) # the basis must sum up to 1 for it to produce a valid Bezier curve. assert round(sum(output_values), 5) == 1 diff --git a/graphs/bidirectional_a_star.py b/graphs/bidirectional_a_star.py index 071f1cd68..373d67142 100644 --- a/graphs/bidirectional_a_star.py +++ b/graphs/bidirectional_a_star.py @@ -68,7 +68,7 @@ class Node: if HEURISTIC == 1: return abs(dx) + abs(dy) else: - return sqrt(dy ** 2 + dx ** 2) + return sqrt(dy**2 + dx**2) def __lt__(self, other: Node) -> bool: return self.f_cost < other.f_cost diff --git a/hashes/chaos_machine.py b/hashes/chaos_machine.py index 7ef4fdb3c..7ad3e5540 100644 --- a/hashes/chaos_machine.py +++ b/hashes/chaos_machine.py @@ -63,8 +63,8 @@ def pull(): params_space[key] = (machine_time * 0.01 + r * 1.01) % 1 + 3 # Choosing Chaotic Data - X = int(buffer_space[(key + 2) % m] * (10 ** 10)) - Y = int(buffer_space[(key - 2) % m] * (10 ** 10)) + X = int(buffer_space[(key + 2) % m] * (10**10)) + Y = int(buffer_space[(key - 2) % m] * (10**10)) # Machine Time machine_time += 1 diff --git a/hashes/hamming_code.py b/hashes/hamming_code.py index 4a32bae1a..ac20fe03b 100644 --- a/hashes/hamming_code.py +++ b/hashes/hamming_code.py @@ -78,7 +78,7 @@ def emitterConverter(sizePar, data): >>> emitterConverter(4, "101010111111") ['1', '1', '1', '1', '0', '1', '0', '0', '1', '0', '1', '1', '1', '1', '1', '1'] """ - if sizePar + len(data) <= 2 ** sizePar - (len(data) - 1): + if sizePar + len(data) <= 2**sizePar - (len(data) - 1): print("ERROR - size of parity don't match with size of data") exit(0) diff --git a/hashes/md5.py b/hashes/md5.py index b08ab9573..c56c073cc 100644 --- a/hashes/md5.py +++ b/hashes/md5.py @@ -94,7 +94,7 @@ def not32(i): def sum32(a, b): - return (a + b) % 2 ** 32 + return (a + b) % 2**32 def leftrot32(i, s): @@ -114,7 +114,7 @@ def md5me(testString): bs += format(ord(i), "08b") bs = pad(bs) - tvals = [int(2 ** 32 * abs(math.sin(i + 1))) for i in range(64)] + tvals = [int(2**32 * abs(math.sin(i + 1))) for i in range(64)] a0 = 0x67452301 b0 = 0xEFCDAB89 @@ -211,7 +211,7 @@ def md5me(testString): dtemp = D D = C C = B - B = sum32(B, leftrot32((A + f + tvals[i] + m[g]) % 2 ** 32, s[i])) + B = sum32(B, leftrot32((A + f + tvals[i] + m[g]) % 2**32, s[i])) A = dtemp a0 = sum32(a0, A) b0 = sum32(b0, B) diff --git a/linear_algebra/src/lib.py b/linear_algebra/src/lib.py index 85dc4b71c..2bfcea7f8 100644 --- a/linear_algebra/src/lib.py +++ b/linear_algebra/src/lib.py @@ -172,7 +172,7 @@ class Vector: """ if len(self.__components) == 0: raise Exception("Vector is empty") - squares = [c ** 2 for c in self.__components] + squares = [c**2 for c in self.__components] return math.sqrt(sum(squares)) def angle(self, other: Vector, deg: bool = False) -> float: diff --git a/machine_learning/k_means_clust.py b/machine_learning/k_means_clust.py index c45be8a4c..10c9374d8 100644 --- a/machine_learning/k_means_clust.py +++ b/machine_learning/k_means_clust.py @@ -112,7 +112,7 @@ def compute_heterogeneity(data, k, centroids, cluster_assignment): distances = pairwise_distances( member_data_points, [centroids[i]], metric="euclidean" ) - squared_distances = distances ** 2 + squared_distances = distances**2 heterogeneity += np.sum(squared_distances) return heterogeneity diff --git a/machine_learning/local_weighted_learning/local_weighted_learning.py b/machine_learning/local_weighted_learning/local_weighted_learning.py index af8694bf8..db6868687 100644 --- a/machine_learning/local_weighted_learning/local_weighted_learning.py +++ b/machine_learning/local_weighted_learning/local_weighted_learning.py @@ -25,7 +25,7 @@ def weighted_matrix(point: np.mat, training_data_x: np.mat, bandwidth: float) -> # calculating weights for all training examples [x(i)'s] for j in range(m): diff = point - training_data_x[j] - weights[j, j] = np.exp(diff * diff.T / (-2.0 * bandwidth ** 2)) + weights[j, j] = np.exp(diff * diff.T / (-2.0 * bandwidth**2)) return weights diff --git a/machine_learning/sequential_minimum_optimization.py b/machine_learning/sequential_minimum_optimization.py index 98ce05c46..c217a370a 100644 --- a/machine_learning/sequential_minimum_optimization.py +++ b/machine_learning/sequential_minimum_optimization.py @@ -345,15 +345,15 @@ class SmoSVM: ol = ( l1 * f1 + L * f2 - + 1 / 2 * l1 ** 2 * K(i1, i1) - + 1 / 2 * L ** 2 * K(i2, i2) + + 1 / 2 * l1**2 * K(i1, i1) + + 1 / 2 * L**2 * K(i2, i2) + s * L * l1 * K(i1, i2) ) oh = ( h1 * f1 + H * f2 - + 1 / 2 * h1 ** 2 * K(i1, i1) - + 1 / 2 * H ** 2 * K(i2, i2) + + 1 / 2 * h1**2 * K(i1, i1) + + 1 / 2 * H**2 * K(i2, i2) + s * H * h1 * K(i1, i2) ) """ diff --git a/maths/area.py b/maths/area.py index 7b39312cf..b1b139cf4 100644 --- a/maths/area.py +++ b/maths/area.py @@ -19,7 +19,7 @@ def surface_area_cube(side_length: float) -> float: """ if side_length < 0: raise ValueError("surface_area_cube() only accepts non-negative values") - return 6 * side_length ** 2 + return 6 * side_length**2 def surface_area_sphere(radius: float) -> float: @@ -39,7 +39,7 @@ def surface_area_sphere(radius: float) -> float: """ if radius < 0: raise ValueError("surface_area_sphere() only accepts non-negative values") - return 4 * pi * radius ** 2 + return 4 * pi * radius**2 def surface_area_hemisphere(radius: float) -> float: @@ -62,7 +62,7 @@ def surface_area_hemisphere(radius: float) -> float: """ if radius < 0: raise ValueError("surface_area_hemisphere() only accepts non-negative values") - return 3 * pi * radius ** 2 + return 3 * pi * radius**2 def surface_area_cone(radius: float, height: float) -> float: @@ -90,7 +90,7 @@ def surface_area_cone(radius: float, height: float) -> float: """ if radius < 0 or height < 0: raise ValueError("surface_area_cone() only accepts non-negative values") - return pi * radius * (radius + (height ** 2 + radius ** 2) ** 0.5) + return pi * radius * (radius + (height**2 + radius**2) ** 0.5) def surface_area_cylinder(radius: float, height: float) -> float: @@ -158,7 +158,7 @@ def area_square(side_length: float) -> float: """ if side_length < 0: raise ValueError("area_square() only accepts non-negative values") - return side_length ** 2 + return side_length**2 def area_triangle(base: float, height: float) -> float: @@ -307,7 +307,7 @@ def area_circle(radius: float) -> float: """ if radius < 0: raise ValueError("area_circle() only accepts non-negative values") - return pi * radius ** 2 + return pi * radius**2 def area_ellipse(radius_x: float, radius_y: float) -> float: diff --git a/maths/area_under_curve.py b/maths/area_under_curve.py index ce0932426..6fb3a7c98 100644 --- a/maths/area_under_curve.py +++ b/maths/area_under_curve.py @@ -50,7 +50,7 @@ def trapezoidal_area( if __name__ == "__main__": def f(x): - return x ** 3 + x ** 2 + return x**3 + x**2 print("f(x) = x^3 + x^2") print("The area between the curve, x = -5, x = 5 and the x axis is:") diff --git a/maths/armstrong_numbers.py b/maths/armstrong_numbers.py index 4e62737e1..65aebe937 100644 --- a/maths/armstrong_numbers.py +++ b/maths/armstrong_numbers.py @@ -36,7 +36,7 @@ def armstrong_number(n: int) -> bool: temp = n while temp > 0: rem = temp % 10 - sum += rem ** number_of_digits + sum += rem**number_of_digits temp //= 10 return n == sum @@ -63,7 +63,7 @@ def pluperfect_number(n: int) -> bool: digit_total += 1 for (cnt, i) in zip(digit_histogram, range(len(digit_histogram))): - sum += cnt * i ** digit_total + sum += cnt * i**digit_total return n == sum diff --git a/maths/basic_maths.py b/maths/basic_maths.py index 47d3d91b3..58e797772 100644 --- a/maths/basic_maths.py +++ b/maths/basic_maths.py @@ -81,14 +81,14 @@ def sum_of_divisors(n: int) -> int: temp += 1 n = int(n / 2) if temp > 1: - s *= (2 ** temp - 1) / (2 - 1) + s *= (2**temp - 1) / (2 - 1) for i in range(3, int(math.sqrt(n)) + 1, 2): temp = 1 while n % i == 0: temp += 1 n = int(n / i) if temp > 1: - s *= (i ** temp - 1) / (i - 1) + s *= (i**temp - 1) / (i - 1) return int(s) diff --git a/maths/binomial_distribution.py b/maths/binomial_distribution.py index a74a5a7ed..5b56f2d59 100644 --- a/maths/binomial_distribution.py +++ b/maths/binomial_distribution.py @@ -24,7 +24,7 @@ def binomial_distribution(successes: int, trials: int, prob: float) -> float: raise ValueError("the function is defined for non-negative integers") if not 0 < prob < 1: raise ValueError("prob has to be in range of 1 - 0") - probability = (prob ** successes) * ((1 - prob) ** (trials - successes)) + probability = (prob**successes) * ((1 - prob) ** (trials - successes)) # Calculate the binomial coefficient: n! / k!(n-k)! coefficient = float(factorial(trials)) coefficient /= factorial(successes) * factorial(trials - successes) diff --git a/maths/fibonacci.py b/maths/fibonacci.py index ca4f4a236..07bd6d2ec 100644 --- a/maths/fibonacci.py +++ b/maths/fibonacci.py @@ -159,7 +159,7 @@ def fib_binet(n: int) -> list[int]: raise Exception("n is too large") sqrt_5 = sqrt(5) phi = (1 + sqrt_5) / 2 - return [round(phi ** i / sqrt_5) for i in range(n + 1)] + return [round(phi**i / sqrt_5) for i in range(n + 1)] if __name__ == "__main__": diff --git a/maths/gaussian.py b/maths/gaussian.py index a5dba50a9..51ebc2e25 100644 --- a/maths/gaussian.py +++ b/maths/gaussian.py @@ -52,7 +52,7 @@ def gaussian(x, mu: float = 0.0, sigma: float = 1.0) -> int: >>> gaussian(2523, mu=234234, sigma=3425) 0.0 """ - return 1 / sqrt(2 * pi * sigma ** 2) * exp(-((x - mu) ** 2) / (2 * sigma ** 2)) + return 1 / sqrt(2 * pi * sigma**2) * exp(-((x - mu) ** 2) / (2 * sigma**2)) if __name__ == "__main__": diff --git a/maths/karatsuba.py b/maths/karatsuba.py index df29c77a5..b772c0d77 100644 --- a/maths/karatsuba.py +++ b/maths/karatsuba.py @@ -14,8 +14,8 @@ def karatsuba(a, b): m1 = max(len(str(a)), len(str(b))) m2 = m1 // 2 - a1, a2 = divmod(a, 10 ** m2) - b1, b2 = divmod(b, 10 ** m2) + a1, a2 = divmod(a, 10**m2) + b1, b2 = divmod(b, 10**m2) x = karatsuba(a2, b2) y = karatsuba((a1 + a2), (b1 + b2)) diff --git a/maths/monte_carlo.py b/maths/monte_carlo.py index 28027cbe4..efb6a01d5 100644 --- a/maths/monte_carlo.py +++ b/maths/monte_carlo.py @@ -20,7 +20,7 @@ def pi_estimator(iterations: int): """ # A local function to see if a dot lands in the circle. def is_in_circle(x: float, y: float) -> bool: - distance_from_centre = sqrt((x ** 2) + (y ** 2)) + distance_from_centre = sqrt((x**2) + (y**2)) # Our circle has a radius of 1, so a distance # greater than 1 would land outside the circle. return distance_from_centre <= 1 diff --git a/maths/numerical_integration.py b/maths/numerical_integration.py index 577c41a44..cf2efce12 100644 --- a/maths/numerical_integration.py +++ b/maths/numerical_integration.py @@ -56,7 +56,7 @@ def trapezoidal_area( if __name__ == "__main__": def f(x): - return x ** 3 + return x**3 print("f(x) = x^3") print("The area between the curve, x = -10, x = 10 and the x axis is:") diff --git a/maths/perfect_square.py b/maths/perfect_square.py index 4393dcfbc..107e68528 100644 --- a/maths/perfect_square.py +++ b/maths/perfect_square.py @@ -58,9 +58,9 @@ def perfect_square_binary_search(n: int) -> bool: right = n while left <= right: mid = (left + right) // 2 - if mid ** 2 == n: + if mid**2 == n: return True - elif mid ** 2 > n: + elif mid**2 > n: right = mid - 1 else: left = mid + 1 diff --git a/maths/pi_monte_carlo_estimation.py b/maths/pi_monte_carlo_estimation.py index 20b46dddc..81be08378 100644 --- a/maths/pi_monte_carlo_estimation.py +++ b/maths/pi_monte_carlo_estimation.py @@ -11,7 +11,7 @@ class Point: True, if the point lies in the unit circle False, otherwise """ - return (self.x ** 2 + self.y ** 2) <= 1 + return (self.x**2 + self.y**2) <= 1 @classmethod def random_unit_square(cls): diff --git a/maths/polynomial_evaluation.py b/maths/polynomial_evaluation.py index 68ff97ddd..4e4016e51 100644 --- a/maths/polynomial_evaluation.py +++ b/maths/polynomial_evaluation.py @@ -12,7 +12,7 @@ def evaluate_poly(poly: Sequence[float], x: float) -> float: >>> evaluate_poly((0.0, 0.0, 5.0, 9.3, 7.0), 10.0) 79800.0 """ - return sum(c * (x ** i) for i, c in enumerate(poly)) + return sum(c * (x**i) for i, c in enumerate(poly)) def horner(poly: Sequence[float], x: float) -> float: diff --git a/maths/radix2_fft.py b/maths/radix2_fft.py index 9fc9f843e..0a431a115 100644 --- a/maths/radix2_fft.py +++ b/maths/radix2_fft.py @@ -91,7 +91,7 @@ class FFT: next_ncol = self.C_max_length // 2 while next_ncol > 0: new_dft = [[] for i in range(next_ncol)] - root = self.root ** next_ncol + root = self.root**next_ncol # First half of next step current_root = 1 diff --git a/maths/segmented_sieve.py b/maths/segmented_sieve.py index c1cc497ad..b15ec2480 100644 --- a/maths/segmented_sieve.py +++ b/maths/segmented_sieve.py @@ -48,4 +48,4 @@ def sieve(n): return prime -print(sieve(10 ** 6)) +print(sieve(10**6)) diff --git a/maths/sum_of_geometric_progression.py b/maths/sum_of_geometric_progression.py index f29dd8005..9079f35af 100644 --- a/maths/sum_of_geometric_progression.py +++ b/maths/sum_of_geometric_progression.py @@ -25,4 +25,4 @@ def sum_of_geometric_progression( return num_of_terms * first_term # Formula for finding sum of n terms of a GeometricProgression - return (first_term / (1 - common_ratio)) * (1 - common_ratio ** num_of_terms) + return (first_term / (1 - common_ratio)) * (1 - common_ratio**num_of_terms) diff --git a/physics/n_body_simulation.py b/physics/n_body_simulation.py index 045a49f7f..01083b9a2 100644 --- a/physics/n_body_simulation.py +++ b/physics/n_body_simulation.py @@ -159,16 +159,16 @@ class BodySystem: # Calculation of the distance using Pythagoras's theorem # Extra factor due to the softening technique - distance = (dif_x ** 2 + dif_y ** 2 + self.softening_factor) ** ( + distance = (dif_x**2 + dif_y**2 + self.softening_factor) ** ( 1 / 2 ) # Newton's law of universal gravitation. force_x += ( - self.gravitation_constant * body2.mass * dif_x / distance ** 3 + self.gravitation_constant * body2.mass * dif_x / distance**3 ) force_y += ( - self.gravitation_constant * body2.mass * dif_y / distance ** 3 + self.gravitation_constant * body2.mass * dif_y / distance**3 ) # Update the body's velocity once all the force components have been added diff --git a/project_euler/problem_006/sol1.py b/project_euler/problem_006/sol1.py index 61dd7a321..615991bb1 100644 --- a/project_euler/problem_006/sol1.py +++ b/project_euler/problem_006/sol1.py @@ -35,9 +35,9 @@ def solution(n: int = 100) -> int: sum_of_squares = 0 sum_of_ints = 0 for i in range(1, n + 1): - sum_of_squares += i ** 2 + sum_of_squares += i**2 sum_of_ints += i - return sum_of_ints ** 2 - sum_of_squares + return sum_of_ints**2 - sum_of_squares if __name__ == "__main__": diff --git a/project_euler/problem_007/sol2.py b/project_euler/problem_007/sol2.py index 20c2ddf21..dfcad8c14 100644 --- a/project_euler/problem_007/sol2.py +++ b/project_euler/problem_007/sol2.py @@ -25,7 +25,7 @@ def isprime(number: int) -> bool: True """ - for i in range(2, int(number ** 0.5) + 1): + for i in range(2, int(number**0.5) + 1): if number % i == 0: return False return True diff --git a/project_euler/problem_009/sol1.py b/project_euler/problem_009/sol1.py index 83c88acf1..1d908402b 100644 --- a/project_euler/problem_009/sol1.py +++ b/project_euler/problem_009/sol1.py @@ -33,7 +33,7 @@ def solution() -> int: for b in range(a + 1, 400): for c in range(b + 1, 500): if (a + b + c) == 1000: - if (a ** 2) + (b ** 2) == (c ** 2): + if (a**2) + (b**2) == (c**2): return a * b * c return -1 @@ -54,7 +54,7 @@ def solution_fast() -> int: for a in range(300): for b in range(400): c = 1000 - a - b - if a < b < c and (a ** 2) + (b ** 2) == (c ** 2): + if a < b < c and (a**2) + (b**2) == (c**2): return a * b * c return -1 diff --git a/project_euler/problem_010/sol3.py b/project_euler/problem_010/sol3.py index f49d9393c..72e2894df 100644 --- a/project_euler/problem_010/sol3.py +++ b/project_euler/problem_010/sol3.py @@ -46,7 +46,7 @@ def solution(n: int = 2000000) -> int: primality_list[0] = 1 primality_list[1] = 1 - for i in range(2, int(n ** 0.5) + 1): + for i in range(2, int(n**0.5) + 1): if primality_list[i] == 0: for j in range(i * i, n + 1, i): primality_list[j] = 1 diff --git a/project_euler/problem_016/sol1.py b/project_euler/problem_016/sol1.py index f6620aa94..93584d1d4 100644 --- a/project_euler/problem_016/sol1.py +++ b/project_euler/problem_016/sol1.py @@ -18,7 +18,7 @@ def solution(power: int = 1000) -> int: >>> solution(15) 26 """ - num = 2 ** power + num = 2**power string_num = str(num) list_num = list(string_num) sum_of_num = 0 @@ -31,6 +31,6 @@ def solution(power: int = 1000) -> int: if __name__ == "__main__": power = int(input("Enter the power of 2: ").strip()) - print("2 ^ ", power, " = ", 2 ** power) + print("2 ^ ", power, " = ", 2**power) result = solution(power) print("Sum of the digits is: ", result) diff --git a/project_euler/problem_016/sol2.py b/project_euler/problem_016/sol2.py index 304d27d1e..1408212e7 100644 --- a/project_euler/problem_016/sol2.py +++ b/project_euler/problem_016/sol2.py @@ -19,7 +19,7 @@ def solution(power: int = 1000) -> int: >>> solution(15) 26 """ - n = 2 ** power + n = 2**power r = 0 while n: r, n = r + n % 10, n // 10 diff --git a/project_euler/problem_023/sol1.py b/project_euler/problem_023/sol1.py index a72b6123e..83b85f3f7 100644 --- a/project_euler/problem_023/sol1.py +++ b/project_euler/problem_023/sol1.py @@ -30,7 +30,7 @@ def solution(limit=28123): """ sumDivs = [1] * (limit + 1) - for i in range(2, int(limit ** 0.5) + 1): + for i in range(2, int(limit**0.5) + 1): sumDivs[i * i] += i for k in range(i + 1, limit // i + 1): sumDivs[k * i] += k + i diff --git a/project_euler/problem_027/sol1.py b/project_euler/problem_027/sol1.py index 6f28b925b..928c0ec4f 100644 --- a/project_euler/problem_027/sol1.py +++ b/project_euler/problem_027/sol1.py @@ -61,7 +61,7 @@ def solution(a_limit: int = 1000, b_limit: int = 1000) -> int: if is_prime(b): count = 0 n = 0 - while is_prime((n ** 2) + (a * n) + b): + while is_prime((n**2) + (a * n) + b): count += 1 n += 1 if count > longest[0]: diff --git a/project_euler/problem_028/sol1.py b/project_euler/problem_028/sol1.py index cbc7de6be..1ea5d4fca 100644 --- a/project_euler/problem_028/sol1.py +++ b/project_euler/problem_028/sol1.py @@ -40,7 +40,7 @@ def solution(n: int = 1001) -> int: for i in range(1, int(ceil(n / 2.0))): odd = 2 * i + 1 even = 2 * i - total = total + 4 * odd ** 2 - 6 * even + total = total + 4 * odd**2 - 6 * even return total diff --git a/project_euler/problem_029/sol1.py b/project_euler/problem_029/sol1.py index 726bcaf6e..d3ab90ac7 100644 --- a/project_euler/problem_029/sol1.py +++ b/project_euler/problem_029/sol1.py @@ -41,7 +41,7 @@ def solution(n: int = 100) -> int: for a in range(2, N): for b in range(2, N): - currentPow = a ** b # calculates the current power + currentPow = a**b # calculates the current power collectPowers.add(currentPow) # adds the result to the set return len(collectPowers) diff --git a/project_euler/problem_048/sol1.py b/project_euler/problem_048/sol1.py index 01ff702d9..5a4538cf5 100644 --- a/project_euler/problem_048/sol1.py +++ b/project_euler/problem_048/sol1.py @@ -17,7 +17,7 @@ def solution(): """ total = 0 for i in range(1, 1001): - total += i ** i + total += i**i return str(total)[-10:] diff --git a/project_euler/problem_050/sol1.py b/project_euler/problem_050/sol1.py index cfb1911df..fc6e6f2b9 100644 --- a/project_euler/problem_050/sol1.py +++ b/project_euler/problem_050/sol1.py @@ -35,7 +35,7 @@ def prime_sieve(limit: int) -> list[int]: is_prime[1] = False is_prime[2] = True - for i in range(3, int(limit ** 0.5 + 1), 2): + for i in range(3, int(limit**0.5 + 1), 2): index = i * 2 while index < limit: is_prime[index] = False diff --git a/project_euler/problem_051/sol1.py b/project_euler/problem_051/sol1.py index eedb02379..921704bc4 100644 --- a/project_euler/problem_051/sol1.py +++ b/project_euler/problem_051/sol1.py @@ -37,7 +37,7 @@ def prime_sieve(n: int) -> list[int]: is_prime[1] = False is_prime[2] = True - for i in range(3, int(n ** 0.5 + 1), 2): + for i in range(3, int(n**0.5 + 1), 2): index = i * 2 while index < n: is_prime[index] = False diff --git a/project_euler/problem_056/sol1.py b/project_euler/problem_056/sol1.py index f1ec03c49..c772bec58 100644 --- a/project_euler/problem_056/sol1.py +++ b/project_euler/problem_056/sol1.py @@ -30,7 +30,7 @@ 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)) + 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_062/sol1.py b/project_euler/problem_062/sol1.py index 83286c801..0c9baf880 100644 --- a/project_euler/problem_062/sol1.py +++ b/project_euler/problem_062/sol1.py @@ -55,7 +55,7 @@ def get_digits(num: int) -> str: >>> get_digits(123) '0166788' """ - return "".join(sorted(list(str(num ** 3)))) + return "".join(sorted(list(str(num**3)))) if __name__ == "__main__": diff --git a/project_euler/problem_063/sol1.py b/project_euler/problem_063/sol1.py index 29efddba4..bea30a2e5 100644 --- a/project_euler/problem_063/sol1.py +++ b/project_euler/problem_063/sol1.py @@ -26,7 +26,7 @@ def solution(max_base: int = 10, max_power: int = 22) -> int: bases = range(1, max_base) powers = range(1, max_power) return sum( - 1 for power in powers for base in bases if len(str(base ** power)) == power + 1 for power in powers for base in bases if len(str(base**power)) == power ) diff --git a/project_euler/problem_064/sol1.py b/project_euler/problem_064/sol1.py index 69e3f6d97..5df64a90a 100644 --- a/project_euler/problem_064/sol1.py +++ b/project_euler/problem_064/sol1.py @@ -38,7 +38,7 @@ def continuous_fraction_period(n: int) -> int: period = 0 while integer_part != 2 * ROOT: numerator = denominator * integer_part - numerator - denominator = (n - numerator ** 2) / denominator + denominator = (n - numerator**2) / denominator integer_part = int((ROOT + numerator) / denominator) period += 1 return period diff --git a/project_euler/problem_069/sol1.py b/project_euler/problem_069/sol1.py index d148dd79a..5dfd61a89 100644 --- a/project_euler/problem_069/sol1.py +++ b/project_euler/problem_069/sol1.py @@ -24,7 +24,7 @@ Find the value of n ≤ 1,000,000 for which n/φ(n) is a maximum. """ -def solution(n: int = 10 ** 6) -> int: +def solution(n: int = 10**6) -> int: """ Returns solution to problem. Algorithm: diff --git a/project_euler/problem_077/sol1.py b/project_euler/problem_077/sol1.py index 214e25879..6098ea9e5 100644 --- a/project_euler/problem_077/sol1.py +++ b/project_euler/problem_077/sol1.py @@ -23,7 +23,7 @@ primes = set(range(3, NUM_PRIMES, 2)) primes.add(2) prime: int -for prime in range(3, ceil(NUM_PRIMES ** 0.5), 2): +for prime in range(3, ceil(NUM_PRIMES**0.5), 2): if prime not in primes: continue primes.difference_update(set(range(prime * prime, NUM_PRIMES, prime))) diff --git a/project_euler/problem_086/sol1.py b/project_euler/problem_086/sol1.py index 0bf66e6b5..064af215c 100644 --- a/project_euler/problem_086/sol1.py +++ b/project_euler/problem_086/sol1.py @@ -91,7 +91,7 @@ def solution(limit: int = 1000000) -> int: while num_cuboids <= limit: max_cuboid_size += 1 for sum_shortest_sides in range(2, 2 * max_cuboid_size + 1): - if sqrt(sum_shortest_sides ** 2 + max_cuboid_size ** 2).is_integer(): + if sqrt(sum_shortest_sides**2 + max_cuboid_size**2).is_integer(): num_cuboids += ( min(max_cuboid_size, sum_shortest_sides // 2) - max(1, sum_shortest_sides - max_cuboid_size) diff --git a/project_euler/problem_092/sol1.py b/project_euler/problem_092/sol1.py index 437a85bad..d326fc33f 100644 --- a/project_euler/problem_092/sol1.py +++ b/project_euler/problem_092/sol1.py @@ -12,7 +12,7 @@ How many starting numbers below ten million will arrive at 89? """ -DIGITS_SQUARED = [digit ** 2 for digit in range(10)] +DIGITS_SQUARED = [digit**2 for digit in range(10)] def next_number(number: int) -> int: diff --git a/project_euler/problem_097/sol1.py b/project_euler/problem_097/sol1.py index 2e848c09a..da5e8120b 100644 --- a/project_euler/problem_097/sol1.py +++ b/project_euler/problem_097/sol1.py @@ -34,7 +34,7 @@ def solution(n: int = 10) -> str: """ if not isinstance(n, int) or n < 0: raise ValueError("Invalid input") - MODULUS = 10 ** n + MODULUS = 10**n NUMBER = 28433 * (pow(2, 7830457, MODULUS)) + 1 return str(NUMBER % MODULUS) diff --git a/project_euler/problem_101/sol1.py b/project_euler/problem_101/sol1.py index 14013c435..046788475 100644 --- a/project_euler/problem_101/sol1.py +++ b/project_euler/problem_101/sol1.py @@ -175,15 +175,15 @@ def question_function(variable: int) -> int: return ( 1 - variable - + variable ** 2 - - variable ** 3 - + variable ** 4 - - variable ** 5 - + variable ** 6 - - variable ** 7 - + variable ** 8 - - variable ** 9 - + variable ** 10 + + variable**2 + - variable**3 + + variable**4 + - variable**5 + + variable**6 + - variable**7 + + variable**8 + - variable**9 + + variable**10 ) diff --git a/project_euler/problem_125/sol1.py b/project_euler/problem_125/sol1.py index afc1f2890..7a8f908ed 100644 --- a/project_euler/problem_125/sol1.py +++ b/project_euler/problem_125/sol1.py @@ -35,7 +35,7 @@ def solution() -> int: Returns the sum of all numbers less than 1e8 that are both palindromic and can be written as the sum of consecutive squares. """ - LIMIT = 10 ** 8 + LIMIT = 10**8 answer = set() first_square = 1 sum_squares = 5 @@ -45,9 +45,9 @@ def solution() -> int: if is_palindrome(sum_squares): answer.add(sum_squares) last_square += 1 - sum_squares += last_square ** 2 + sum_squares += last_square**2 first_square += 1 - sum_squares = first_square ** 2 + (first_square + 1) ** 2 + sum_squares = first_square**2 + (first_square + 1) ** 2 return sum(answer) diff --git a/project_euler/problem_144/sol1.py b/project_euler/problem_144/sol1.py index 3f7a766be..b5f103b64 100644 --- a/project_euler/problem_144/sol1.py +++ b/project_euler/problem_144/sol1.py @@ -58,15 +58,15 @@ def next_point( # y^2 + 4x^2 = 100 # y - b = m * (x - a) # ==> A x^2 + B x + C = 0 - quadratic_term = outgoing_gradient ** 2 + 4 + quadratic_term = outgoing_gradient**2 + 4 linear_term = 2 * outgoing_gradient * (point_y - outgoing_gradient * point_x) constant_term = (point_y - outgoing_gradient * point_x) ** 2 - 100 x_minus = ( - -linear_term - sqrt(linear_term ** 2 - 4 * quadratic_term * constant_term) + -linear_term - sqrt(linear_term**2 - 4 * quadratic_term * constant_term) ) / (2 * quadratic_term) x_plus = ( - -linear_term + sqrt(linear_term ** 2 - 4 * quadratic_term * constant_term) + -linear_term + sqrt(linear_term**2 - 4 * quadratic_term * constant_term) ) / (2 * quadratic_term) # two solutions, one of which is our input point diff --git a/project_euler/problem_145/__init__.py b/project_euler/problem_145/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/project_euler/problem_145/sol1.py b/project_euler/problem_145/sol1.py deleted file mode 100644 index 5ba3af86a..000000000 --- a/project_euler/problem_145/sol1.py +++ /dev/null @@ -1,87 +0,0 @@ -""" -Problem 145: https://projecteuler.net/problem=145 - -Name: How many reversible numbers are there below one-billion? - -Some positive integers n have the property that the -sum [ n + reverse(n) ] consists entirely of odd (decimal) digits. -For instance, 36 + 63 = 99 and 409 + 904 = 1313. -We will call such numbers reversible; so 36, 63, 409, and 904 are reversible. -Leading zeroes are not allowed in either n or reverse(n). - -There are 120 reversible numbers below one-thousand. - -How many reversible numbers are there below one-billion (10^9)? - - -Solution: - -Here a brute force solution is used to find and count the reversible numbers. - -""" -from __future__ import annotations - - -def check_if_odd(sum: int = 36) -> int: - """ - Check if the last digit in the sum is even or odd. If even return 0. - If odd then floor division by 10 is used to remove the last number. - Process continues until sum becomes 0 because no more numbers. - >>> check_if_odd(36) - 0 - >>> check_if_odd(33) - 1 - """ - while sum > 0: - if (sum % 10) % 2 == 0: - return 0 - sum = sum // 10 - return 1 - - -def find_reverse_number(number: int = 36) -> int: - """ - Reverses the given number. Does not work with number that end in zero. - >>> find_reverse_number(36) - 63 - >>> find_reverse_number(409) - 904 - """ - reverse = 0 - - while number > 0: - temp = number % 10 - reverse = reverse * 10 + temp - number = number // 10 - - return reverse - - -def solution(number: int = 1000000000) -> int: - """ - Loops over the range of numbers. - Checks if they have ending zeros which disqualifies them from being reversible. - If that condition is passed it generates the reversed number. - Then sum up n and reverse(n). - Then check if all the numbers in the sum are odd. If true add to the answer. - >>> solution(1000000000) - 608720 - >>> solution(1000000) - 18720 - >>> solution(1000000) - 18720 - >>> solution(1000) - 120 - """ - answer = 0 - for x in range(1, number): - if x % 10 != 0: - reversed_number = find_reverse_number(x) - sum = x + reversed_number - answer += check_if_odd(sum) - - return answer - - -if __name__ == "__main__": - print(f"{solution() = }") diff --git a/project_euler/problem_173/sol1.py b/project_euler/problem_173/sol1.py index d539b1437..5416e2546 100644 --- a/project_euler/problem_173/sol1.py +++ b/project_euler/problem_173/sol1.py @@ -25,8 +25,8 @@ def solution(limit: int = 1000000) -> int: answer = 0 for outer_width in range(3, (limit // 4) + 2): - if outer_width ** 2 > limit: - hole_width_lower_bound = max(ceil(sqrt(outer_width ** 2 - limit)), 1) + if outer_width**2 > limit: + hole_width_lower_bound = max(ceil(sqrt(outer_width**2 - limit)), 1) else: hole_width_lower_bound = 1 if (outer_width - hole_width_lower_bound) % 2: diff --git a/project_euler/problem_180/sol1.py b/project_euler/problem_180/sol1.py index f7c097323..12e34dcaa 100644 --- a/project_euler/problem_180/sol1.py +++ b/project_euler/problem_180/sol1.py @@ -61,7 +61,7 @@ def is_sq(number: int) -> bool: >>> is_sq(1000000) True """ - sq: int = int(number ** 0.5) + sq: int = int(number**0.5) return number == sq * sq diff --git a/project_euler/problem_188/sol1.py b/project_euler/problem_188/sol1.py index c8cd9eb10..dd4360adb 100644 --- a/project_euler/problem_188/sol1.py +++ b/project_euler/problem_188/sol1.py @@ -59,7 +59,7 @@ def solution(base: int = 1777, height: int = 1855, digits: int = 8) -> int: # exponentiation result = base for i in range(1, height): - result = _modexpt(base, result, 10 ** digits) + result = _modexpt(base, result, 10**digits) return result diff --git a/project_euler/problem_203/sol1.py b/project_euler/problem_203/sol1.py index fe4d14b20..2ba3c96c9 100644 --- a/project_euler/problem_203/sol1.py +++ b/project_euler/problem_203/sol1.py @@ -82,10 +82,10 @@ def get_primes_squared(max_number: int) -> list[int]: if non_primes[num]: continue - for num_counter in range(num ** 2, max_prime + 1, num): + for num_counter in range(num**2, max_prime + 1, num): non_primes[num_counter] = True - primes.append(num ** 2) + primes.append(num**2) return primes diff --git a/project_euler/problem_205/sol1.py b/project_euler/problem_205/sol1.py index 7249df488..63b997b9f 100644 --- a/project_euler/problem_205/sol1.py +++ b/project_euler/problem_205/sol1.py @@ -63,7 +63,7 @@ def solution() -> float: colin_totals_frequencies[min_colin_total:peter_total] ) - total_games_number = (4 ** 9) * (6 ** 6) + total_games_number = (4**9) * (6**6) peter_win_probability = peter_wins_count / total_games_number rounded_peter_win_probability = round(peter_win_probability, ndigits=7) diff --git a/project_euler/problem_207/sol1.py b/project_euler/problem_207/sol1.py index 99d1a9174..2b3591f51 100644 --- a/project_euler/problem_207/sol1.py +++ b/project_euler/problem_207/sol1.py @@ -81,7 +81,7 @@ def solution(max_proportion: float = 1 / 12345) -> int: integer = 3 while True: - partition_candidate = (integer ** 2 - 1) / 4 + partition_candidate = (integer**2 - 1) / 4 # if candidate is an integer, then there is a partition for k if partition_candidate == int(partition_candidate): partition_candidate = int(partition_candidate) diff --git a/project_euler/problem_234/sol1.py b/project_euler/problem_234/sol1.py index 7516b164d..7b20a2206 100644 --- a/project_euler/problem_234/sol1.py +++ b/project_euler/problem_234/sol1.py @@ -35,7 +35,7 @@ def prime_sieve(n: int) -> list: is_prime[1] = False is_prime[2] = True - for i in range(3, int(n ** 0.5 + 1), 2): + for i in range(3, int(n**0.5 + 1), 2): index = i * 2 while index < n: is_prime[index] = False @@ -69,11 +69,11 @@ def solution(limit: int = 999_966_663_333) -> int: prime_index = 0 last_prime = primes[prime_index] - while (last_prime ** 2) <= limit: + while (last_prime**2) <= limit: next_prime = primes[prime_index + 1] - lower_bound = last_prime ** 2 - upper_bound = next_prime ** 2 + lower_bound = last_prime**2 + upper_bound = next_prime**2 # Get numbers divisible by lps(current) current = lower_bound + last_prime diff --git a/project_euler/problem_301/sol1.py b/project_euler/problem_301/sol1.py index b1d434c18..4b494033c 100644 --- a/project_euler/problem_301/sol1.py +++ b/project_euler/problem_301/sol1.py @@ -48,8 +48,8 @@ def solution(exponent: int = 30) -> int: # To find how many total games were lost for a given exponent x, # we need to find the Fibonacci number F(x+2). fibonacci_index = exponent + 2 - phi = (1 + 5 ** 0.5) / 2 - fibonacci = (phi ** fibonacci_index - (phi - 1) ** fibonacci_index) / 5 ** 0.5 + phi = (1 + 5**0.5) / 2 + fibonacci = (phi**fibonacci_index - (phi - 1) ** fibonacci_index) / 5**0.5 return int(fibonacci) diff --git a/project_euler/problem_551/sol1.py b/project_euler/problem_551/sol1.py index 005d2e985..c15445e4d 100644 --- a/project_euler/problem_551/sol1.py +++ b/project_euler/problem_551/sol1.py @@ -14,7 +14,7 @@ Find a(10^15) ks = [k for k in range(2, 20 + 1)] -base = [10 ** k for k in range(ks[-1] + 1)] +base = [10**k for k in range(ks[-1] + 1)] memo: dict[int, dict[int, list[list[int]]]] = {} @@ -168,7 +168,7 @@ def add(digits, k, addend): digits.append(digit) -def solution(n: int = 10 ** 15) -> int: +def solution(n: int = 10**15) -> int: """ returns n-th term of sequence @@ -193,7 +193,7 @@ def solution(n: int = 10 ** 15) -> int: a_n = 0 for j in range(len(digits)): - a_n += digits[j] * 10 ** j + a_n += digits[j] * 10**j return a_n diff --git a/quantum/deutsch_jozsa.py b/quantum/deutsch_jozsa.py index 304eea196..d7e2d8335 100755 --- a/quantum/deutsch_jozsa.py +++ b/quantum/deutsch_jozsa.py @@ -39,7 +39,7 @@ def dj_oracle(case: str, num_qubits: int) -> q.QuantumCircuit: if case == "balanced": # First generate a random number that tells us which CNOTs to # wrap in X-gates: - b = np.random.randint(1, 2 ** num_qubits) + b = np.random.randint(1, 2**num_qubits) # Next, format 'b' as a binary string of length 'n', padded with zeros: b_str = format(b, f"0{num_qubits}b") # Next, we place the first X-gates. Each digit in our binary string diff --git a/searches/hill_climbing.py b/searches/hill_climbing.py index bb24e781a..83a3b8b74 100644 --- a/searches/hill_climbing.py +++ b/searches/hill_climbing.py @@ -166,7 +166,7 @@ if __name__ == "__main__": doctest.testmod() def test_f1(x, y): - return (x ** 2) + (y ** 2) + return (x**2) + (y**2) # starting the problem with initial coordinates (3, 4) prob = SearchProblem(x=3, y=4, step_size=1, function_to_optimize=test_f1) @@ -187,7 +187,7 @@ if __name__ == "__main__": ) def test_f2(x, y): - return (3 * x ** 2) - (6 * y) + return (3 * x**2) - (6 * y) prob = SearchProblem(x=3, y=4, step_size=1, function_to_optimize=test_f1) local_min = hill_climbing(prob, find_max=True) diff --git a/searches/simulated_annealing.py b/searches/simulated_annealing.py index ad29559f1..063d225d0 100644 --- a/searches/simulated_annealing.py +++ b/searches/simulated_annealing.py @@ -97,7 +97,7 @@ def simulated_annealing( if __name__ == "__main__": def test_f1(x, y): - return (x ** 2) + (y ** 2) + return (x**2) + (y**2) # starting the problem with initial coordinates (12, 47) prob = SearchProblem(x=12, y=47, step_size=1, function_to_optimize=test_f1) @@ -120,7 +120,7 @@ if __name__ == "__main__": ) def test_f2(x, y): - return (3 * x ** 2) - (6 * y) + return (3 * x**2) - (6 * y) prob = SearchProblem(x=3, y=4, step_size=1, function_to_optimize=test_f1) local_min = simulated_annealing(prob, find_max=False, visualization=True) From b2a77cc4fb922ab66f0978e45c108bdb4c30396d Mon Sep 17 00:00:00 2001 From: Saptarshi Sengupta <94242536+saptarshi1996@users.noreply.github.com> Date: Mon, 31 Jan 2022 06:11:46 +0530 Subject: [PATCH 241/726] Scraping prescription drug prices from Rx site using the prescription drug name and zipcode (#5967) * add wellrx scraping * write test fix docs * fix resolve issues * black format. fix returns * type check fix for union * black formatted * Change requests after code review * add precommit changes * flake errors --- web_programming/fetch_well_rx_price.py | 102 +++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 web_programming/fetch_well_rx_price.py diff --git a/web_programming/fetch_well_rx_price.py b/web_programming/fetch_well_rx_price.py new file mode 100644 index 000000000..58dbe5993 --- /dev/null +++ b/web_programming/fetch_well_rx_price.py @@ -0,0 +1,102 @@ +""" + +Scrape the price and pharmacy name for a prescription drug from rx site +after providing the drug name and zipcode. + +""" + +from typing import Union +from urllib.error import HTTPError + +from bs4 import BeautifulSoup +from requests import exceptions, get + +BASE_URL = "https://www.wellrx.com/prescriptions/{0}/{1}/?freshSearch=true" + + +def fetch_pharmacy_and_price_list(drug_name: str, zip_code: str) -> Union[list, None]: + """[summary] + + This function will take input of drug name and zipcode, + then request to the BASE_URL site. + Get the page data and scrape it to the generate the + list of lowest prices for the prescription drug. + + Args: + drug_name (str): [Drug name] + zip_code(str): [Zip code] + + Returns: + list: [List of pharmacy name and price] + + >>> fetch_pharmacy_and_price_list(None, None) + + >>> fetch_pharmacy_and_price_list(None, 30303) + + >>> fetch_pharmacy_and_price_list("eliquis", None) + + """ + + try: + + # Has user provided both inputs? + if not drug_name or not zip_code: + return None + + request_url = BASE_URL.format(drug_name, zip_code) + response = get(request_url) + + # Is the response ok? + response.raise_for_status() + + # Scrape the data using bs4 + soup = BeautifulSoup(response.text, "html.parser") + + # This list will store the name and price. + pharmacy_price_list = [] + + # Fetch all the grids that contains the items. + grid_list = soup.find_all("div", {"class": "grid-x pharmCard"}) + if grid_list and len(grid_list) > 0: + for grid in grid_list: + + # Get the pharmacy price. + pharmacy_name = grid.find("p", {"class": "list-title"}).text + + # Get price of the drug. + price = grid.find("span", {"p", "price price-large"}).text + + pharmacy_price_list.append( + { + "pharmacy_name": pharmacy_name, + "price": price, + } + ) + + return pharmacy_price_list + + except (HTTPError, exceptions.RequestException, ValueError): + return None + + +if __name__ == "__main__": + + # Enter a drug name and a zip code + drug_name = input("Enter drug name: ").strip() + zip_code = input("Enter zip code: ").strip() + + pharmacy_price_list: Union[list, None] = fetch_pharmacy_and_price_list( + drug_name, zip_code + ) + + if pharmacy_price_list: + + print(f"\nSearch results for {drug_name} at location {zip_code}:") + for pharmacy_price in pharmacy_price_list: + + name = pharmacy_price["pharmacy_name"] + price = pharmacy_price["price"] + + print(f"Pharmacy: {name} Price: {price}") + else: + print(f"No results found for {drug_name}") From d28ac6483a97deb5ac09a5261d851e97a25c2ee5 Mon Sep 17 00:00:00 2001 From: Saptarshi Sengupta <94242536+saptarshi1996@users.noreply.github.com> Date: Wed, 2 Feb 2022 03:49:17 +0530 Subject: [PATCH 242/726] Scrape anime and play episodes on browser without ads from terminal (#5975) * fetch anime * formatted code * fix format errors * fix bot reviews * pr review fixes * remove unussed exception * change var name * fix comments --- web_programming/fetch_anime_and_play.py | 188 ++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 web_programming/fetch_anime_and_play.py diff --git a/web_programming/fetch_anime_and_play.py b/web_programming/fetch_anime_and_play.py new file mode 100644 index 000000000..e11948d0a --- /dev/null +++ b/web_programming/fetch_anime_and_play.py @@ -0,0 +1,188 @@ +from xml.dom import NotFoundErr + +import requests +from bs4 import BeautifulSoup, NavigableString +from fake_useragent import UserAgent + +BASE_URL = "https://ww1.gogoanime2.org" + + +def search_scraper(anime_name: str) -> list: + + """[summary] + + Take an url and + return list of anime after scraping the site. + + >>> type(search_scraper("demon_slayer")) + + + Args: + anime_name (str): [Name of anime] + + Raises: + e: [Raises exception on failure] + + Returns: + [list]: [List of animes] + """ + + # concat the name to form the search url. + search_url = f"{BASE_URL}/search/{anime_name}" + + response = requests.get( + search_url, headers={"UserAgent": UserAgent().chrome} + ) # request the url. + + # Is the response ok? + response.raise_for_status() + + # parse with soup. + soup = BeautifulSoup(response.text, "html.parser") + + # get list of anime + anime_ul = soup.find("ul", {"class": "items"}) + anime_li = anime_ul.children + + # for each anime, insert to list. the name and url. + anime_list = [] + for anime in anime_li: + if not isinstance(anime, NavigableString): + try: + anime_url, anime_title = ( + anime.find("a")["href"], + anime.find("a")["title"], + ) + anime_list.append( + { + "title": anime_title, + "url": anime_url, + } + ) + except (NotFoundErr, KeyError): + pass + + return anime_list + + +def search_anime_episode_list(episode_endpoint: str) -> list: + + """[summary] + + Take an url and + return list of episodes after scraping the site + for an url. + + >>> type(search_anime_episode_list("/anime/kimetsu-no-yaiba")) + + + Args: + episode_endpoint (str): [Endpoint of episode] + + Raises: + e: [description] + + Returns: + [list]: [List of episodes] + """ + + request_url = f"{BASE_URL}{episode_endpoint}" + + response = requests.get(url=request_url, headers={"UserAgent": UserAgent().chrome}) + response.raise_for_status() + + soup = BeautifulSoup(response.text, "html.parser") + + # With this id. get the episode list. + episode_page_ul = soup.find("ul", {"id": "episode_related"}) + episode_page_li = episode_page_ul.children + + episode_list = [] + for episode in episode_page_li: + try: + if not isinstance(episode, NavigableString): + episode_list.append( + { + "title": episode.find("div", {"class": "name"}).text.replace( + " ", "" + ), + "url": episode.find("a")["href"], + } + ) + except (KeyError, NotFoundErr): + pass + + return episode_list + + +def get_anime_episode(episode_endpoint: str) -> list: + + """[summary] + + Get click url and download url from episode url + + >>> type(get_anime_episode("/watch/kimetsu-no-yaiba/1")) + + + Args: + episode_endpoint (str): [Endpoint of episode] + + Raises: + e: [description] + + Returns: + [list]: [List of download and watch url] + """ + + episode_page_url = f"{BASE_URL}{episode_endpoint}" + + response = requests.get( + url=episode_page_url, headers={"User-Agent": UserAgent().chrome} + ) + response.raise_for_status() + + soup = BeautifulSoup(response.text, "html.parser") + + try: + episode_url = soup.find("iframe", {"id": "playerframe"})["src"] + download_url = episode_url.replace("/embed/", "/playlist/") + ".m3u8" + except (KeyError, NotFoundErr) as e: + raise e + + return [f"{BASE_URL}{episode_url}", f"{BASE_URL}{download_url}"] + + +if __name__ == "__main__": + + anime_name = input("Enter anime name: ").strip() + anime_list = search_scraper(anime_name) + print("\n") + + if len(anime_list) == 0: + print("No anime found with this name") + else: + + print(f"Found {len(anime_list)} results: ") + for (i, anime) in enumerate(anime_list): + anime_title = anime["title"] + print(f"{i+1}. {anime_title}") + + anime_choice = int(input("\nPlease choose from the following list: ").strip()) + chosen_anime = anime_list[anime_choice - 1] + print(f"You chose {chosen_anime['title']}. Searching for episodes...") + + episode_list = search_anime_episode_list(chosen_anime["url"]) + if len(episode_list) == 0: + print("No episode found for this anime") + else: + print(f"Found {len(episode_list)} results: ") + for (i, episode) in enumerate(episode_list): + print(f"{i+1}. {episode['title']}") + + episode_choice = int(input("\nChoose an episode by serial no: ").strip()) + chosen_episode = episode_list[episode_choice - 1] + print(f"You chose {chosen_episode['title']}. Searching...") + + episode_url, download_url = get_anime_episode(chosen_episode["url"]) + print(f"\nTo watch, ctrl+click on {episode_url}.") + print(f"To download, ctrl+click on {download_url}.") From 54f765bdd0331f4b9381de8c879218ace1313be9 Mon Sep 17 00:00:00 2001 From: Calvin McCarter Date: Wed, 2 Feb 2022 15:05:05 -0500 Subject: [PATCH 243/726] Extend power iteration to handle complex Hermitian input matrices (#5925) * works python3 -m unittest discover --start-directory src --pattern "power*.py" --t . -v * cleanup * revert switch to unittest * fix flake8 --- linear_algebra/src/power_iteration.py | 64 ++++++++++++++++++--------- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/linear_algebra/src/power_iteration.py b/linear_algebra/src/power_iteration.py index 2cf22838e..4c6525b6e 100644 --- a/linear_algebra/src/power_iteration.py +++ b/linear_algebra/src/power_iteration.py @@ -9,10 +9,10 @@ def power_iteration( ) -> tuple[float, np.ndarray]: """ Power Iteration. - Find the largest eignevalue and corresponding eigenvector + Find the largest eigenvalue and corresponding eigenvector of matrix input_matrix given a random vector in the same space. Will work so long as vector has component of largest eigenvector. - input_matrix must be symmetric. + input_matrix must be either real or Hermitian. Input input_matrix: input matrix whose largest eigenvalue we will find. @@ -41,6 +41,12 @@ def power_iteration( assert np.shape(input_matrix)[0] == np.shape(input_matrix)[1] # Ensure proper dimensionality. assert np.shape(input_matrix)[0] == np.shape(vector)[0] + # Ensure inputs are either both complex or both real + assert np.iscomplexobj(input_matrix) == np.iscomplexobj(vector) + is_complex = np.iscomplexobj(input_matrix) + if is_complex: + # Ensure complex input_matrix is Hermitian + assert np.array_equal(input_matrix, input_matrix.conj().T) # Set convergence to False. Will define convergence when we exceed max_iterations # or when we have small changes from one iteration to next. @@ -57,7 +63,8 @@ def power_iteration( vector = w / np.linalg.norm(w) # Find rayleigh quotient # (faster than usual b/c we know vector is normalized already) - lamda = np.dot(vector.T, np.dot(input_matrix, vector)) + vectorH = vector.conj().T if is_complex else vector.T + lamda = np.dot(vectorH, np.dot(input_matrix, vector)) # Check convergence. error = np.abs(lamda - lamda_previous) / lamda @@ -68,6 +75,9 @@ def power_iteration( lamda_previous = lamda + if is_complex: + lamda = np.real(lamda) + return lamda, vector @@ -75,26 +85,40 @@ def test_power_iteration() -> None: """ >>> test_power_iteration() # self running tests """ - # Our implementation. - input_matrix = np.array([[41, 4, 20], [4, 26, 30], [20, 30, 50]]) - vector = np.array([41, 4, 20]) - eigen_value, eigen_vector = power_iteration(input_matrix, vector) + real_input_matrix = np.array([[41, 4, 20], [4, 26, 30], [20, 30, 50]]) + real_vector = np.array([41, 4, 20]) + complex_input_matrix = real_input_matrix.astype(np.complex128) + imag_matrix = np.triu(1j * complex_input_matrix, 1) + complex_input_matrix += imag_matrix + complex_input_matrix += -1 * imag_matrix.T + complex_vector = np.array([41, 4, 20]).astype(np.complex128) - # Numpy implementation. + for problem_type in ["real", "complex"]: + if problem_type == "real": + input_matrix = real_input_matrix + vector = real_vector + elif problem_type == "complex": + input_matrix = complex_input_matrix + vector = complex_vector - # Get eigen values and eigen vectors using built in numpy - # eigh (eigh used for symmetric or hermetian matrices). - eigen_values, eigen_vectors = np.linalg.eigh(input_matrix) - # Last eigen value is the maximum one. - eigen_value_max = eigen_values[-1] - # Last column in this matrix is eigen vector corresponding to largest eigen value. - eigen_vector_max = eigen_vectors[:, -1] + # Our implementation. + eigen_value, eigen_vector = power_iteration(input_matrix, vector) - # Check our implementation and numpy gives close answers. - assert np.abs(eigen_value - eigen_value_max) <= 1e-6 - # Take absolute values element wise of each eigenvector. - # as they are only unique to a minus sign. - assert np.linalg.norm(np.abs(eigen_vector) - np.abs(eigen_vector_max)) <= 1e-6 + # Numpy implementation. + + # Get eigenvalues and eigenvectors using built-in numpy + # eigh (eigh used for symmetric or hermetian matrices). + eigen_values, eigen_vectors = np.linalg.eigh(input_matrix) + # Last eigenvalue is the maximum one. + eigen_value_max = eigen_values[-1] + # Last column in this matrix is eigenvector corresponding to largest eigenvalue. + eigen_vector_max = eigen_vectors[:, -1] + + # Check our implementation and numpy gives close answers. + assert np.abs(eigen_value - eigen_value_max) <= 1e-6 + # Take absolute values element wise of each eigenvector. + # as they are only unique to a minus sign. + assert np.linalg.norm(np.abs(eigen_vector) - np.abs(eigen_vector_max)) <= 1e-6 if __name__ == "__main__": From f707f6d689ed40f51e5ceb8f0554e26e1e9fd507 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sun, 13 Feb 2022 06:57:44 +0100 Subject: [PATCH 244/726] Upgrade to Python 3.10 (#5992) * Upgrade to Python 3.10 * Upgrade to Python 3.10 * mypy || true * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .github/workflows/build.yml | 4 ++-- .github/workflows/pre-commit.yml | 2 +- DIRECTORY.md | 2 ++ requirements.txt | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4f270ea55..aabfacbfc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-python@v2 with: - python-version: "3.9" + python-version: "3.10" - uses: actions/cache@v2 with: path: ~/.cache/pip @@ -23,7 +23,7 @@ jobs: python -m pip install mypy pytest-cov -r requirements.txt - run: | mkdir -p .mypy_cache - mypy --ignore-missing-imports --install-types --non-interactive . + mypy --ignore-missing-imports --install-types --non-interactive . || true - name: Run tests run: pytest --doctest-modules --ignore=project_euler/ --ignore=scripts/validate_solutions.py --cov-report=term-missing:skip-covered --cov=. . - if: ${{ success() }} diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 19196098b..de73c96ad 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -15,7 +15,7 @@ jobs: key: ${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} - uses: actions/setup-python@v2 with: - python-version: 3.9 + python-version: "3.10" - uses: psf/black@21.4b0 - name: Install pre-commit run: | diff --git a/DIRECTORY.md b/DIRECTORY.md index b5ddb9fcb..e95785b25 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -1014,9 +1014,11 @@ * [Daily Horoscope](https://github.com/TheAlgorithms/Python/blob/master/web_programming/daily_horoscope.py) * [Download Images From Google Query](https://github.com/TheAlgorithms/Python/blob/master/web_programming/download_images_from_google_query.py) * [Emails From Url](https://github.com/TheAlgorithms/Python/blob/master/web_programming/emails_from_url.py) + * [Fetch Anime And Play](https://github.com/TheAlgorithms/Python/blob/master/web_programming/fetch_anime_and_play.py) * [Fetch Bbc News](https://github.com/TheAlgorithms/Python/blob/master/web_programming/fetch_bbc_news.py) * [Fetch Github Info](https://github.com/TheAlgorithms/Python/blob/master/web_programming/fetch_github_info.py) * [Fetch Jobs](https://github.com/TheAlgorithms/Python/blob/master/web_programming/fetch_jobs.py) + * [Fetch Well Rx Price](https://github.com/TheAlgorithms/Python/blob/master/web_programming/fetch_well_rx_price.py) * [Get Imdb Top 250 Movies Csv](https://github.com/TheAlgorithms/Python/blob/master/web_programming/get_imdb_top_250_movies_csv.py) * [Get Imdbtop](https://github.com/TheAlgorithms/Python/blob/master/web_programming/get_imdbtop.py) * [Get Top Hn Posts](https://github.com/TheAlgorithms/Python/blob/master/web_programming/get_top_hn_posts.py) diff --git a/requirements.txt b/requirements.txt index 9a26dcc21..294494acf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ beautifulsoup4 fake_useragent -keras<2.7.0 +keras lxml matplotlib numpy From 885580b3a152d02ad72ff433c2aefb6d604ef3c8 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sun, 13 Feb 2022 11:01:58 +0100 Subject: [PATCH 245/726] pyupgrade --py310-plus and run mypy in precommit, not build (#5996) * pyupgrade --py310-plus and run mypy in precommit, not build * pyupgrade --py310-plus web_programming/fetch_well_rx_price.py * pyupgrade --py310-plus web_programming/fetch_well_rx_price.py * Fix arithmetic_analysis/in_static_equilibrium.py * Fix arithmetic_analysis/in_static_equilibrium.py --- .github/workflows/build.yml | 5 +---- .pre-commit-config.yaml | 2 +- arithmetic_analysis/in_static_equilibrium.py | 4 ++-- web_programming/fetch_well_rx_price.py | 5 ++--- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index aabfacbfc..403ec44c8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,10 +20,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip setuptools six wheel - python -m pip install mypy pytest-cov -r requirements.txt - - run: | - mkdir -p .mypy_cache - mypy --ignore-missing-imports --install-types --non-interactive . || true + python -m pip install pytest-cov -r requirements.txt - name: Run tests run: pytest --doctest-modules --ignore=project_euler/ --ignore=scripts/validate_solutions.py --cov-report=term-missing:skip-covered --cov=. . - if: ${{ success() }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 33069a807..ab74d28e1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -30,7 +30,7 @@ repos: hooks: - id: pyupgrade args: - - --py39-plus + - --py310-plus - repo: https://gitlab.com/pycqa/flake8 rev: 3.9.2 diff --git a/arithmetic_analysis/in_static_equilibrium.py b/arithmetic_analysis/in_static_equilibrium.py index 6fe84b454..2ac3e7213 100644 --- a/arithmetic_analysis/in_static_equilibrium.py +++ b/arithmetic_analysis/in_static_equilibrium.py @@ -13,9 +13,9 @@ def polar_force( Resolves force along rectangular components. (force, angle) => (force_x, force_y) >>> polar_force(10, 45) - [7.0710678118654755, 7.071067811865475] + [7.071067811865477, 7.0710678118654755] >>> polar_force(10, 3.14, radian_mode=True) - [-9.999987317275394, 0.01592652916486828] + [-9.999987317275396, 0.01592652916486828] """ if radian_mode: return [magnitude * cos(angle), magnitude * sin(angle)] diff --git a/web_programming/fetch_well_rx_price.py b/web_programming/fetch_well_rx_price.py index 58dbe5993..5174f39f9 100644 --- a/web_programming/fetch_well_rx_price.py +++ b/web_programming/fetch_well_rx_price.py @@ -5,7 +5,6 @@ after providing the drug name and zipcode. """ -from typing import Union from urllib.error import HTTPError from bs4 import BeautifulSoup @@ -14,7 +13,7 @@ from requests import exceptions, get BASE_URL = "https://www.wellrx.com/prescriptions/{0}/{1}/?freshSearch=true" -def fetch_pharmacy_and_price_list(drug_name: str, zip_code: str) -> Union[list, None]: +def fetch_pharmacy_and_price_list(drug_name: str, zip_code: str) -> list | None: """[summary] This function will take input of drug name and zipcode, @@ -85,7 +84,7 @@ if __name__ == "__main__": drug_name = input("Enter drug name: ").strip() zip_code = input("Enter zip code: ").strip() - pharmacy_price_list: Union[list, None] = fetch_pharmacy_and_price_list( + pharmacy_price_list: list | None = fetch_pharmacy_and_price_list( drug_name, zip_code ) From 637cf10555adf7bffdc6aeeef587c4145c8a27a7 Mon Sep 17 00:00:00 2001 From: zer0-x <65136727+zer0-x@users.noreply.github.com> Date: Sun, 13 Feb 2022 20:09:09 +0300 Subject: [PATCH 246/726] Add points are collinear in 3d algorithm to /maths (#5983) * Add points are collinear in 3d algorithm to /maths * Apply suggestions from code review in points_are_collinear_3d.py Thanks to cclauss. Co-authored-by: Christian Clauss * Rename some variables to be more self-documenting. * Update points_are_collinear_3d.py Co-authored-by: Christian Clauss --- maths/points_are_collinear_3d.py | 126 +++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 maths/points_are_collinear_3d.py diff --git a/maths/points_are_collinear_3d.py b/maths/points_are_collinear_3d.py new file mode 100644 index 000000000..3bc0b3b9e --- /dev/null +++ b/maths/points_are_collinear_3d.py @@ -0,0 +1,126 @@ +""" +Check if three points are collinear in 3D. + +In short, the idea is that we are able to create a triangle using three points, +and the area of that triangle can determine if the three points are collinear or not. + + +First, we create two vectors with the same initial point from the three points, +then we will calculate the cross-product of them. + +The length of the cross vector is numerically equal to the area of a parallelogram. + +Finally, the area of the triangle is equal to half of the area of the parallelogram. + +Since we are only differentiating between zero and anything else, +we can get rid of the square root when calculating the length of the vector, +and also the division by two at the end. + +From a second perspective, if the two vectors are parallel and overlapping, +we can't get a nonzero perpendicular vector, +since there will be an infinite number of orthogonal vectors. + +To simplify the solution we will not calculate the length, +but we will decide directly from the vector whether it is equal to (0, 0, 0) or not. + + +Read More: + https://math.stackexchange.com/a/1951650 +""" + +Vector3d = tuple[float, float, float] +Point3d = tuple[float, float, float] + + +def create_vector(end_point1: Point3d, end_point2: Point3d) -> Vector3d: + """ + Pass two points to get the vector from them in the form (x, y, z). + + >>> create_vector((0, 0, 0), (1, 1, 1)) + (1, 1, 1) + >>> create_vector((45, 70, 24), (47, 32, 1)) + (2, -38, -23) + >>> create_vector((-14, -1, -8), (-7, 6, 4)) + (7, 7, 12) + """ + x = end_point2[0] - end_point1[0] + y = end_point2[1] - end_point1[1] + z = end_point2[2] - end_point1[2] + return (x, y, z) + + +def get_3d_vectors_cross(ab: Vector3d, ac: Vector3d) -> Vector3d: + """ + Get the cross of the two vectors AB and AC. + + I used determinant of 2x2 to get the determinant of the 3x3 matrix in the process. + + Read More: + https://en.wikipedia.org/wiki/Cross_product + https://en.wikipedia.org/wiki/Determinant + + >>> get_3d_vectors_cross((3, 4, 7), (4, 9, 2)) + (-55, 22, 11) + >>> get_3d_vectors_cross((1, 1, 1), (1, 1, 1)) + (0, 0, 0) + >>> get_3d_vectors_cross((-4, 3, 0), (3, -9, -12)) + (-36, -48, 27) + >>> get_3d_vectors_cross((17.67, 4.7, 6.78), (-9.5, 4.78, -19.33)) + (-123.2594, 277.15110000000004, 129.11260000000001) + """ + x = ab[1] * ac[2] - ab[2] * ac[1] # *i + y = (ab[0] * ac[2] - ab[2] * ac[0]) * -1 # *j + z = ab[0] * ac[1] - ab[1] * ac[0] # *k + return (x, y, z) + + +def is_zero_vector(vector: Vector3d, accuracy: int) -> bool: + """ + Check if vector is equal to (0, 0, 0) of not. + + Sine the algorithm is very accurate, we will never get a zero vector, + so we need to round the vector axis, + because we want a result that is either True or False. + In other applications, we can return a float that represents the collinearity ratio. + + >>> is_zero_vector((0, 0, 0), accuracy=10) + True + >>> is_zero_vector((15, 74, 32), accuracy=10) + False + >>> is_zero_vector((-15, -74, -32), accuracy=10) + False + """ + return tuple(round(x, accuracy) for x in vector) == (0, 0, 0) + + +def are_collinear(a: Point3d, b: Point3d, c: Point3d, accuracy: int = 10) -> bool: + """ + Check if three points are collinear or not. + + 1- Create tow vectors AB and AC. + 2- Get the cross vector of the tow vectors. + 3- Calcolate the length of the cross vector. + 4- If the length is zero then the points are collinear, else they are not. + + The use of the accuracy parameter is explained in is_zero_vector docstring. + + >>> are_collinear((4.802293498137402, 3.536233125455244, 0), + ... (-2.186788107953106, -9.24561398001649, 7.141509524846482), + ... (1.530169574640268, -2.447927606600034, 3.343487096469054)) + True + >>> are_collinear((-6, -2, 6), + ... (6.200213806439997, -4.930157614926678, -4.482371908289856), + ... (-4.085171149525941, -2.459889509029438, 4.354787180795383)) + True + >>> are_collinear((2.399001826862445, -2.452009976680793, 4.464656666157666), + ... (-3.682816335934376, 5.753788986533145, 9.490993909044244), + ... (1.962903518985307, 3.741415730125627, 7)) + False + >>> are_collinear((1.875375340689544, -7.268426006071538, 7.358196269835993), + ... (-3.546599383667157, -4.630005261513976, 3.208784032924246), + ... (-2.564606140206386, 3.937845170672183, 7)) + False + """ + ab = create_vector(a, b) + ac = create_vector(a, c) + return is_zero_vector(get_3d_vectors_cross(ab, ac), accuracy) From 7a9b3c7292cbd71fdc7723f449b9bbcbefbf9747 Mon Sep 17 00:00:00 2001 From: Lukas Date: Sun, 13 Feb 2022 12:20:19 -0500 Subject: [PATCH 247/726] Added average absolute deviation (#5951) * Added average absolute deviation * Formats program with black * reruns updated pre commit * Update average_absolute_deviation.py Co-authored-by: Christian Clauss --- DIRECTORY.md | 1 + maths/average_absolute_deviation.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 maths/average_absolute_deviation.py diff --git a/DIRECTORY.md b/DIRECTORY.md index e95785b25..eeea22e47 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -454,6 +454,7 @@ * [Area](https://github.com/TheAlgorithms/Python/blob/master/maths/area.py) * [Area Under Curve](https://github.com/TheAlgorithms/Python/blob/master/maths/area_under_curve.py) * [Armstrong Numbers](https://github.com/TheAlgorithms/Python/blob/master/maths/armstrong_numbers.py) + * [Average Absolute Deviation](https://github.com/TheAlgorithms/Python/blob/master/maths/average_absolute_deviation.py) * [Average Mean](https://github.com/TheAlgorithms/Python/blob/master/maths/average_mean.py) * [Average Median](https://github.com/TheAlgorithms/Python/blob/master/maths/average_median.py) * [Average Mode](https://github.com/TheAlgorithms/Python/blob/master/maths/average_mode.py) diff --git a/maths/average_absolute_deviation.py b/maths/average_absolute_deviation.py new file mode 100644 index 000000000..193d94a2f --- /dev/null +++ b/maths/average_absolute_deviation.py @@ -0,0 +1,29 @@ +def average_absolute_deviation(nums: list[int]) -> float: + """ + Return the average absolute deviation of a list of numbers. + Wiki: https://en.wikipedia.org/wiki/Average_absolute_deviation + + >>> average_absolute_deviation([0]) + 0.0 + >>> average_absolute_deviation([4, 1, 3, 2]) + 1.0 + >>> average_absolute_deviation([2, 70, 6, 50, 20, 8, 4, 0]) + 20.0 + >>> average_absolute_deviation([-20, 0, 30, 15]) + 16.25 + >>> average_absolute_deviation([]) + Traceback (most recent call last): + ... + ValueError: List is empty + """ + if not nums: # Makes sure that the list is not empty + raise ValueError("List is empty") + + average = sum(nums) / len(nums) # Calculate the average + return sum(abs(x - average) for x in nums) / len(nums) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 37200a4b3b262dd9aa690c4b6514ead0944b3778 Mon Sep 17 00:00:00 2001 From: Anirudh Lakhotia Date: Wed, 16 Mar 2022 21:10:48 +0530 Subject: [PATCH 248/726] LICENSE: Year change (#5920) * :memo: Updated year Fixes: #5916 * Update LICENSE.md Co-authored-by: John Law --- LICENSE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.md b/LICENSE.md index c3c2857cd..2897d02e2 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2016-2021 The Algorithms +Copyright (c) 2016-2022 TheAlgorithms and contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 4064bf45f54c1359b686cd7f231b25ee5ae2d3cc Mon Sep 17 00:00:00 2001 From: Harshit Agarwal <43147421+9harshit@users.noreply.github.com> Date: Wed, 30 Mar 2022 00:10:56 -0300 Subject: [PATCH 249/726] fix(pre-commit): update `black` version (#6075) black==22.1.0 is breaking the hook. Updating it to 22.3.0 fixes all the issue Refer: https://github.com/python-poetry/poetry/issues/5375 --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ab74d28e1..33da02fb7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: requirements-txt-fixer - repo: https://github.com/psf/black - rev: 22.1.0 + rev: 22.3.0 hooks: - id: black From 1f1daaf1c75adbe43126e53ef1eba718ecb67029 Mon Sep 17 00:00:00 2001 From: Harshit Agarwal <43147421+9harshit@users.noreply.github.com> Date: Mon, 4 Apr 2022 00:36:32 -0300 Subject: [PATCH 250/726] feat: add strings/ngram algorithm (#6074) * feat: added ngram algorithm * fix(test): use `math.isclose` to match floating point numbers approximately Co-authored-by: Christian Clauss Co-authored-by: Dhruv Manilawala --- arithmetic_analysis/in_static_equilibrium.py | 14 +++++++++--- strings/ngram.py | 23 ++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 strings/ngram.py diff --git a/arithmetic_analysis/in_static_equilibrium.py b/arithmetic_analysis/in_static_equilibrium.py index 2ac3e7213..ed0d1eb98 100644 --- a/arithmetic_analysis/in_static_equilibrium.py +++ b/arithmetic_analysis/in_static_equilibrium.py @@ -12,8 +12,12 @@ def polar_force( """ Resolves force along rectangular components. (force, angle) => (force_x, force_y) - >>> polar_force(10, 45) - [7.071067811865477, 7.0710678118654755] + >>> import math + >>> force = polar_force(10, 45) + >>> math.isclose(force[0], 7.071067811865477) + True + >>> math.isclose(force[1], 7.0710678118654755) + True >>> polar_force(10, 3.14, radian_mode=True) [-9.999987317275396, 0.01592652916486828] """ @@ -50,7 +54,11 @@ def in_static_equilibrium( if __name__ == "__main__": # Test to check if it works forces = array( - [polar_force(718.4, 180 - 30), polar_force(879.54, 45), polar_force(100, -90)] + [ + polar_force(718.4, 180 - 30), + polar_force(879.54, 45), + polar_force(100, -90), + ] ) location = array([[0, 0], [0, 0], [0, 0]]) diff --git a/strings/ngram.py b/strings/ngram.py new file mode 100644 index 000000000..0b13e34a4 --- /dev/null +++ b/strings/ngram.py @@ -0,0 +1,23 @@ +""" +https://en.wikipedia.org/wiki/N-gram +""" + + +def create_ngram(sentence: str, ngram_size: int) -> list[str]: + """ + Create ngrams from a sentence + + >>> create_ngram("I am a sentence", 2) + ['I ', ' a', 'am', 'm ', ' a', 'a ', ' s', 'se', 'en', 'nt', 'te', 'en', 'nc', 'ce'] + >>> create_ngram("I am an NLPer", 2) + ['I ', ' a', 'am', 'm ', ' a', 'an', 'n ', ' N', 'NL', 'LP', 'Pe', 'er'] + >>> create_ngram("This is short", 50) + [] + """ + return [sentence[i : i + ngram_size] for i in range(len(sentence) - ngram_size + 1)] + + +if __name__ == "__main__": + from doctest import testmod + + testmod() From 1d3d18bcd28cd4eb0ffb7b1db213215f2f92c78a Mon Sep 17 00:00:00 2001 From: Aviv Faraj <73610201+avivfaraj@users.noreply.github.com> Date: Mon, 4 Apr 2022 16:44:29 +0300 Subject: [PATCH 251/726] horizontal motion code physics (#4710) * Add files via upload * Changed print to f-string Also printed out results in a math notation * Add files via upload * Fixes: #4710 provided return type * File exists in another pull request * imported radians from math * Updated file according to pre-commit test * Updated file * Updated gamma * Deleted duplicate file * removed pi * reversed tests * Fixed angle condition * Modified prints to f-string * Update horizontal_projectile_motion.py * Update horizontal_projectile_motion.py * Fixes #4710 added exceptions and tests * Added float tests * Fixed type annotations * Fixed last annotation * Fixed annotations * fixed format * Revert "fixed format" This reverts commit 5b0249ac0a0f9c36c3cfbab8423eb72925a73ffb. Undo changes @wq * Revert "Fixed annotations" This reverts commit c37bb9540834cb77e37822eb376a5896cda34778. * Revert "Fixed last annotation" This reverts commit e3678fdeadd23f1bfca27015ab524efa184f6c79. * Revert "Fixed type annotations" This reverts commit 3f2b238c34cd926b335d1f6f750e009f08e8f270. * Revert to 4e2fcaf6fb * Fixing errors found during pre-commit --- physics/horizontal_projectile_motion.py | 152 ++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 physics/horizontal_projectile_motion.py diff --git a/physics/horizontal_projectile_motion.py b/physics/horizontal_projectile_motion.py new file mode 100644 index 000000000..0f27b0617 --- /dev/null +++ b/physics/horizontal_projectile_motion.py @@ -0,0 +1,152 @@ +""" +Horizontal Projectile Motion problem in physics. +This algorithm solves a specific problem in which +the motion starts from the ground as can be seen below: + (v = 0) + ** + * * + * * + * * + * * + * * +GROUND GROUND +For more info: https://en.wikipedia.org/wiki/Projectile_motion +""" + +# Importing packages +from math import radians as angle_to_radians +from math import sin + +# Acceleration Constant on hearth (unit m/s^2) +g = 9.80665 + + +def check_args(init_velocity: float, angle: float) -> None: + """ + Check that the arguments are valid + """ + + # Ensure valid instance + if not isinstance(init_velocity, (int, float)): + raise TypeError("Invalid velocity. Should be a positive number.") + + if not isinstance(angle, (int, float)): + raise TypeError("Invalid angle. Range is 1-90 degrees.") + + # Ensure valid angle + if angle > 90 or angle < 1: + raise ValueError("Invalid angle. Range is 1-90 degrees.") + + # Ensure valid velocity + if init_velocity < 0: + raise ValueError("Invalid velocity. Should be a positive number.") + + +def horizontal_distance(init_velocity: float, angle: float) -> float: + """ + Returns the horizontal distance that the object cover + Formula: + v_0^2 * sin(2 * alpha) + --------------------- + g + v_0 - initial velocity + alpha - angle + >>> horizontal_distance(30, 45) + 91.77 + >>> horizontal_distance(100, 78) + 414.76 + >>> horizontal_distance(-1, 20) + Traceback (most recent call last): + ... + ValueError: Invalid velocity. Should be a positive number. + >>> horizontal_distance(30, -20) + Traceback (most recent call last): + ... + ValueError: Invalid angle. Range is 1-90 degrees. + """ + check_args(init_velocity, angle) + radians = angle_to_radians(2 * angle) + return round(init_velocity**2 * sin(radians) / g, 2) + + +def max_height(init_velocity: float, angle: float) -> float: + """ + Returns the maximum height that the object reach + Formula: + v_0^2 * sin^2(alpha) + -------------------- + 2g + v_0 - initial velocity + alpha - angle + >>> max_height(30, 45) + 22.94 + >>> max_height(100, 78) + 487.82 + >>> max_height("a", 20) + Traceback (most recent call last): + ... + TypeError: Invalid velocity. Should be a positive number. + >>> horizontal_distance(30, "b") + Traceback (most recent call last): + ... + TypeError: Invalid angle. Range is 1-90 degrees. + """ + check_args(init_velocity, angle) + radians = angle_to_radians(angle) + return round(init_velocity**2 * sin(radians) ** 2 / (2 * g), 2) + + +def total_time(init_velocity: float, angle: float) -> float: + """ + Returns total time of the motion + Formula: + 2 * v_0 * sin(alpha) + -------------------- + g + v_0 - initial velocity + alpha - angle + >>> total_time(30, 45) + 4.33 + >>> total_time(100, 78) + 19.95 + >>> total_time(-10, 40) + Traceback (most recent call last): + ... + ValueError: Invalid velocity. Should be a positive number. + >>> total_time(30, "b") + Traceback (most recent call last): + ... + TypeError: Invalid angle. Range is 1-90 degrees. + """ + check_args(init_velocity, angle) + radians = angle_to_radians(angle) + return round(2 * init_velocity * sin(radians) / g, 2) + + +def test_motion() -> None: + """ + >>> test_motion() + """ + v0, angle = 25, 20 + assert horizontal_distance(v0, angle) == 40.97 + assert max_height(v0, angle) == 3.73 + assert total_time(v0, angle) == 1.74 + + +if __name__ == "__main__": + from doctest import testmod + + testmod() + + # Get input from user + init_vel = float(input("Initial Velocity: ").strip()) + + # Get input from user + angle = float(input("angle: ").strip()) + + # Print results + print() + print("Results: ") + print(f"Horizontal Distance: {str(horizontal_distance(init_vel, angle))} [m]") + print(f"Maximum Height: {str(max_height(init_vel, angle))} [m]") + print(f"Total Time: {str(total_time(init_vel, angle))} [s]") From 1400cb86ff7c656087963db41844e0ca503ae6d5 Mon Sep 17 00:00:00 2001 From: "Paulo S. G. Ferraz" Date: Fri, 8 Apr 2022 14:40:45 -0300 Subject: [PATCH 252/726] Remove duplicate is_prime related functions (#5892) * Fixes (#5434) * Update ciphers.rabin_miller.py maths.miller_rabin.py * Fixing ERROR maths/miller_rabin.py - ModuleNotFoundError and changing project_euler's isPrime to is_prime function names * Update sol1.py * fix: try to change to list * fix pre-commit * fix capital letters * Update miller_rabin.py * Update rabin_miller.py Co-authored-by: John Law --- ciphers/rabin_miller.py | 6 +++--- maths/miller_rabin.py | 10 +++++----- project_euler/problem_003/sol1.py | 22 +++++++++++----------- project_euler/problem_007/sol2.py | 10 +++++----- project_euler/problem_007/sol3.py | 10 +++++----- project_euler/problem_058/sol1.py | 17 ++++++++--------- 6 files changed, 37 insertions(+), 38 deletions(-) diff --git a/ciphers/rabin_miller.py b/ciphers/rabin_miller.py index c42ad2f59..a9b834bfb 100644 --- a/ciphers/rabin_miller.py +++ b/ciphers/rabin_miller.py @@ -25,7 +25,7 @@ def rabinMiller(num: int) -> bool: return True -def isPrime(num: int) -> bool: +def is_prime_low_num(num: int) -> bool: if num < 2: return False @@ -213,11 +213,11 @@ def isPrime(num: int) -> bool: def generateLargePrime(keysize: int = 1024) -> int: while True: num = random.randrange(2 ** (keysize - 1), 2 ** (keysize)) - if isPrime(num): + if is_prime_low_num(num): return num if __name__ == "__main__": num = generateLargePrime() print(("Prime number:", num)) - print(("isPrime:", isPrime(num))) + print(("is_prime_low_num:", is_prime_low_num(num))) diff --git a/maths/miller_rabin.py b/maths/miller_rabin.py index 2b0944508..d35e54858 100644 --- a/maths/miller_rabin.py +++ b/maths/miller_rabin.py @@ -6,11 +6,11 @@ from .binary_exp_mod import bin_exp_mod # This is a probabilistic check to test primality, useful for big numbers! # if it's a prime, it will return true # if it's not a prime, the chance of it returning true is at most 1/4**prec -def is_prime(n, prec=1000): +def is_prime_big(n, prec=1000): """ - >>> from .prime_check import prime_check - >>> # all(is_prime(i) == prime_check(i) for i in range(1000)) # 3.45s - >>> all(is_prime(i) == prime_check(i) for i in range(256)) + >>> from maths.prime_check import prime_check + >>> # all(is_prime_big(i) == prime_check(i) for i in range(1000)) # 3.45s + >>> all(is_prime_big(i) == prime_check(i) for i in range(256)) True """ if n < 2: @@ -48,4 +48,4 @@ def is_prime(n, prec=1000): if __name__ == "__main__": n = abs(int(input("Enter bound : ").strip())) print("Here's the list of primes:") - print(", ".join(str(i) for i in range(n + 1) if is_prime(i))) + print(", ".join(str(i) for i in range(n + 1) if is_prime_big(i))) diff --git a/project_euler/problem_003/sol1.py b/project_euler/problem_003/sol1.py index 1f3299842..606a6945e 100644 --- a/project_euler/problem_003/sol1.py +++ b/project_euler/problem_003/sol1.py @@ -13,23 +13,23 @@ References: import math -def isprime(num: int) -> bool: +def is_prime(num: int) -> bool: """ Returns boolean representing primality of given number num. - >>> isprime(2) + >>> is_prime(2) True - >>> isprime(3) + >>> is_prime(3) True - >>> isprime(27) + >>> is_prime(27) False - >>> isprime(2999) + >>> is_prime(2999) True - >>> isprime(0) + >>> is_prime(0) Traceback (most recent call last): ... ValueError: Parameter num must be greater than or equal to two. - >>> isprime(1) + >>> is_prime(1) Traceback (most recent call last): ... ValueError: Parameter num must be greater than or equal to two. @@ -84,18 +84,18 @@ def solution(n: int = 600851475143) -> int: if n <= 0: raise ValueError("Parameter n must be greater than or equal to one.") max_number = 0 - if isprime(n): + if is_prime(n): return n while n % 2 == 0: n //= 2 - if isprime(n): + if is_prime(n): return n for i in range(3, int(math.sqrt(n)) + 1, 2): if n % i == 0: - if isprime(n // i): + if is_prime(n // i): max_number = n // i break - elif isprime(i): + elif is_prime(i): max_number = i return max_number diff --git a/project_euler/problem_007/sol2.py b/project_euler/problem_007/sol2.py index dfcad8c14..44d72e949 100644 --- a/project_euler/problem_007/sol2.py +++ b/project_euler/problem_007/sol2.py @@ -13,15 +13,15 @@ References: """ -def isprime(number: int) -> bool: +def is_prime(number: int) -> bool: """ Determines whether the given number is prime or not - >>> isprime(2) + >>> is_prime(2) True - >>> isprime(15) + >>> is_prime(15) False - >>> isprime(29) + >>> is_prime(29) True """ @@ -76,7 +76,7 @@ def solution(nth: int = 10001) -> int: primes: list[int] = [] num = 2 while len(primes) < nth: - if isprime(num): + if is_prime(num): primes.append(num) num += 1 else: diff --git a/project_euler/problem_007/sol3.py b/project_euler/problem_007/sol3.py index 7911fa3e9..daa719cef 100644 --- a/project_euler/problem_007/sol3.py +++ b/project_euler/problem_007/sol3.py @@ -15,15 +15,15 @@ import itertools import math -def prime_check(number: int) -> bool: +def is_prime(number: int) -> bool: """ Determines whether a given number is prime or not - >>> prime_check(2) + >>> is_prime(2) True - >>> prime_check(15) + >>> is_prime(15) False - >>> prime_check(29) + >>> is_prime(29) True """ @@ -39,7 +39,7 @@ def prime_generator(): num = 2 while True: - if prime_check(num): + if is_prime(num): yield num num += 1 diff --git a/project_euler/problem_058/sol1.py b/project_euler/problem_058/sol1.py index ed407edf7..c59b0dd71 100644 --- a/project_euler/problem_058/sol1.py +++ b/project_euler/problem_058/sol1.py @@ -36,14 +36,14 @@ count of current primes. from math import isqrt -def isprime(number: int) -> int: +def is_prime(number: int) -> int: """ - returns whether the given number is prime or not - >>> isprime(1) + Returns whether the given number is prime or not + >>> is_prime(1) 0 - >>> isprime(17) + >>> is_prime(17) 1 - >>> isprime(10000) + >>> is_prime(10000) 0 """ if number == 1: @@ -60,7 +60,7 @@ def isprime(number: int) -> int: def solution(ratio: float = 0.1) -> int: """ - returns the side length of the square spiral of odd length greater + Returns the side length of the square spiral of odd length greater than 1 for which the ratio of primes along both diagonals first falls below the given ratio. >>> solution(.5) @@ -76,9 +76,8 @@ def solution(ratio: float = 0.1) -> int: while primes / (2 * j - 1) >= ratio: for i in range(j * j + j + 1, (j + 2) * (j + 2), j + 1): - primes = primes + isprime(i) - - j = j + 2 + primes += is_prime(i) + j += 2 return j From 10d0e4ecbf741f9acded245b5f47f77b8d672596 Mon Sep 17 00:00:00 2001 From: varopxndx <42877919+varopxndx@users.noreply.github.com> Date: Thu, 28 Apr 2022 12:05:21 -0500 Subject: [PATCH 253/726] docs: Fix quicksort & binary tree traversal doc (#4878) * Fix quicksort doc * add binary tree traversals doc * Add link to the reference * Fix job * Change url * Update binary_tree_traversals.md * Update normal_distribution_quick_sort.md * Update normal_distribution_quick_sort.md Co-authored-by: John Law --- .../binary_tree/binary_tree_traversals.md | 111 ++++++++++++++++++ sorts/normal_distribution_quick_sort.md | 45 ++----- 2 files changed, 124 insertions(+), 32 deletions(-) create mode 100644 data_structures/binary_tree/binary_tree_traversals.md diff --git a/data_structures/binary_tree/binary_tree_traversals.md b/data_structures/binary_tree/binary_tree_traversals.md new file mode 100644 index 000000000..ebe727b65 --- /dev/null +++ b/data_structures/binary_tree/binary_tree_traversals.md @@ -0,0 +1,111 @@ +# Binary Tree Traversal + +## Overview + +The combination of binary trees being data structures and traversal being an algorithm relates to classic problems, either directly or indirectly. + +> If you can grasp the traversal of binary trees, the traversal of other complicated trees will be easy for you. + +The following are some common ways to traverse trees. + +- Depth First Traversals (DFS): In-order, Pre-order, Post-order + +- Level Order Traversal or Breadth First or Traversal (BFS) + +There are applications for both DFS and BFS. + +Stack can be used to simplify the process of DFS traversal. Besides, since tree is a recursive data structure, recursion and stack are two key points for DFS. + +Graph for DFS: + +![binary-tree-traversal-dfs](https://tva1.sinaimg.cn/large/007S8ZIlly1ghluhzhynsg30dw0dw3yl.gif) + +The key point of BFS is how to determine whether the traversal of each level has been completed. The answer is to use a variable as a flag to represent the end of the traversal of current level. + +## Pre-order Traversal + +The traversal order of pre-order traversal is `root-left-right`. + +Algorithm Pre-order + +1. Visit the root node and push it into a stack. + +2. Pop a node from the stack, and push its right and left child node into the stack respectively. + +3. Repeat step 2. + +Conclusion: This problem involves the classic recursive data structure (i.e. a binary tree), and the algorithm above demonstrates how a simplified solution can be reached by using a stack. + +If you look at the bigger picture, you'll find that the process of traversal is as followed. `Visit the left subtrees respectively from top to bottom, and visit the right subtrees respectively from bottom to top`. If we are to implement it from this perspective, things will be somewhat different. For the `top to bottom` part we can simply use recursion, and for the `bottom to top` part we can turn to stack. + +## In-order Traversal + +The traversal order of in-order traversal is `left-root-right`. + +So the root node is not printed first. Things are getting a bit complicated here. + +Algorithm In-order + +1. Visit the root and push it into a stack. + +2. If there is a left child node, push it into the stack. Repeat this process until a leaf node reached. + + > At this point the root node and all the left nodes are in the stack. + +3. Start popping nodes from the stack. If a node has a right child node, push the child node into the stack. Repeat step 2. + +It's worth pointing out that the in-order traversal of a binary search tree (BST) is a sorted array, which is helpful for coming up simplified solutions for some problems. + +## Post-order Traversal + +The traversal order of post-order traversal is `left-right-root`. + +This one is a bit of a challenge. It deserves the `hard` tag of LeetCode. + +In this case, the root node is printed not as the first but the last one. A cunning way to do it is to: + +Record whether the current node has been visited. If 1) it's a leaf node or 2) both its left and right subtrees have been traversed, then it can be popped from the stack. + +As for `1) it's a leaf node`, you can easily tell whether a node is a leaf if both its left and right are `null`. + +As for `2) both its left and right subtrees have been traversed`, we only need a variable to record whether a node has been visited or not. In the worst case, we need to record the status for every single node and the space complexity is `O(n)`. But if you come to think about it, as we are using a stack and start printing the result from the leaf nodes, it makes sense that we only record the status for the current node popping from the stack, reducing the space complexity to `O(1)`. + +## Level Order Traversal + +The key point of level order traversal is how do we know whether the traversal of each level is done. The answer is that we use a variable as a flag representing the end of the traversal of the current level. + +![binary-tree-traversal-bfs](https://tva1.sinaimg.cn/large/007S8ZIlly1ghlui1tpoug30dw0dw3yl.gif) + +Algorithm Level-order + +1. Visit the root node, put it in a FIFO queue, put in the queue a special flag (we are using `null` here). + +2. Dequeue a node. + +3. If the node equals `null`, it means that all nodes of the current level have been visited. If the queue is empty, we do nothing. Or else we put in another `null`. + +4. If the node is not `null`, meaning the traversal of current level has not finished yet, we enqueue its left subtree and right subtree respectively. + +## Bi-color marking + +We know that there is a tri-color marking in garbage collection algorithm, which works as described below. + +- The white color represents "not visited". + +- The gray color represents "not all child nodes visited". + +- The black color represents "all child nodes visited". + +Enlightened by tri-color marking, a bi-color marking method can be invented to solve all three traversal problems with one solution. + +The core idea is as follow. + +- Use a color to mark whether a node has been visited or not. Nodes yet to be visited are marked as white and visited nodes are marked as gray. + +- If we are visiting a white node, turn it into gray, and push its right child node, itself, and it's left child node into the stack respectively. + +- If we are visiting a gray node, print it. + +Implementation of pre-order and post-order traversal algorithms can be easily done by changing the order of pushing the child nodes into the stack. + +Reference: [LeetCode](https://github.com/azl397985856/leetcode/blob/master/thinkings/binary-tree-traversal.en.md) diff --git a/sorts/normal_distribution_quick_sort.md b/sorts/normal_distribution_quick_sort.md index 2a9f77b3e..c073f2cbc 100644 --- a/sorts/normal_distribution_quick_sort.md +++ b/sorts/normal_distribution_quick_sort.md @@ -1,15 +1,12 @@ # Normal Distribution QuickSort +QuickSort Algorithm where the pivot element is chosen randomly between first and last elements of the array, and the array elements are taken from Standard Normal Distribution. -Algorithm implementing QuickSort Algorithm where the pivot element is chosen randomly between first and last elements of the array and the array elements are taken from a Standard Normal Distribution. -This is different from the ordinary quicksort in the sense, that it applies more to real life problems , where elements usually follow a normal distribution. Also the pivot is randomized to make it a more generic one. +## Array elements +The array elements are taken from a Standard Normal Distribution, having mean = 0 and standard deviation = 1. -## Array Elements - -The array elements are taken from a Standard Normal Distribution , having mean = 0 and standard deviation 1. - -#### The code +### The code ```python @@ -27,7 +24,7 @@ The array elements are taken from a Standard Normal Distribution , having mean = ------ -#### The Distribution of the Array elements. +#### The distribution of the array elements ```python >>> mu, sigma = 0, 1 # mean and standard deviation @@ -35,41 +32,25 @@ The array elements are taken from a Standard Normal Distribution , having mean = >>> count, bins, ignored = plt.hist(s, 30, normed=True) >>> plt.plot(bins , 1/(sigma * np.sqrt(2 * np.pi)) *np.exp( - (bins - mu)**2 / (2 * sigma**2) ),linewidth=2, color='r') >>> plt.show() - ``` +------ +![normal distribution large](https://upload.wikimedia.org/wikipedia/commons/thumb/2/25/The_Normal_Distribution.svg/1280px-The_Normal_Distribution.svg.png) ------ +------ +## Comparing the numbers of comparisons - - -![](https://www.mathsisfun.com/data/images/normal-distrubution-large.gif) - ---- - ---------------------- - --- - -## Plotting the function for Checking 'The Number of Comparisons' taking place between Normal Distribution QuickSort and Ordinary QuickSort +We can plot the function for Checking 'The Number of Comparisons' taking place between Normal Distribution QuickSort and Ordinary QuickSort: ```python ->>>import matplotlib.pyplot as plt +>>> import matplotlib.pyplot as plt - - # Normal Disrtibution QuickSort is red + # Normal Distribution QuickSort is red >>> plt.plot([1,2,4,16,32,64,128,256,512,1024,2048],[1,1,6,15,43,136,340,800,2156,6821,16325],linewidth=2, color='r') - #Ordinary QuickSort is green + # Ordinary QuickSort is green >>> plt.plot([1,2,4,16,32,64,128,256,512,1024,2048],[1,1,4,16,67,122,362,949,2131,5086,12866],linewidth=2, color='g') >>> plt.show() - ``` - - ----- - - ------------------- From a7e4b2326a74067404339b1147c1ff40568ee4c0 Mon Sep 17 00:00:00 2001 From: Manuel Di Lullo <39048927+manueldilullo@users.noreply.github.com> Date: Sun, 1 May 2022 11:45:08 +0200 Subject: [PATCH 254/726] Add prefix conversions for strings (#5453) * First commit for add_prefix_conversion * Class names in CamelCase, str.format() to f-string * Fixed following pre-commit guidelines * solved issues with mypy and enum.Enum * Rename add_prefix_conversion.py to prefix_conversions_string.py Co-authored-by: John Law --- conversions/prefix_conversions_string.py | 121 +++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 conversions/prefix_conversions_string.py diff --git a/conversions/prefix_conversions_string.py b/conversions/prefix_conversions_string.py new file mode 100644 index 000000000..3255eae6f --- /dev/null +++ b/conversions/prefix_conversions_string.py @@ -0,0 +1,121 @@ +""" +* Author: Manuel Di Lullo (https://github.com/manueldilullo) +* Description: Convert a number to use the correct SI or Binary unit prefix. + +Inspired by prefix_conversion.py file in this repository by lance-pyles + +URL: https://en.wikipedia.org/wiki/Metric_prefix#List_of_SI_prefixes +URL: https://en.wikipedia.org/wiki/Binary_prefix +""" + +from __future__ import annotations + +from enum import Enum, unique +from typing import Type, TypeVar + +# Create a generic variable that can be 'Enum', or any subclass. +T = TypeVar("T", bound="Enum") + + +@unique +class BinaryUnit(Enum): + yotta = 80 + zetta = 70 + exa = 60 + peta = 50 + tera = 40 + giga = 30 + mega = 20 + kilo = 10 + + +@unique +class SIUnit(Enum): + yotta = 24 + zetta = 21 + exa = 18 + peta = 15 + tera = 12 + giga = 9 + mega = 6 + kilo = 3 + hecto = 2 + deca = 1 + deci = -1 + centi = -2 + milli = -3 + micro = -6 + nano = -9 + pico = -12 + femto = -15 + atto = -18 + zepto = -21 + yocto = -24 + + @classmethod + def get_positive(cls: Type[T]) -> dict: + """ + Returns a dictionary with only the elements of this enum + that has a positive value + >>> from itertools import islice + >>> positive = SIUnit.get_positive() + >>> inc = iter(positive.items()) + >>> dict(islice(inc, len(positive) // 2)) + {'yotta': 24, 'zetta': 21, 'exa': 18, 'peta': 15, 'tera': 12} + >>> dict(inc) + {'giga': 9, 'mega': 6, 'kilo': 3, 'hecto': 2, 'deca': 1} + """ + return {unit.name: unit.value for unit in cls if unit.value > 0} + + @classmethod + def get_negative(cls: Type[T]) -> dict: + """ + Returns a dictionary with only the elements of this enum + that has a negative value + @example + >>> from itertools import islice + >>> negative = SIUnit.get_negative() + >>> inc = iter(negative.items()) + >>> dict(islice(inc, len(negative) // 2)) + {'deci': -1, 'centi': -2, 'milli': -3, 'micro': -6, 'nano': -9} + >>> dict(inc) + {'pico': -12, 'femto': -15, 'atto': -18, 'zepto': -21, 'yocto': -24} + """ + return {unit.name: unit.value for unit in cls if unit.value < 0} + + +def add_si_prefix(value: float) -> str: + """ + Function that converts a number to his version with SI prefix + @input value (an integer) + @example: + >>> add_si_prefix(10000) + '10.0 kilo' + """ + prefixes = SIUnit.get_positive() if value > 0 else SIUnit.get_negative() + for name_prefix, value_prefix in prefixes.items(): + numerical_part = value / (10 ** value_prefix) + if numerical_part > 1: + return f"{str(numerical_part)} {name_prefix}" + return str(value) + + +def add_binary_prefix(value: float) -> str: + """ + Function that converts a number to his version with Binary prefix + @input value (an integer) + @example: + >>> add_binary_prefix(65536) + '64.0 kilo' + """ + for prefix in BinaryUnit: + numerical_part = value / (2 ** prefix.value) + if numerical_part > 1: + return f"{str(numerical_part)} {prefix.name}" + return str(value) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From e1ec661d4e368ceabd50e7ef3714c85dbe139c02 Mon Sep 17 00:00:00 2001 From: Shuangchi He <34329208+Yulv-git@users.noreply.github.com> Date: Sun, 1 May 2022 18:44:23 +0800 Subject: [PATCH 255/726] Fix some typos (#6113) * Fix some typos. * Update volume.py Co-authored-by: John Law --- ciphers/shuffled_shift_cipher.py | 2 +- data_structures/stacks/dijkstras_two_stack_algorithm.py | 2 +- divide_and_conquer/inversions.py | 2 +- maths/volume.py | 4 ++-- strings/manacher.py | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ciphers/shuffled_shift_cipher.py b/ciphers/shuffled_shift_cipher.py index 3b84f97f6..714acd4b1 100644 --- a/ciphers/shuffled_shift_cipher.py +++ b/ciphers/shuffled_shift_cipher.py @@ -9,7 +9,7 @@ class ShuffledShiftCipher: This algorithm uses the Caesar Cipher algorithm but removes the option to use brute force to decrypt the message. - The passcode is a a random password from the selection buffer of + The passcode is a random password from the selection buffer of 1. uppercase letters of the English alphabet 2. lowercase letters of the English alphabet 3. digits from 0 to 9 diff --git a/data_structures/stacks/dijkstras_two_stack_algorithm.py b/data_structures/stacks/dijkstras_two_stack_algorithm.py index ba2ca92c7..976c9a53c 100644 --- a/data_structures/stacks/dijkstras_two_stack_algorithm.py +++ b/data_structures/stacks/dijkstras_two_stack_algorithm.py @@ -10,7 +10,7 @@ such as: (5 + ((4 * 2) * (2 + 3))) THESE ARE THE ALGORITHM'S RULES: RULE 1: Scan the expression from left to right. When an operand is encountered, - push it onto the the operand stack. + push it onto the operand stack. RULE 2: When an operator is encountered in the expression, push it onto the operator stack. diff --git a/divide_and_conquer/inversions.py b/divide_and_conquer/inversions.py index b47145602..e20d35dac 100644 --- a/divide_and_conquer/inversions.py +++ b/divide_and_conquer/inversions.py @@ -11,7 +11,7 @@ algorithm which runs in nlogn and the brute-force n^2 algorithm. def count_inversions_bf(arr): """ - Counts the number of inversions using a a naive brute-force algorithm + Counts the number of inversions using a naive brute-force algorithm Parameters ---------- arr: arr: array-like, the list containing the items for which the number diff --git a/maths/volume.py b/maths/volume.py index b11995bab..acaed65f4 100644 --- a/maths/volume.py +++ b/maths/volume.py @@ -38,8 +38,8 @@ def vol_spheres_intersect( Calculate the volume of the intersection of two spheres. The intersection is composed by two spherical caps and therefore its volume is the - sum of the volumes of the spherical caps. First it calculates the heights (h1, h2) - of the the spherical caps, then the two volumes and it returns the sum. + sum of the volumes of the spherical caps. First, it calculates the heights (h1, h2) + of the spherical caps, then the two volumes and it returns the sum. The height formulas are h1 = (radius_1 - radius_2 + centers_distance) * (radius_1 + radius_2 - centers_distance) diff --git a/strings/manacher.py b/strings/manacher.py index e6ea71cde..c58c7c19e 100644 --- a/strings/manacher.py +++ b/strings/manacher.py @@ -88,7 +88,7 @@ iv) a1 is corresponding equal character of a5 in palindrome with center a3 (reme now for a5 we will calculate the length of palindromic substring with center as a5 but can we use previously calculated information in some way? Yes, look the above string we know that a5 is inside the palindrome with center a3 and -previously we have have calculated that +previously we have calculated that a0==a2 (palindrome of center a1) a2==a4 (palindrome of center a3) a0==a6 (palindrome of center a3) From 7a394411b70bf7ca654e97f2d2663674ce1757c7 Mon Sep 17 00:00:00 2001 From: John Law Date: Sun, 1 May 2022 21:52:40 +0800 Subject: [PATCH 256/726] fix black at prefix string (#6122) * fix black at prefix string * Type -> type * Type unused --- conversions/prefix_conversions_string.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/conversions/prefix_conversions_string.py b/conversions/prefix_conversions_string.py index 3255eae6f..3851d7c8b 100644 --- a/conversions/prefix_conversions_string.py +++ b/conversions/prefix_conversions_string.py @@ -11,7 +11,7 @@ URL: https://en.wikipedia.org/wiki/Binary_prefix from __future__ import annotations from enum import Enum, unique -from typing import Type, TypeVar +from typing import TypeVar # Create a generic variable that can be 'Enum', or any subclass. T = TypeVar("T", bound="Enum") @@ -53,7 +53,7 @@ class SIUnit(Enum): yocto = -24 @classmethod - def get_positive(cls: Type[T]) -> dict: + def get_positive(cls: type[T]) -> dict: """ Returns a dictionary with only the elements of this enum that has a positive value @@ -68,7 +68,7 @@ class SIUnit(Enum): return {unit.name: unit.value for unit in cls if unit.value > 0} @classmethod - def get_negative(cls: Type[T]) -> dict: + def get_negative(cls: type[T]) -> dict: """ Returns a dictionary with only the elements of this enum that has a negative value @@ -94,7 +94,7 @@ def add_si_prefix(value: float) -> str: """ prefixes = SIUnit.get_positive() if value > 0 else SIUnit.get_negative() for name_prefix, value_prefix in prefixes.items(): - numerical_part = value / (10 ** value_prefix) + numerical_part = value / (10**value_prefix) if numerical_part > 1: return f"{str(numerical_part)} {name_prefix}" return str(value) @@ -109,7 +109,7 @@ def add_binary_prefix(value: float) -> str: '64.0 kilo' """ for prefix in BinaryUnit: - numerical_part = value / (2 ** prefix.value) + numerical_part = value / (2**prefix.value) if numerical_part > 1: return f"{str(numerical_part)} {prefix.name}" return str(value) From 4bd5494992a03a63aa0a1d55169a0171dee38468 Mon Sep 17 00:00:00 2001 From: Vineet Rao <28603906+VinWare@users.noreply.github.com> Date: Mon, 2 May 2022 19:28:12 +0530 Subject: [PATCH 257/726] Add solution to Problem 145 of Project Euler (#5464) * Solution to Problem 145 of Project Euler * Provided more descriptive filename * Update sol1.py Co-authored-by: John Law --- project_euler/problem_145/__init__.py | 0 project_euler/problem_145/sol1.py | 57 +++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 project_euler/problem_145/__init__.py create mode 100644 project_euler/problem_145/sol1.py diff --git a/project_euler/problem_145/__init__.py b/project_euler/problem_145/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_145/sol1.py b/project_euler/problem_145/sol1.py new file mode 100644 index 000000000..82e2ea79b --- /dev/null +++ b/project_euler/problem_145/sol1.py @@ -0,0 +1,57 @@ +""" +Project Euler problem 145: https://projecteuler.net/problem=145 +Author: Vineet Rao +Problem statement: + +Some positive integers n have the property that the sum [ n + reverse(n) ] +consists entirely of odd (decimal) digits. +For instance, 36 + 63 = 99 and 409 + 904 = 1313. +We will call such numbers reversible; so 36, 63, 409, and 904 are reversible. +Leading zeroes are not allowed in either n or reverse(n). + +There are 120 reversible numbers below one-thousand. + +How many reversible numbers are there below one-billion (10^9)? +""" + + +def odd_digits(num: int) -> bool: + """ + Check if the number passed as argument has only odd digits. + >>> odd_digits(123) + False + >>> odd_digits(135797531) + True + """ + num_str = str(num) + for i in ["0", "2", "4", "6", "8"]: + if i in num_str: + return False + return True + + +def solution(max_num: int = 1_000_000_000) -> int: + """ + To evaluate the solution, use solution() + >>> solution(1000) + 120 + >>> solution(1_000_000) + 18720 + >>> solution(10_000_000) + 68720 + """ + result = 0 + # All single digit numbers reverse to themselves, so their sums are even + # Therefore at least one digit in their sum is even + # Last digit cannot be 0, else it causes leading zeros in reverse + for num in range(11, max_num): + if num % 10 == 0: + continue + num_sum = num + int(str(num)[::-1]) + num_is_reversible = odd_digits(num_sum) + result += 1 if num_is_reversible else 0 + return result + + +if __name__ == "__main__": + print(f"{solution() = }") From 26f2df762248e947638ffdb61a9d7c9f5d5f0592 Mon Sep 17 00:00:00 2001 From: Kunwar Preet Singh <75082218+Enkryp@users.noreply.github.com> Date: Mon, 2 May 2022 19:42:18 +0530 Subject: [PATCH 258/726] Add sol for P104 Project Euler (#5257) * Hacktoberfest: added sol for P104 Project Euler * bot requests resolved * pre-commit * Update sol.py * Update sol.py * remove trailing zeroes * Update sol.py * Update sol.py * Update sol.py Co-authored-by: John Law --- project_euler/problem_104/__init__.py | 0 project_euler/problem_104/sol.py | 137 ++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 project_euler/problem_104/__init__.py create mode 100644 project_euler/problem_104/sol.py diff --git a/project_euler/problem_104/__init__.py b/project_euler/problem_104/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_104/sol.py b/project_euler/problem_104/sol.py new file mode 100644 index 000000000..0818ac401 --- /dev/null +++ b/project_euler/problem_104/sol.py @@ -0,0 +1,137 @@ +""" +Project Euler Problem 104 : https://projecteuler.net/problem=104 + +The Fibonacci sequence is defined by the recurrence relation: + +Fn = Fn−1 + Fn−2, where F1 = 1 and F2 = 1. +It turns out that F541, which contains 113 digits, is the first Fibonacci number +for which the last nine digits are 1-9 pandigital (contain all the digits 1 to 9, +but not necessarily in order). And F2749, which contains 575 digits, is the first +Fibonacci number for which the first nine digits are 1-9 pandigital. + +Given that Fk is the first Fibonacci number for which the first nine digits AND +the last nine digits are 1-9 pandigital, find k. +""" + + +def check(number: int) -> bool: + """ + Takes a number and checks if it is pandigital both from start and end + + + >>> check(123456789987654321) + True + + >>> check(120000987654321) + False + + >>> check(1234567895765677987654321) + True + + """ + + check_last = [0] * 11 + check_front = [0] * 11 + + # mark last 9 numbers + for x in range(9): + check_last[int(number % 10)] = 1 + number = number // 10 + # flag + f = True + + # check last 9 numbers for pandigitality + + for x in range(9): + if not check_last[x + 1]: + f = False + if not f: + return f + + # mark first 9 numbers + number = int(str(number)[:9]) + + for x in range(9): + check_front[int(number % 10)] = 1 + number = number // 10 + + # check first 9 numbers for pandigitality + + for x in range(9): + if not check_front[x + 1]: + f = False + return f + + +def check1(number: int) -> bool: + """ + Takes a number and checks if it is pandigital from END + + >>> check1(123456789987654321) + True + + >>> check1(120000987654321) + True + + >>> check1(12345678957656779870004321) + False + + """ + + check_last = [0] * 11 + + # mark last 9 numbers + for x in range(9): + check_last[int(number % 10)] = 1 + number = number // 10 + # flag + f = True + + # check last 9 numbers for pandigitality + + for x in range(9): + if not check_last[x + 1]: + f = False + return f + + +def solution() -> int: + """ + Outputs the answer is the least Fibonacci number pandigital from both sides. + >>> solution() + 329468 + """ + + a = 1 + b = 1 + c = 2 + # temporary Fibonacci numbers + + a1 = 1 + b1 = 1 + c1 = 2 + # temporary Fibonacci numbers mod 1e9 + + # mod m=1e9, done for fast optimisation + tocheck = [0] * 1000000 + m = 1000000000 + + for x in range(1000000): + c1 = (a1 + b1) % m + a1 = b1 % m + b1 = c1 % m + if check1(b1): + tocheck[x + 3] = 1 + + for x in range(1000000): + c = a + b + a = b + b = c + # perform check only if in tocheck + if tocheck[x + 3] and check(b): + return x + 3 # first 2 already done + return -1 + + +if __name__ == "__main__": + print(f"{solution() = }") From 8226636ea321d8fddae55460cd3c8a25b537160e Mon Sep 17 00:00:00 2001 From: Simon Date: Mon, 2 May 2022 18:07:29 +0200 Subject: [PATCH 259/726] Add the Horn-Schunck algorithm (#5333) * Added implementation of the Horn-Schunck algorithm * Cleaner variable names * added doctests * Fix doctest * Update horn_schunck.py * Update horn_schunck.py * Update horn_schunck.py * Update horn_schunck.py Co-authored-by: John Law --- computer_vision/horn_schunck.py | 130 ++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 computer_vision/horn_schunck.py diff --git a/computer_vision/horn_schunck.py b/computer_vision/horn_schunck.py new file mode 100644 index 000000000..1428487d0 --- /dev/null +++ b/computer_vision/horn_schunck.py @@ -0,0 +1,130 @@ +""" + The Horn-Schunck method estimates the optical flow for every single pixel of + a sequence of images. + It works by assuming brightness constancy between two consecutive frames + and smoothness in the optical flow. + + Useful resources: + Wikipedia: https://en.wikipedia.org/wiki/Horn%E2%80%93Schunck_method + Paper: http://image.diku.dk/imagecanon/material/HornSchunckOptical_Flow.pdf +""" + +import numpy as np +from scipy.ndimage.filters import convolve +from typing_extensions import SupportsIndex + + +def warp( + image: np.ndarray, horizontal_flow: np.ndarray, vertical_flow: np.ndarray +) -> np.ndarray: + """ + Warps the pixels of an image into a new image using the horizontal and vertical + flows. + Pixels that are warped from an invalid location are set to 0. + + Parameters: + image: Grayscale image + horizontal_flow: Horizontal flow + vertical_flow: Vertical flow + + Returns: Warped image + + >>> warp(np.array([[0, 1, 2], [0, 3, 0], [2, 2, 2]]), \ + np.array([[0, 1, -1], [-1, 0, 0], [1, 1, 1]]), \ + np.array([[0, 0, 0], [0, 1, 0], [0, 0, 1]])) + array([[0, 0, 0], + [3, 1, 0], + [0, 2, 3]]) + """ + flow = np.stack((horizontal_flow, vertical_flow), 2) + + # Create a grid of all pixel coordinates and subtract the flow to get the + # target pixels coordinates + grid = np.stack( + np.meshgrid(np.arange(0, image.shape[1]), np.arange(0, image.shape[0])), 2 + ) + grid = np.round(grid - flow).astype(np.int32) + + # Find the locations outside of the original image + invalid = (grid < 0) | (grid >= np.array([image.shape[1], image.shape[0]])) + grid[invalid] = 0 + + warped = image[grid[:, :, 1], grid[:, :, 0]] + + # Set pixels at invalid locations to 0 + warped[invalid[:, :, 0] | invalid[:, :, 1]] = 0 + + return warped + + +def horn_schunck( + image0: np.ndarray, + image1: np.ndarray, + num_iter: SupportsIndex, + alpha: float | None = None, +) -> tuple[np.ndarray, np.ndarray]: + """ + This function performs the Horn-Schunck algorithm and returns the estimated + optical flow. It is assumed that the input images are grayscale and + normalized to be in [0, 1]. + + Parameters: + image0: First image of the sequence + image1: Second image of the sequence + alpha: Regularization constant + num_iter: Number of iterations performed + + Returns: estimated horizontal & vertical flow + + >>> np.round(horn_schunck(np.array([[0, 0, 2], [0, 0, 2]]), \ + np.array([[0, 2, 0], [0, 2, 0]]), alpha=0.1, num_iter=110)).\ + astype(np.int32) + array([[[ 0, -1, -1], + [ 0, -1, -1]], + + [[ 0, 0, 0], + [ 0, 0, 0]]], dtype=int32) + """ + if alpha is None: + alpha = 0.1 + + # Initialize flow + horizontal_flow = np.zeros_like(image0) + vertical_flow = np.zeros_like(image0) + + # Prepare kernels for the calculation of the derivatives and the average velocity + kernel_x = np.array([[-1, 1], [-1, 1]]) * 0.25 + kernel_y = np.array([[-1, -1], [1, 1]]) * 0.25 + kernel_t = np.array([[1, 1], [1, 1]]) * 0.25 + kernel_laplacian = np.array( + [[1 / 12, 1 / 6, 1 / 12], [1 / 6, 0, 1 / 6], [1 / 12, 1 / 6, 1 / 12]] + ) + + # Iteratively refine the flow + for _ in range(num_iter): + warped_image = warp(image0, horizontal_flow, vertical_flow) + derivative_x = convolve(warped_image, kernel_x) + convolve(image1, kernel_x) + derivative_y = convolve(warped_image, kernel_y) + convolve(image1, kernel_y) + derivative_t = convolve(warped_image, kernel_t) + convolve(image1, -kernel_t) + + avg_horizontal_velocity = convolve(horizontal_flow, kernel_laplacian) + avg_vertical_velocity = convolve(vertical_flow, kernel_laplacian) + + # This updates the flow as proposed in the paper (Step 12) + update = ( + derivative_x * avg_horizontal_velocity + + derivative_y * avg_vertical_velocity + + derivative_t + ) + update = update / (alpha**2 + derivative_x**2 + derivative_y**2) + + horizontal_flow = avg_horizontal_velocity - derivative_x * update + vertical_flow = avg_vertical_velocity - derivative_y * update + + return horizontal_flow, vertical_flow + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 3bff196981312e41ba9dac91e1bd971b7120726c Mon Sep 17 00:00:00 2001 From: KerimovEmil Date: Wed, 11 May 2022 23:28:45 -0400 Subject: [PATCH 260/726] Fix some typos in solution 1 of euler 686 (#6112) While reading this code I noticed some typos in the doc strings and wanted to fix them. --- project_euler/problem_686/sol1.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/project_euler/problem_686/sol1.py b/project_euler/problem_686/sol1.py index 3b6bdb655..99a317cd1 100644 --- a/project_euler/problem_686/sol1.py +++ b/project_euler/problem_686/sol1.py @@ -27,7 +27,7 @@ def log_difference(number: int) -> float: Computing 2^90 is time consuming. Hence we find log(2^90) = 90*log(2) = 27.092699609758302 But we require only the decimal part to determine whether the power starts with 123. - SO we just return the decimal part of the log product. + So we just return the decimal part of the log product. Therefore we return 0.092699609758302 >>> log_difference(90) @@ -57,14 +57,14 @@ def solution(number: int = 678910) -> int: So if number = 10, then solution returns 2515 as we observe from above series. - Wwe will define a lowerbound and upperbound. + We will define a lowerbound and upperbound. lowerbound = log(1.23), upperbound = log(1.24) because we need to find the powers that yield 123 as starting digits. log(1.23) = 0.08990511143939792, log(1,24) = 0.09342168516223506. We use 1.23 and not 12.3 or 123, because log(1.23) yields only decimal value which is less than 1. - log(12.3) will be same decimal vale but 1 added to it + log(12.3) will be same decimal value but 1 added to it which is log(12.3) = 1.093421685162235. We observe that decimal value remains same no matter 1.23 or 12.3 Since we use the function log_difference(), @@ -87,7 +87,7 @@ def solution(number: int = 678910) -> int: Hence to optimize the algorithm we will increment by 196 or 93 depending upon the log_difference() value. - Lets take for example 90. + Let's take for example 90. Since 90 is the first power leading to staring digits as 123, we will increment iterator by 196. Because the difference between any two powers leading to 123 @@ -99,7 +99,7 @@ def solution(number: int = 678910) -> int: The iterator will now become 379, which is the next power leading to 123 as starting digits. - Lets take 1060. We increment by 196, we get 1256. + Let's take 1060. We increment by 196, we get 1256. log_difference(1256) = 0.09367455396034, Which is greater than upperbound hence we increment by 93. Now iterator is 1349. log_difference(1349) = 0.08946415071057 which is less than lowerbound. @@ -107,7 +107,7 @@ def solution(number: int = 678910) -> int: Conditions are as follows: - 1) If we find a power, whose log_difference() is in the range of + 1) If we find a power whose log_difference() is in the range of lower and upperbound, we will increment by 196. which implies that the power is a number which will lead to 123 as starting digits. 2) If we find a power, whose log_difference() is greater than or equal upperbound, From e23c18fb5cb34d51b69e2840c304ade597163085 Mon Sep 17 00:00:00 2001 From: Omkaar <79257339+Pysics@users.noreply.github.com> Date: Thu, 12 May 2022 09:00:00 +0530 Subject: [PATCH 261/726] Fix typos (#6127) --- maths/integration_by_simpson_approx.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maths/integration_by_simpson_approx.py b/maths/integration_by_simpson_approx.py index da0e1cffd..feb77440d 100644 --- a/maths/integration_by_simpson_approx.py +++ b/maths/integration_by_simpson_approx.py @@ -40,7 +40,7 @@ def simpson_integration(function, a: float, b: float, precision: int = 4) -> flo Args: function : the function which's integration is desired a : the lower limit of integration - b : upper limit of integraion + b : upper limit of integration precision : precision of the result,error required default is 4 Returns: @@ -106,7 +106,7 @@ def simpson_integration(function, a: float, b: float, precision: int = 4) -> flo isinstance(precision, int) and precision > 0 ), f"precision should be positive integer your input : {precision}" - # just applying the formula of simpson for approximate integraion written in + # just applying the formula of simpson for approximate integration written in # mentioned article in first comment of this file and above this function h = (b - a) / N_STEPS From 533eea5afa916fbe1d0db6db8da76c68b2928ca0 Mon Sep 17 00:00:00 2001 From: Leoriem-code <73761711+Leoriem-code@users.noreply.github.com> Date: Thu, 12 May 2022 05:35:56 +0200 Subject: [PATCH 262/726] fix mypy annotations for arithmetic_analysis (#6040) * fixed mypy annotations for arithmetic_analysis * shortened numpy references --- arithmetic_analysis/gaussian_elimination.py | 14 ++++++++++---- arithmetic_analysis/in_static_equilibrium.py | 9 +++++---- arithmetic_analysis/jacobi_iteration_method.py | 14 +++++++++----- arithmetic_analysis/lu_decomposition.py | 6 +++++- 4 files changed, 29 insertions(+), 14 deletions(-) diff --git a/arithmetic_analysis/gaussian_elimination.py b/arithmetic_analysis/gaussian_elimination.py index 2dada4fbf..89ed3b323 100644 --- a/arithmetic_analysis/gaussian_elimination.py +++ b/arithmetic_analysis/gaussian_elimination.py @@ -5,9 +5,13 @@ Gaussian elimination - https://en.wikipedia.org/wiki/Gaussian_elimination import numpy as np +from numpy import float64 +from numpy.typing import NDArray -def retroactive_resolution(coefficients: np.matrix, vector: np.ndarray) -> np.ndarray: +def retroactive_resolution( + coefficients: NDArray[float64], vector: NDArray[float64] +) -> NDArray[float64]: """ This function performs a retroactive linear system resolution for triangular matrix @@ -27,7 +31,7 @@ def retroactive_resolution(coefficients: np.matrix, vector: np.ndarray) -> np.nd rows, columns = np.shape(coefficients) - x = np.zeros((rows, 1), dtype=float) + x: NDArray[float64] = np.zeros((rows, 1), dtype=float) for row in reversed(range(rows)): sum = 0 for col in range(row + 1, columns): @@ -38,7 +42,9 @@ def retroactive_resolution(coefficients: np.matrix, vector: np.ndarray) -> np.nd return x -def gaussian_elimination(coefficients: np.matrix, vector: np.ndarray) -> np.ndarray: +def gaussian_elimination( + coefficients: NDArray[float64], vector: NDArray[float64] +) -> NDArray[float64]: """ This function performs Gaussian elimination method @@ -60,7 +66,7 @@ def gaussian_elimination(coefficients: np.matrix, vector: np.ndarray) -> np.ndar return np.array((), dtype=float) # augmented matrix - augmented_mat = np.concatenate((coefficients, vector), axis=1) + augmented_mat: NDArray[float64] = np.concatenate((coefficients, vector), axis=1) augmented_mat = augmented_mat.astype("float64") # scale the matrix leaving it triangular diff --git a/arithmetic_analysis/in_static_equilibrium.py b/arithmetic_analysis/in_static_equilibrium.py index ed0d1eb98..d762a376f 100644 --- a/arithmetic_analysis/in_static_equilibrium.py +++ b/arithmetic_analysis/in_static_equilibrium.py @@ -3,7 +3,8 @@ Checks if a system of forces is in static equilibrium. """ from __future__ import annotations -from numpy import array, cos, cross, ndarray, radians, sin +from numpy import array, cos, cross, float64, radians, sin +from numpy.typing import NDArray def polar_force( @@ -27,7 +28,7 @@ def polar_force( def in_static_equilibrium( - forces: ndarray, location: ndarray, eps: float = 10**-1 + forces: NDArray[float64], location: NDArray[float64], eps: float = 10**-1 ) -> bool: """ Check if a system is in equilibrium. @@ -46,7 +47,7 @@ def in_static_equilibrium( False """ # summation of moments is zero - moments: ndarray = cross(location, forces) + moments: NDArray[float64] = cross(location, forces) sum_moments: float = sum(moments) return abs(sum_moments) < eps @@ -61,7 +62,7 @@ if __name__ == "__main__": ] ) - location = array([[0, 0], [0, 0], [0, 0]]) + location: NDArray[float64] = array([[0, 0], [0, 0], [0, 0]]) assert in_static_equilibrium(forces, location) diff --git a/arithmetic_analysis/jacobi_iteration_method.py b/arithmetic_analysis/jacobi_iteration_method.py index 667482425..4336aaa91 100644 --- a/arithmetic_analysis/jacobi_iteration_method.py +++ b/arithmetic_analysis/jacobi_iteration_method.py @@ -4,13 +4,15 @@ Jacobi Iteration Method - https://en.wikipedia.org/wiki/Jacobi_method from __future__ import annotations import numpy as np +from numpy import float64 +from numpy.typing import NDArray # Method to find solution of system of linear equations def jacobi_iteration_method( - coefficient_matrix: np.ndarray, - constant_matrix: np.ndarray, - init_val: list, + coefficient_matrix: NDArray[float64], + constant_matrix: NDArray[float64], + init_val: list[int], iterations: int, ) -> list[float]: """ @@ -99,7 +101,9 @@ def jacobi_iteration_method( if iterations <= 0: raise ValueError("Iterations must be at least 1") - table = np.concatenate((coefficient_matrix, constant_matrix), axis=1) + table: NDArray[float64] = np.concatenate( + (coefficient_matrix, constant_matrix), axis=1 + ) rows, cols = table.shape @@ -125,7 +129,7 @@ def jacobi_iteration_method( # Checks if the given matrix is strictly diagonally dominant -def strictly_diagonally_dominant(table: np.ndarray) -> bool: +def strictly_diagonally_dominant(table: NDArray[float64]) -> bool: """ >>> table = np.array([[4, 1, 1, 2], [1, 5, 2, -6], [1, 2, 4, -4]]) >>> strictly_diagonally_dominant(table) diff --git a/arithmetic_analysis/lu_decomposition.py b/arithmetic_analysis/lu_decomposition.py index b488b1bb3..371f7b166 100644 --- a/arithmetic_analysis/lu_decomposition.py +++ b/arithmetic_analysis/lu_decomposition.py @@ -6,9 +6,13 @@ Reference: from __future__ import annotations import numpy as np +import numpy.typing as NDArray +from numpy import float64 -def lower_upper_decomposition(table: np.ndarray) -> tuple[np.ndarray, np.ndarray]: +def lower_upper_decomposition( + table: NDArray[float64], +) -> tuple[NDArray[float64], NDArray[float64]]: """Lower-Upper (LU) Decomposition Example: From 562cf31a9a9d448b761cdc30df03fb7b526966d9 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Thu, 12 May 2022 06:48:04 +0300 Subject: [PATCH 263/726] Improve Project Euler problem 074 solution 2 (#5803) * Fix statement * Improve solution * Fix * Add tests --- project_euler/problem_074/sol2.py | 195 +++++++++++++++++------------- 1 file changed, 108 insertions(+), 87 deletions(-) diff --git a/project_euler/problem_074/sol2.py b/project_euler/problem_074/sol2.py index 55e67c6b9..d76bb014d 100644 --- a/project_euler/problem_074/sol2.py +++ b/project_euler/problem_074/sol2.py @@ -1,122 +1,143 @@ """ - Project Euler Problem 074: https://projecteuler.net/problem=74 +Project Euler Problem 074: https://projecteuler.net/problem=74 - Starting from any positive integer number - it is possible to attain another one summing the factorial of its digits. +The number 145 is well known for the property that the sum of the factorial of its +digits is equal to 145: - Repeating this step, we can build chains of numbers. - It is not difficult to prove that EVERY starting number - will eventually get stuck in a loop. +1! + 4! + 5! = 1 + 24 + 120 = 145 - The request is to find how many numbers less than one million - produce a chain with exactly 60 non repeating items. +Perhaps less well known is 169, in that it produces the longest chain of numbers that +link back to 169; it turns out that there are only three such loops that exist: - Solution approach: - This solution simply consists in a loop that generates - the chains of non repeating items. - The generation of the chain stops before a repeating item - or if the size of the chain is greater then the desired one. - After generating each chain, the length is checked and the - counter increases. +169 → 363601 → 1454 → 169 +871 → 45361 → 871 +872 → 45362 → 872 + +It is not difficult to prove that EVERY starting number will eventually get stuck in a +loop. For example, + +69 → 363600 → 1454 → 169 → 363601 (→ 1454) +78 → 45360 → 871 → 45361 (→ 871) +540 → 145 (→ 145) + +Starting with 69 produces a chain of five non-repeating terms, but the longest +non-repeating chain with a starting number below one million is sixty terms. + +How many chains, with a starting number below one million, contain exactly sixty +non-repeating terms? + +Solution approach: +This solution simply consists in a loop that generates the chains of non repeating +items using the cached sizes of the previous chains. +The generation of the chain stops before a repeating item or if the size of the chain +is greater then the desired one. +After generating each chain, the length is checked and the counter increases. """ +from math import factorial -factorial_cache: dict[int, int] = {} -factorial_sum_cache: dict[int, int] = {} +DIGIT_FACTORIAL: dict[str, int] = {str(digit): factorial(digit) for digit in range(10)} -def factorial(a: int) -> int: - """Returns the factorial of the input a - >>> factorial(5) - 120 - - >>> factorial(6) - 720 - - >>> factorial(0) - 1 +def digit_factorial_sum(number: int) -> int: """ + Function to perform the sum of the factorial of all the digits in number - # The factorial function is not defined for negative numbers - if a < 0: - raise ValueError("Invalid negative input!", a) + >>> digit_factorial_sum(69.0) + Traceback (most recent call last): + ... + TypeError: Parameter number must be int - if a in factorial_cache: - return factorial_cache[a] + >>> digit_factorial_sum(-1) + Traceback (most recent call last): + ... + ValueError: Parameter number must be greater than or equal to 0 - # The case of 0! is handled separately - if a == 0: - factorial_cache[a] = 1 - else: - # use a temporary support variable to store the computation - temporary_number = a - temporary_computation = 1 + >>> digit_factorial_sum(0) + 1 - while temporary_number > 0: - temporary_computation *= temporary_number - temporary_number -= 1 - - factorial_cache[a] = temporary_computation - return factorial_cache[a] - - -def factorial_sum(a: int) -> int: - """Function to perform the sum of the factorial - of all the digits in a - - >>> factorial_sum(69) + >>> digit_factorial_sum(69) 363600 """ - if a in factorial_sum_cache: - return factorial_sum_cache[a] - # Prepare a variable to hold the computation - fact_sum = 0 + if not isinstance(number, int): + raise TypeError("Parameter number must be int") - """ Convert a in string to iterate on its digits - convert the digit back into an int - and add its factorial to fact_sum. - """ - for i in str(a): - fact_sum += factorial(int(i)) - factorial_sum_cache[a] = fact_sum - return fact_sum + if number < 0: + raise ValueError("Parameter number must be greater than or equal to 0") + + # Converts number in string to iterate on its digits and adds its factorial. + return sum(DIGIT_FACTORIAL[digit] for digit in str(number)) def solution(chain_length: int = 60, number_limit: int = 1000000) -> int: - """Returns the number of numbers that produce - chains with exactly 60 non repeating elements. + """ + Returns the number of numbers below number_limit that produce chains with exactly + chain_length non repeating elements. + + >>> solution(10.0, 1000) + Traceback (most recent call last): + ... + TypeError: Parameters chain_length and number_limit must be int + + >>> solution(10, 1000.0) + Traceback (most recent call last): + ... + TypeError: Parameters chain_length and number_limit must be int + + >>> solution(0, 1000) + Traceback (most recent call last): + ... + ValueError: Parameters chain_length and number_limit must be greater than 0 + + >>> solution(10, 0) + Traceback (most recent call last): + ... + ValueError: Parameters chain_length and number_limit must be greater than 0 + >>> solution(10, 1000) 26 """ + if not isinstance(chain_length, int) or not isinstance(number_limit, int): + raise TypeError("Parameters chain_length and number_limit must be int") + + if chain_length <= 0 or number_limit <= 0: + raise ValueError( + "Parameters chain_length and number_limit must be greater than 0" + ) + # the counter for the chains with the exact desired length - chain_counter = 0 + chains_counter = 0 + # the cached sizes of the previous chains + chain_sets_lengths: dict[int, int] = {} - for i in range(1, number_limit + 1): + for start_chain_element in range(1, number_limit): - # The temporary list will contain the elements of the chain - chain_set = {i} - len_chain_set = 1 - last_chain_element = i + # The temporary set will contain the elements of the chain + chain_set = set() + chain_set_length = 0 - # The new element of the chain - new_chain_element = factorial_sum(last_chain_element) + # Stop computing the chain when you find a cached size, a repeating item or the + # length is greater then the desired one. + chain_element = start_chain_element + while ( + chain_element not in chain_sets_lengths + and chain_element not in chain_set + and chain_set_length <= chain_length + ): + chain_set.add(chain_element) + chain_set_length += 1 + chain_element = digit_factorial_sum(chain_element) - # Stop computing the chain when you find a repeating item - # or the length it greater then the desired one. + if chain_element in chain_sets_lengths: + chain_set_length += chain_sets_lengths[chain_element] - while new_chain_element not in chain_set and len_chain_set <= chain_length: - chain_set.add(new_chain_element) + chain_sets_lengths[start_chain_element] = chain_set_length - len_chain_set += 1 - last_chain_element = new_chain_element - new_chain_element = factorial_sum(last_chain_element) + # If chain contains the exact amount of elements increase the counter + if chain_set_length == chain_length: + chains_counter += 1 - # If the while exited because the chain list contains the exact amount - # of elements increase the counter - if len_chain_set == chain_length: - chain_counter += 1 - - return chain_counter + return chains_counter if __name__ == "__main__": From bbb88bb5c261085ff23bce2b3c17266ebfa7b087 Mon Sep 17 00:00:00 2001 From: eee555 <50390200+eee555@users.noreply.github.com> Date: Fri, 13 May 2022 04:28:51 +0800 Subject: [PATCH 264/726] Fix bug in bucket_sort.py (#6005) --- sorts/bucket_sort.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sorts/bucket_sort.py b/sorts/bucket_sort.py index 58242a1cb..7bcbe61a4 100644 --- a/sorts/bucket_sort.py +++ b/sorts/bucket_sort.py @@ -54,8 +54,8 @@ def bucket_sort(my_list: list) -> list: bucket_count = int(max_value - min_value) + 1 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]) + for i in my_list: + buckets[int(i - min_value)].append(i) return [v for bucket in buckets for v in sorted(bucket)] From e95ecfaf27c545391bdb7a2d1d8948943a40f828 Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj Date: Fri, 13 May 2022 11:25:53 +0530 Subject: [PATCH 265/726] Add missing type annotations for `strings` directory (#5817) * Type annotations for `strings/autocomplete_using_trie.py` * Update autocomplete_using_trie.py * Update detecting_english_programmatically.py * Update detecting_english_programmatically.py * Update frequency_finder.py * Update frequency_finder.py * Update frequency_finder.py * Update word_occurrence.py * Update frequency_finder.py * Update z_function.py * Update z_function.py * Update frequency_finder.py --- strings/autocomplete_using_trie.py | 28 +++--- strings/detecting_english_programmatically.py | 53 ++++++----- strings/frequency_finder.py | 94 +++++++------------ strings/word_occurrence.py | 3 +- strings/z_function.py | 6 +- 5 files changed, 82 insertions(+), 102 deletions(-) diff --git a/strings/autocomplete_using_trie.py b/strings/autocomplete_using_trie.py index 8aa0dc223..758260292 100644 --- a/strings/autocomplete_using_trie.py +++ b/strings/autocomplete_using_trie.py @@ -1,11 +1,13 @@ +from __future__ import annotations + END = "#" class Trie: - def __init__(self): - self._trie = {} + def __init__(self) -> None: + self._trie: dict = {} - def insert_word(self, text): + def insert_word(self, text: str) -> None: trie = self._trie for char in text: if char not in trie: @@ -13,7 +15,7 @@ class Trie: trie = trie[char] trie[END] = True - def find_word(self, prefix): + def find_word(self, prefix: str) -> tuple | list: trie = self._trie for char in prefix: if char in trie: @@ -22,7 +24,7 @@ class Trie: return [] return self._elements(trie) - def _elements(self, d): + def _elements(self, d: dict) -> tuple: result = [] for c, v in d.items(): if c == END: @@ -39,26 +41,28 @@ for word in words: trie.insert_word(word) -def autocomplete_using_trie(s): +def autocomplete_using_trie(string: str) -> tuple: """ >>> trie = Trie() >>> for word in words: ... trie.insert_word(word) ... >>> matches = autocomplete_using_trie("de") - - "detergent " in matches + >>> "detergent " in matches True - "dog " in matches + >>> "dog " in matches False """ - suffixes = trie.find_word(s) - return tuple(s + w for w in suffixes) + suffixes = trie.find_word(string) + return tuple(string + word for word in suffixes) -def main(): +def main() -> None: print(autocomplete_using_trie("de")) if __name__ == "__main__": + import doctest + + doctest.testmod() main() diff --git a/strings/detecting_english_programmatically.py b/strings/detecting_english_programmatically.py index 44fb71918..aa18db210 100644 --- a/strings/detecting_english_programmatically.py +++ b/strings/detecting_english_programmatically.py @@ -4,55 +4,56 @@ UPPERLETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" LETTERS_AND_SPACE = UPPERLETTERS + UPPERLETTERS.lower() + " \t\n" -def loadDictionary(): +def load_dictionary() -> dict[str, None]: path = os.path.split(os.path.realpath(__file__)) - englishWords = {} - with open(path[0] + "/dictionary.txt") as dictionaryFile: - for word in dictionaryFile.read().split("\n"): - englishWords[word] = None - return englishWords + english_words: dict[str, None] = {} + with open(path[0] + "/dictionary.txt") as dictionary_file: + for word in dictionary_file.read().split("\n"): + english_words[word] = None + return english_words -ENGLISH_WORDS = loadDictionary() +ENGLISH_WORDS = load_dictionary() -def getEnglishCount(message): +def get_english_count(message: str) -> float: message = message.upper() - message = removeNonLetters(message) - possibleWords = message.split() + message = remove_non_letters(message) + possible_words = message.split() - if possibleWords == []: + if possible_words == []: return 0.0 matches = 0 - for word in possibleWords: + for word in possible_words: if word in ENGLISH_WORDS: matches += 1 - return float(matches) / len(possibleWords) + return float(matches) / len(possible_words) -def removeNonLetters(message): - lettersOnly = [] +def remove_non_letters(message: str) -> str: + letters_only = [] for symbol in message: if symbol in LETTERS_AND_SPACE: - lettersOnly.append(symbol) - return "".join(lettersOnly) + letters_only.append(symbol) + return "".join(letters_only) -def isEnglish(message, wordPercentage=20, letterPercentage=85): +def is_english( + message: str, word_percentage: int = 20, letter_percentage: int = 85 +) -> bool: """ - >>> isEnglish('Hello World') + >>> is_english('Hello World') True - - >>> isEnglish('llold HorWd') + >>> is_english('llold HorWd') False """ - wordsMatch = getEnglishCount(message) * 100 >= wordPercentage - numLetters = len(removeNonLetters(message)) - messageLettersPercentage = (float(numLetters) / len(message)) * 100 - lettersMatch = messageLettersPercentage >= letterPercentage - return wordsMatch and lettersMatch + words_match = get_english_count(message) * 100 >= word_percentage + num_letters = len(remove_non_letters(message)) + message_letters_percentage = (float(num_letters) / len(message)) * 100 + letters_match = message_letters_percentage >= letter_percentage + return words_match and letters_match if __name__ == "__main__": diff --git a/strings/frequency_finder.py b/strings/frequency_finder.py index 48760a9de..7024be17b 100644 --- a/strings/frequency_finder.py +++ b/strings/frequency_finder.py @@ -1,7 +1,9 @@ # Frequency Finder +import string + # frequency taken from http://en.wikipedia.org/wiki/Letter_frequency -englishLetterFreq = { +english_letter_freq = { "E": 12.70, "T": 9.06, "A": 8.17, @@ -33,85 +35,57 @@ ETAOIN = "ETAOINSHRDLCUMWFGYPBVKJXQZ" LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" -def getLetterCount(message): - letterCount = { - "A": 0, - "B": 0, - "C": 0, - "D": 0, - "E": 0, - "F": 0, - "G": 0, - "H": 0, - "I": 0, - "J": 0, - "K": 0, - "L": 0, - "M": 0, - "N": 0, - "O": 0, - "P": 0, - "Q": 0, - "R": 0, - "S": 0, - "T": 0, - "U": 0, - "V": 0, - "W": 0, - "X": 0, - "Y": 0, - "Z": 0, - } +def get_letter_count(message: str) -> dict[str, int]: + letter_count = {letter: 0 for letter in string.ascii_uppercase} for letter in message.upper(): if letter in LETTERS: - letterCount[letter] += 1 + letter_count[letter] += 1 - return letterCount + return letter_count -def getItemAtIndexZero(x): +def get_item_at_index_zero(x: tuple) -> str: return x[0] -def getFrequencyOrder(message): - letterToFreq = getLetterCount(message) - freqToLetter = {} +def get_frequency_order(message: str) -> str: + letter_to_freq = get_letter_count(message) + freq_to_letter: dict[int, list[str]] = { + freq: [] for letter, freq in letter_to_freq.items() + } for letter in LETTERS: - if letterToFreq[letter] not in freqToLetter: - freqToLetter[letterToFreq[letter]] = [letter] - else: - freqToLetter[letterToFreq[letter]].append(letter) + freq_to_letter[letter_to_freq[letter]].append(letter) - for freq in freqToLetter: - freqToLetter[freq].sort(key=ETAOIN.find, reverse=True) - freqToLetter[freq] = "".join(freqToLetter[freq]) + freq_to_letter_str: dict[int, str] = {} - freqPairs = list(freqToLetter.items()) - freqPairs.sort(key=getItemAtIndexZero, reverse=True) + for freq in freq_to_letter: + freq_to_letter[freq].sort(key=ETAOIN.find, reverse=True) + freq_to_letter_str[freq] = "".join(freq_to_letter[freq]) - freqOrder = [] - for freqPair in freqPairs: - freqOrder.append(freqPair[1]) + freq_pairs = list(freq_to_letter_str.items()) + freq_pairs.sort(key=get_item_at_index_zero, reverse=True) - return "".join(freqOrder) + freq_order: list[str] = [freq_pair[1] for freq_pair in freq_pairs] + + return "".join(freq_order) -def englishFreqMatchScore(message): +def english_freq_match_score(message: str) -> int: """ - >>> englishFreqMatchScore('Hello World') + >>> english_freq_match_score('Hello World') 1 """ - freqOrder = getFrequencyOrder(message) - matchScore = 0 - for commonLetter in ETAOIN[:6]: - if commonLetter in freqOrder[:6]: - matchScore += 1 + freq_order = get_frequency_order(message) + match_score = 0 + for common_letter in ETAOIN[:6]: + if common_letter in freq_order[:6]: + match_score += 1 - for uncommonLetter in ETAOIN[-6:]: - if uncommonLetter in freqOrder[-6:]: - matchScore += 1 + for uncommon_letter in ETAOIN[-6:]: + if uncommon_letter in freq_order[-6:]: + match_score += 1 - return matchScore + return match_score if __name__ == "__main__": diff --git a/strings/word_occurrence.py b/strings/word_occurrence.py index 4acfa41ad..4e0b3ff34 100644 --- a/strings/word_occurrence.py +++ b/strings/word_occurrence.py @@ -1,6 +1,7 @@ # Created by sarathkaul on 17/11/19 # Modified by Arkadip Bhattacharya(@darkmatter18) on 20/04/2020 from collections import defaultdict +from typing import DefaultDict def word_occurence(sentence: str) -> dict: @@ -14,7 +15,7 @@ def word_occurence(sentence: str) -> dict: >>> dict(word_occurence("Two spaces")) {'Two': 1, 'spaces': 1} """ - occurrence: dict = defaultdict(int) + occurrence: DefaultDict[str, int] = defaultdict(int) # Creating a dictionary containing count of each word for word in sentence.split(): occurrence[word] += 1 diff --git a/strings/z_function.py b/strings/z_function.py index d8d823a37..e77ba8dab 100644 --- a/strings/z_function.py +++ b/strings/z_function.py @@ -10,7 +10,7 @@ Time Complexity: O(n) - where n is the length of the string """ -def z_function(input_str: str) -> list: +def z_function(input_str: str) -> list[int]: """ For the given string this function computes value for each index, which represents the maximal length substring starting from the index @@ -27,7 +27,7 @@ def z_function(input_str: str) -> list: >>> z_function("zxxzxxz") [0, 0, 0, 4, 0, 0, 1] """ - z_result = [0] * len(input_str) + z_result = [0 for i in range(len(input_str))] # initialize interval's left pointer and right pointer left_pointer, right_pointer = 0, 0 @@ -49,7 +49,7 @@ def z_function(input_str: str) -> list: return z_result -def go_next(i, z_result, s): +def go_next(i: int, z_result: list[int], s: str) -> bool: """ Check if we have to move forward to the next characters or not """ From dbee5f072f68c57bce3443e5ed07fe496ba9d76d Mon Sep 17 00:00:00 2001 From: Omkaar <79257339+Pysics@users.noreply.github.com> Date: Fri, 13 May 2022 18:21:44 +0530 Subject: [PATCH 266/726] Improve code on f-strings and brevity (#6126) * Update strassen_matrix_multiplication.py * Update matrix_operation.py * Update enigma_machine2.py * Update enigma_machine.py * Update enigma_machine2.py * Update rod_cutting.py * Update external_sort.py * Update sol1.py * Update hill_cipher.py * Update prime_numbers.py * Update integration_by_simpson_approx.py --- ciphers/enigma_machine2.py | 6 +++--- ciphers/hill_cipher.py | 2 +- data_structures/hashing/number_theory/prime_numbers.py | 2 +- divide_and_conquer/strassen_matrix_multiplication.py | 2 +- dynamic_programming/rod_cutting.py | 2 +- hashes/enigma_machine.py | 2 +- maths/integration_by_simpson_approx.py | 10 +++------- matrix/matrix_operation.py | 2 +- project_euler/problem_067/sol1.py | 2 +- sorts/external_sort.py | 2 +- 10 files changed, 14 insertions(+), 18 deletions(-) diff --git a/ciphers/enigma_machine2.py b/ciphers/enigma_machine2.py index 9252dd0ed..70f84752d 100644 --- a/ciphers/enigma_machine2.py +++ b/ciphers/enigma_machine2.py @@ -94,15 +94,15 @@ def _validator( rotorpos1, rotorpos2, rotorpos3 = rotpos if not 0 < rotorpos1 <= len(abc): raise ValueError( - f"First rotor position is not within range of 1..26 (" f"{rotorpos1}" + "First rotor position is not within range of 1..26 (" f"{rotorpos1}" ) if not 0 < rotorpos2 <= len(abc): raise ValueError( - f"Second rotor position is not within range of 1..26 (" f"{rotorpos2})" + "Second rotor position is not within range of 1..26 (" f"{rotorpos2})" ) if not 0 < rotorpos3 <= len(abc): raise ValueError( - f"Third rotor position is not within range of 1..26 (" f"{rotorpos3})" + "Third rotor position is not within range of 1..26 (" f"{rotorpos3})" ) # Validates string and returns dict diff --git a/ciphers/hill_cipher.py b/ciphers/hill_cipher.py index bc8f5b41b..d8e436e92 100644 --- a/ciphers/hill_cipher.py +++ b/ciphers/hill_cipher.py @@ -62,7 +62,7 @@ class HillCipher: # take x and return x % len(key_string) modulus = numpy.vectorize(lambda x: x % 36) - to_int = numpy.vectorize(lambda x: round(x)) + to_int = numpy.vectorize(round) def __init__(self, encrypt_key: numpy.ndarray) -> None: """ diff --git a/data_structures/hashing/number_theory/prime_numbers.py b/data_structures/hashing/number_theory/prime_numbers.py index db4d40f47..bf614e7d4 100644 --- a/data_structures/hashing/number_theory/prime_numbers.py +++ b/data_structures/hashing/number_theory/prime_numbers.py @@ -14,7 +14,7 @@ def check_prime(number): elif number == special_non_primes[-1]: return 3 - return all([number % i for i in range(2, number)]) + return all(number % i for i in range(2, number)) def next_prime(value, factor=1, **kwargs): diff --git a/divide_and_conquer/strassen_matrix_multiplication.py b/divide_and_conquer/strassen_matrix_multiplication.py index ca10e04ab..17efcfc7c 100644 --- a/divide_and_conquer/strassen_matrix_multiplication.py +++ b/divide_and_conquer/strassen_matrix_multiplication.py @@ -114,7 +114,7 @@ def strassen(matrix1: list, matrix2: list) -> list: """ if matrix_dimensions(matrix1)[1] != matrix_dimensions(matrix2)[0]: raise Exception( - f"Unable to multiply these matrices, please check the dimensions. \n" + "Unable to multiply these matrices, please check the dimensions. \n" f"Matrix A:{matrix1} \nMatrix B:{matrix2}" ) dimension1 = matrix_dimensions(matrix1) diff --git a/dynamic_programming/rod_cutting.py b/dynamic_programming/rod_cutting.py index 442a39cb1..79104d8f4 100644 --- a/dynamic_programming/rod_cutting.py +++ b/dynamic_programming/rod_cutting.py @@ -181,7 +181,7 @@ def _enforce_args(n: int, prices: list): if n > len(prices): raise ValueError( - f"Each integral piece of rod must have a corresponding " + "Each integral piece of rod must have a corresponding " f"price. Got n = {n} but length of prices = {len(prices)}" ) diff --git a/hashes/enigma_machine.py b/hashes/enigma_machine.py index d1cb6efc2..b0d45718e 100644 --- a/hashes/enigma_machine.py +++ b/hashes/enigma_machine.py @@ -55,5 +55,5 @@ if __name__ == "__main__": print("\n" + "".join(code)) print( f"\nYour Token is {token} please write it down.\nIf you want to decode " - f"this message again you should input same digits as token!" + "this message again you should input same digits as token!" ) diff --git a/maths/integration_by_simpson_approx.py b/maths/integration_by_simpson_approx.py index feb77440d..408041de9 100644 --- a/maths/integration_by_simpson_approx.py +++ b/maths/integration_by_simpson_approx.py @@ -92,16 +92,12 @@ def simpson_integration(function, a: float, b: float, precision: int = 4) -> flo assert callable( function ), f"the function(object) passed should be callable your input : {function}" - assert isinstance(a, float) or isinstance( - a, int - ), f"a should be float or integer your input : {a}" - assert isinstance(function(a), float) or isinstance(function(a), int), ( + assert isinstance(a, (float, int)), f"a should be float or integer your input : {a}" + assert isinstance(function(a), (float, int)), ( "the function should return integer or float return type of your function, " f"{type(a)}" ) - assert isinstance(b, float) or isinstance( - b, int - ), f"b should be float or integer your input : {b}" + assert isinstance(b, (float, int)), f"b should be float or integer your input : {b}" assert ( isinstance(precision, int) and precision > 0 ), f"precision should be positive integer your input : {precision}" diff --git a/matrix/matrix_operation.py b/matrix/matrix_operation.py index 6d0cd4e65..8e5d0f583 100644 --- a/matrix/matrix_operation.py +++ b/matrix/matrix_operation.py @@ -171,7 +171,7 @@ def _verify_matrix_sizes( shape = _shape(matrix_a) + _shape(matrix_b) if shape[0] != shape[3] or shape[1] != shape[2]: raise ValueError( - f"operands could not be broadcast together with shape " + "operands could not be broadcast together with shape " f"({shape[0], shape[1]}), ({shape[2], shape[3]})" ) return (shape[0], shape[2]), (shape[1], shape[3]) diff --git a/project_euler/problem_067/sol1.py b/project_euler/problem_067/sol1.py index ebfa865a9..527d4dc59 100644 --- a/project_euler/problem_067/sol1.py +++ b/project_euler/problem_067/sol1.py @@ -29,7 +29,7 @@ def solution(): triangle = f.readlines() a = map(lambda x: x.rstrip("\r\n").split(" "), triangle) - a = list(map(lambda x: list(map(lambda y: int(y), x)), a)) + a = list(map(lambda x: list(map(int, x)), a)) for i in range(1, len(a)): for j in range(len(a[i])): diff --git a/sorts/external_sort.py b/sorts/external_sort.py index 060e67adf..7af7dc0a6 100644 --- a/sorts/external_sort.py +++ b/sorts/external_sort.py @@ -41,7 +41,7 @@ class FileSplitter: i += 1 def cleanup(self): - map(lambda f: os.remove(f), self.block_filenames) + map(os.remove, self.block_filenames) class NWayMerge: From 80f1da235b0a467dc9b31aa8a56dd3a792a59d7c Mon Sep 17 00:00:00 2001 From: zer0-x <65136727+zer0-x@users.noreply.github.com> Date: Mon, 16 May 2022 14:28:30 +0300 Subject: [PATCH 267/726] Add sin function to maths (#5949) * Add sin function to /maths. * Fix typo in /maths/sin.py * Format sin.py to meet the new black rules. * Some improvements. * Fix a formating error. --- maths/sin.py | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 maths/sin.py diff --git a/maths/sin.py b/maths/sin.py new file mode 100644 index 000000000..b06e6c9f1 --- /dev/null +++ b/maths/sin.py @@ -0,0 +1,64 @@ +""" +Calculate sin function. + +It's not a perfect function so I am rounding the result to 10 decimal places by default. + +Formula: sin(x) = x - x^3/3! + x^5/5! - x^7/7! + ... +Where: x = angle in randians. + +Source: + https://www.homeschoolmath.net/teaching/sine_calculator.php + +""" + +from math import factorial, radians + + +def sin( + angle_in_degrees: float, accuracy: int = 18, rounded_values_count: int = 10 +) -> float: + """ + Implement sin function. + + >>> sin(0.0) + 0.0 + >>> sin(90.0) + 1.0 + >>> sin(180.0) + 0.0 + >>> sin(270.0) + -1.0 + >>> sin(0.68) + 0.0118679603 + >>> sin(1.97) + 0.0343762121 + >>> sin(64.0) + 0.8987940463 + >>> sin(9999.0) + -0.9876883406 + >>> sin(-689.0) + 0.5150380749 + >>> sin(89.7) + 0.9999862922 + """ + # Simplify the angle to be between 360 and -360 degrees. + angle_in_degrees = angle_in_degrees - ((angle_in_degrees // 360.0) * 360.0) + + # Converting from degrees to radians + angle_in_radians = radians(angle_in_degrees) + + result = angle_in_radians + a = 3 + b = -1 + + for _ in range(accuracy): + result += (b * (angle_in_radians**a)) / factorial(a) + + b = -b # One positive term and the next will be negative and so on... + a += 2 # Increased by 2 for every term. + + return round(result, rounded_values_count) + + +if __name__ == "__main__": + __import__("doctest").testmod() From ec54da34b96de0b09b0685881646df1f9f7df989 Mon Sep 17 00:00:00 2001 From: Aviv Faraj <73610201+avivfaraj@users.noreply.github.com> Date: Mon, 16 May 2022 10:26:19 -0400 Subject: [PATCH 268/726] Lorenz transformation - physics (#6097) * Add files via upload * Changed print to f-string Also printed out results in a math notation * Add files via upload * Fixes: #4710 provided return type * File exists in another pull request * imported radians from math * Updated file according to pre-commit test * Updated file * Updated gamma * Deleted duplicate file * removed pi * reversed tests * Fixed angle condition * Modified prints to f-string * Update horizontal_projectile_motion.py * Update horizontal_projectile_motion.py * Fixes #4710 added exceptions and tests * Added float tests * Fixed type annotations * Fixed last annotation * Fixed annotations * fixed format * Revert "fixed format" This reverts commit 5b0249ac0a0f9c36c3cfbab8423eb72925a73ffb. Undo changes @wq * Revert "Fixed annotations" This reverts commit c37bb9540834cb77e37822eb376a5896cda34778. * Revert "Fixed last annotation" This reverts commit e3678fdeadd23f1bfca27015ab524efa184f6c79. * Revert "Fixed type annotations" This reverts commit 3f2b238c34cd926b335d1f6f750e009f08e8f270. * Revert to 4e2fcaf6fb * Fixing errors found during pre-commit * Added gauss law * Implemented Lorenz tranformation with four vector * pre-commit fixes * flake8 fixes * More flake8 fixes * Added blank space for flake8 * Added reference * Trailing whitespace fix * Replaced argument u with velocity (descriptive name fix) * Added tests for functions + moved velocity check to beta function * Modified condition to 'not symbolic' in the transform function * trainling whitespace fix * Added type hint for 'smybolic' argument in transform function * Changed reference to avoid pre-commit fails because of spelling issue related to the URL * Added tests for gamma and transformation_matrix functions * Fixed transformation_matrix tests * Fixed tests on beta and gamma functions --- physics/__init__.py | 0 physics/lorenz_transformation_four_vector.py | 205 +++++++++++++++++++ 2 files changed, 205 insertions(+) create mode 100644 physics/__init__.py create mode 100644 physics/lorenz_transformation_four_vector.py diff --git a/physics/__init__.py b/physics/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/physics/lorenz_transformation_four_vector.py b/physics/lorenz_transformation_four_vector.py new file mode 100644 index 000000000..6c0d5f9d1 --- /dev/null +++ b/physics/lorenz_transformation_four_vector.py @@ -0,0 +1,205 @@ +""" +Lorenz transformation describes the transition from a reference frame P +to another reference frame P', each of which is moving in a direction with +respect to the other. The Lorenz transformation implemented in this code +is the relativistic version using a four vector described by Minkowsky Space: +x0 = ct, x1 = x, x2 = y, and x3 = z + +NOTE: Please note that x0 is c (speed of light) times t (time). + +So, the Lorenz transformation using a four vector is defined as: + +|ct'| | γ -γβ 0 0| |ct| +|x' | = |-γβ γ 0 0| *|x | +|y' | | 0 0 1 0| |y | +|z' | | 0 0 0 1| |z | + +Where: + 1 +γ = --------------- + ----------- + / v^2 | + /(1 - --- + -/ c^2 + + v +β = ----- + c + +Reference: https://en.wikipedia.org/wiki/Lorentz_transformation +""" +from __future__ import annotations + +from math import sqrt + +import numpy as np # type: ignore +from sympy import symbols # type: ignore + +# Coefficient +# Speed of light (m/s) +c = 299792458 + +# Symbols +ct, x, y, z = symbols("ct x y z") +ct_p, x_p, y_p, z_p = symbols("ct' x' y' z'") + + +# Vehicle's speed divided by speed of light (no units) +def beta(velocity: float) -> float: + """ + >>> beta(c) + 1.0 + + >>> beta(199792458) + 0.666435904801848 + + >>> beta(1e5) + 0.00033356409519815205 + + >>> beta(0.2) + Traceback (most recent call last): + ... + ValueError: Speed must be greater than 1! + """ + if velocity > c: + raise ValueError("Speed must not exceed Light Speed 299,792,458 [m/s]!") + + # Usually the speed u should be much higher than 1 (c order of magnitude) + elif velocity < 1: + raise ValueError("Speed must be greater than 1!") + return velocity / c + + +def gamma(velocity: float) -> float: + """ + >>> gamma(4) + 1.0000000000000002 + + >>> gamma(1e5) + 1.0000000556325075 + + >>> gamma(3e7) + 1.005044845777813 + + >>> gamma(2.8e8) + 2.7985595722318277 + + >>> gamma(299792451) + 4627.49902669495 + + >>> gamma(0.3) + Traceback (most recent call last): + ... + ValueError: Speed must be greater than 1! + + >>> gamma(2*c) + Traceback (most recent call last): + ... + ValueError: Speed must not exceed Light Speed 299,792,458 [m/s]! + """ + return 1 / (sqrt(1 - beta(velocity) ** 2)) + + +def transformation_matrix(velocity: float) -> np.array: + """ + >>> transformation_matrix(29979245) + array([[ 1.00503781, -0.10050378, 0. , 0. ], + [-0.10050378, 1.00503781, 0. , 0. ], + [ 0. , 0. , 1. , 0. ], + [ 0. , 0. , 0. , 1. ]]) + + >>> transformation_matrix(19979245.2) + array([[ 1.00222811, -0.06679208, 0. , 0. ], + [-0.06679208, 1.00222811, 0. , 0. ], + [ 0. , 0. , 1. , 0. ], + [ 0. , 0. , 0. , 1. ]]) + + >>> transformation_matrix(1) + array([[ 1.00000000e+00, -3.33564095e-09, 0.00000000e+00, + 0.00000000e+00], + [-3.33564095e-09, 1.00000000e+00, 0.00000000e+00, + 0.00000000e+00], + [ 0.00000000e+00, 0.00000000e+00, 1.00000000e+00, + 0.00000000e+00], + [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 1.00000000e+00]]) + + >>> transformation_matrix(0) + Traceback (most recent call last): + ... + ValueError: Speed must be greater than 1! + + >>> transformation_matrix(c * 1.5) + Traceback (most recent call last): + ... + ValueError: Speed must not exceed Light Speed 299,792,458 [m/s]! + """ + return np.array( + [ + [gamma(velocity), -gamma(velocity) * beta(velocity), 0, 0], + [-gamma(velocity) * beta(velocity), gamma(velocity), 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1], + ] + ) + + +def transform( + velocity: float, event: np.array = np.zeros(4), symbolic: bool = True +) -> np.array: + """ + >>> transform(29979245,np.array([1,2,3,4]), False) + array([ 3.01302757e+08, -3.01302729e+07, 3.00000000e+00, 4.00000000e+00]) + + >>> transform(29979245) + array([1.00503781498831*ct - 0.100503778816875*x, + -0.100503778816875*ct + 1.00503781498831*x, 1.0*y, 1.0*z], + dtype=object) + + >>> transform(19879210.2) + array([1.0022057787097*ct - 0.066456172618675*x, + -0.066456172618675*ct + 1.0022057787097*x, 1.0*y, 1.0*z], + dtype=object) + + >>> transform(299792459, np.array([1,1,1,1])) + Traceback (most recent call last): + ... + ValueError: Speed must not exceed Light Speed 299,792,458 [m/s]! + + >>> transform(-1, np.array([1,1,1,1])) + Traceback (most recent call last): + ... + ValueError: Speed must be greater than 1! + """ + # Ensure event is not a vector of zeros + if not symbolic: + + # x0 is ct (speed of ligt * time) + event[0] = event[0] * c + else: + + # Symbolic four vector + event = np.array([ct, x, y, z]) + + return transformation_matrix(velocity).dot(event) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + + # Example of symbolic vector: + four_vector = transform(29979245) + print("Example of four vector: ") + print(f"ct' = {four_vector[0]}") + print(f"x' = {four_vector[1]}") + print(f"y' = {four_vector[2]}") + print(f"z' = {four_vector[3]}") + + # Substitute symbols with numerical values: + values = np.array([1, 1, 1, 1]) + sub_dict = {ct: c * values[0], x: values[1], y: values[2], z: values[3]} + numerical_vector = [four_vector[i].subs(sub_dict) for i in range(0, 4)] + + print(f"\n{numerical_vector}") From dceb30aad623c8c9dffd739f41e1f5f46eb44530 Mon Sep 17 00:00:00 2001 From: Ikko Ashimine Date: Fri, 20 May 2022 13:03:54 +0900 Subject: [PATCH 269/726] Fix typo in word_occurrence.py (#6154) word_occurence -> word_occurrence --- strings/word_occurrence.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/strings/word_occurrence.py b/strings/word_occurrence.py index 4e0b3ff34..8260620c3 100644 --- a/strings/word_occurrence.py +++ b/strings/word_occurrence.py @@ -4,15 +4,15 @@ from collections import defaultdict from typing import DefaultDict -def word_occurence(sentence: str) -> dict: +def word_occurrence(sentence: str) -> dict: """ >>> from collections import Counter >>> SENTENCE = "a b A b c b d b d e f e g e h e i e j e 0" - >>> occurence_dict = word_occurence(SENTENCE) + >>> occurence_dict = word_occurrence(SENTENCE) >>> all(occurence_dict[word] == count for word, count ... in Counter(SENTENCE.split()).items()) True - >>> dict(word_occurence("Two spaces")) + >>> dict(word_occurrence("Two spaces")) {'Two': 1, 'spaces': 1} """ occurrence: DefaultDict[str, int] = defaultdict(int) @@ -23,5 +23,5 @@ def word_occurence(sentence: str) -> dict: if __name__ == "__main__": - for word, count in word_occurence("INPUT STRING").items(): + for word, count in word_occurrence("INPUT STRING").items(): print(f"{word}: {count}") From 5bac76d7a505c43aad6d0a32cd39982f4b927eac Mon Sep 17 00:00:00 2001 From: dangbb <51513363+dangbb@users.noreply.github.com> Date: Sat, 21 May 2022 21:02:53 +0700 Subject: [PATCH 270/726] Fix `iter_merge_sort` bug (#6153) * Fixed bug where array length 2 can't be sorted * Add MCC and DU path test Add test to conversions/octal_to_decimal.py and sorts\iterative_merge_sort.py * "" * Update octal_to_decimal.py Co-authored-by: John Law --- conversions/octal_to_decimal.py | 36 +++++++++++++++++++++++++++++++++ sorts/iterative_merge_sort.py | 24 ++++++++++++++++++++-- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/conversions/octal_to_decimal.py b/conversions/octal_to_decimal.py index 5a7373fef..551311e26 100644 --- a/conversions/octal_to_decimal.py +++ b/conversions/octal_to_decimal.py @@ -2,12 +2,48 @@ def oct_to_decimal(oct_string: str) -> int: """ Convert a octal value to its decimal equivalent + >>> oct_to_decimal("") + Traceback (most recent call last): + ... + ValueError: Empty string was passed to the function + >>> oct_to_decimal("-") + Traceback (most recent call last): + ... + ValueError: Non-octal value was passed to the function + >>> oct_to_decimal("e") + Traceback (most recent call last): + ... + ValueError: Non-octal value was passed to the function + >>> oct_to_decimal("8") + Traceback (most recent call last): + ... + ValueError: Non-octal value was passed to the function + >>> oct_to_decimal("-e") + Traceback (most recent call last): + ... + ValueError: Non-octal value was passed to the function + >>> oct_to_decimal("-8") + Traceback (most recent call last): + ... + ValueError: Non-octal value was passed to the function + >>> oct_to_decimal("1") + 1 + >>> oct_to_decimal("-1") + -1 >>> oct_to_decimal("12") 10 >>> oct_to_decimal(" 12 ") 10 >>> oct_to_decimal("-45") -37 + >>> oct_to_decimal("-") + Traceback (most recent call last): + ... + ValueError: Non-octal value was passed to the function + >>> oct_to_decimal("0") + 0 + >>> oct_to_decimal("-4055") + -2093 >>> oct_to_decimal("2-0Fm") Traceback (most recent call last): ... diff --git a/sorts/iterative_merge_sort.py b/sorts/iterative_merge_sort.py index 5ee0badab..327974fa6 100644 --- a/sorts/iterative_merge_sort.py +++ b/sorts/iterative_merge_sort.py @@ -32,6 +32,22 @@ def iter_merge_sort(input_list: list) -> list: >>> iter_merge_sort([5, 9, 8, 7, 1, 2, 7]) [1, 2, 5, 7, 7, 8, 9] + >>> iter_merge_sort([1]) + [1] + >>> iter_merge_sort([2, 1]) + [1, 2] + >>> iter_merge_sort([2, 1, 3]) + [1, 2, 3] + >>> iter_merge_sort([4, 3, 2, 1]) + [1, 2, 3, 4] + >>> iter_merge_sort([5, 4, 3, 2, 1]) + [1, 2, 3, 4, 5] + >>> iter_merge_sort(['c', 'b', 'a']) + ['a', 'b', 'c'] + >>> iter_merge_sort([0.3, 0.2, 0.1]) + [0.1, 0.2, 0.3] + >>> iter_merge_sort(['dep', 'dang', 'trai']) + ['dang', 'dep', 'trai'] >>> iter_merge_sort([6]) [6] >>> iter_merge_sort([]) @@ -51,7 +67,7 @@ def iter_merge_sort(input_list: list) -> list: # iteration for two-way merging p = 2 - while p < len(input_list): + while p <= len(input_list): # getting low, high and middle value for merge-sort of single list for i in range(0, len(input_list), p): low = i @@ -62,6 +78,7 @@ def iter_merge_sort(input_list: list) -> list: if p * 2 >= len(input_list): mid = i input_list = merge(input_list, 0, mid, len(input_list) - 1) + break p *= 2 return input_list @@ -69,5 +86,8 @@ def iter_merge_sort(input_list: list) -> list: if __name__ == "__main__": user_input = input("Enter numbers separated by a comma:\n").strip() - unsorted = [int(item.strip()) for item in user_input.split(",")] + if user_input == "": + unsorted = [] + else: + unsorted = [int(item.strip()) for item in user_input.split(",")] print(iter_merge_sort(unsorted)) From a28ad3f759ba4b69e58e65db60eb26f0fd9756cc Mon Sep 17 00:00:00 2001 From: Luke Banicevic <60857954+banaboi@users.noreply.github.com> Date: Tue, 24 May 2022 11:18:50 +1000 Subject: [PATCH 271/726] Add Microsoft Excel Column Title to Column Number Conversion (#4849) * Added excel column title to number algorithm as part of conversions * Renamed file to better reflect algorithm function * Removed duplicate file * Update excel_title_to_column.py * Update excel_title_to_column.py Co-authored-by: John Law --- conversions/excel_title_to_column.py | 33 ++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 conversions/excel_title_to_column.py diff --git a/conversions/excel_title_to_column.py b/conversions/excel_title_to_column.py new file mode 100644 index 000000000..d77031ec2 --- /dev/null +++ b/conversions/excel_title_to_column.py @@ -0,0 +1,33 @@ +def excel_title_to_column(column_title: str) -> int: + """ + Given a string column_title that represents + the column title in an Excel sheet, return + its corresponding column number. + + >>> excel_title_to_column("A") + 1 + >>> excel_title_to_column("B") + 2 + >>> excel_title_to_column("AB") + 28 + >>> excel_title_to_column("Z") + 26 + """ + assert column_title.isupper() + answer = 0 + index = len(column_title) - 1 + power = 0 + + while index >= 0: + value = (ord(column_title[index]) - 64) * pow(26, power) + answer += value + power += 1 + index -= 1 + + return answer + + +if __name__ == "__main__": + from doctest import testmod + + testmod() From de4d98081b9f9ba4bc6447ef20bb8fed329b343e Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Tue, 24 May 2022 04:20:47 +0300 Subject: [PATCH 272/726] Improve Project Euler problem 145 solution 1 (#6141) * updating DIRECTORY.md * Improve solution * updating DIRECTORY.md * Fix Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 9 +++++++++ project_euler/problem_145/sol1.py | 7 ++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index eeea22e47..64a87dc66 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -112,6 +112,7 @@ * [Cnn Classification](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/cnn_classification.py) * [Flip Augmentation](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/flip_augmentation.py) * [Harris Corner](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/harris_corner.py) + * [Horn Schunck](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/horn_schunck.py) * [Mean Threshold](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/mean_threshold.py) * [Mosaic Augmentation](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/mosaic_augmentation.py) * [Pooling Functions](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/pooling_functions.py) @@ -131,6 +132,7 @@ * [Molecular Chemistry](https://github.com/TheAlgorithms/Python/blob/master/conversions/molecular_chemistry.py) * [Octal To Decimal](https://github.com/TheAlgorithms/Python/blob/master/conversions/octal_to_decimal.py) * [Prefix Conversions](https://github.com/TheAlgorithms/Python/blob/master/conversions/prefix_conversions.py) + * [Prefix Conversions String](https://github.com/TheAlgorithms/Python/blob/master/conversions/prefix_conversions_string.py) * [Pressure Conversions](https://github.com/TheAlgorithms/Python/blob/master/conversions/pressure_conversions.py) * [Rgb Hsv Conversion](https://github.com/TheAlgorithms/Python/blob/master/conversions/rgb_hsv_conversion.py) * [Roman Numerals](https://github.com/TheAlgorithms/Python/blob/master/conversions/roman_numerals.py) @@ -529,6 +531,7 @@ * [Perfect Square](https://github.com/TheAlgorithms/Python/blob/master/maths/perfect_square.py) * [Persistence](https://github.com/TheAlgorithms/Python/blob/master/maths/persistence.py) * [Pi Monte Carlo Estimation](https://github.com/TheAlgorithms/Python/blob/master/maths/pi_monte_carlo_estimation.py) + * [Points Are Collinear 3D](https://github.com/TheAlgorithms/Python/blob/master/maths/points_are_collinear_3d.py) * [Pollard Rho](https://github.com/TheAlgorithms/Python/blob/master/maths/pollard_rho.py) * [Polynomial Evaluation](https://github.com/TheAlgorithms/Python/blob/master/maths/polynomial_evaluation.py) * [Power Using Recursion](https://github.com/TheAlgorithms/Python/blob/master/maths/power_using_recursion.py) @@ -619,6 +622,7 @@ * [Tower Of Hanoi](https://github.com/TheAlgorithms/Python/blob/master/other/tower_of_hanoi.py) ## Physics + * [Horizontal Projectile Motion](https://github.com/TheAlgorithms/Python/blob/master/physics/horizontal_projectile_motion.py) * [N Body Simulation](https://github.com/TheAlgorithms/Python/blob/master/physics/n_body_simulation.py) * [Newtons Second Law Of Motion](https://github.com/TheAlgorithms/Python/blob/master/physics/newtons_second_law_of_motion.py) @@ -833,6 +837,8 @@ * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_101/sol1.py) * Problem 102 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_102/sol1.py) + * Problem 104 + * [Sol](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_104/sol.py) * Problem 107 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_107/sol1.py) * Problem 109 @@ -857,6 +863,8 @@ * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_135/sol1.py) * Problem 144 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_144/sol1.py) + * Problem 145 + * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_145/sol1.py) * Problem 173 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_173/sol1.py) * Problem 174 @@ -990,6 +998,7 @@ * [Manacher](https://github.com/TheAlgorithms/Python/blob/master/strings/manacher.py) * [Min Cost String Conversion](https://github.com/TheAlgorithms/Python/blob/master/strings/min_cost_string_conversion.py) * [Naive String Search](https://github.com/TheAlgorithms/Python/blob/master/strings/naive_string_search.py) + * [Ngram](https://github.com/TheAlgorithms/Python/blob/master/strings/ngram.py) * [Palindrome](https://github.com/TheAlgorithms/Python/blob/master/strings/palindrome.py) * [Prefix Function](https://github.com/TheAlgorithms/Python/blob/master/strings/prefix_function.py) * [Rabin Karp](https://github.com/TheAlgorithms/Python/blob/master/strings/rabin_karp.py) diff --git a/project_euler/problem_145/sol1.py b/project_euler/problem_145/sol1.py index 82e2ea79b..09d8daff5 100644 --- a/project_euler/problem_145/sol1.py +++ b/project_euler/problem_145/sol1.py @@ -23,10 +23,11 @@ def odd_digits(num: int) -> bool: >>> odd_digits(135797531) True """ - num_str = str(num) - for i in ["0", "2", "4", "6", "8"]: - if i in num_str: + while num > 0: + digit = num % 10 + if digit % 2 == 0: return False + num //= 10 return True From b8fdd81f286e2435d058750d35420cb5a89f470d Mon Sep 17 00:00:00 2001 From: Raine Legary <64663183+Rainethhh@users.noreply.github.com> Date: Tue, 24 May 2022 23:49:54 -0600 Subject: [PATCH 273/726] Add minmum path sum (#5882) * commit on 'shortest_path_sum' * minimum_path_sum updated * commit to 'minimum_path_sum' * added description to minimum_path_sum * bot requirements fixed for * Update minimum_path_sum.py * Update minimum_path_sum.py Co-authored-by: John Law --- graphs/minimum_path_sum.py | 63 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 graphs/minimum_path_sum.py diff --git a/graphs/minimum_path_sum.py b/graphs/minimum_path_sum.py new file mode 100644 index 000000000..df1e545df --- /dev/null +++ b/graphs/minimum_path_sum.py @@ -0,0 +1,63 @@ +def min_path_sum(grid: list) -> int: + """ + Find the path from top left to bottom right of array of numbers + with the lowest possible sum and return the sum along this path. + >>> min_path_sum([ + ... [1, 3, 1], + ... [1, 5, 1], + ... [4, 2, 1], + ... ]) + 7 + + >>> min_path_sum([ + ... [1, 0, 5, 6, 7], + ... [8, 9, 0, 4, 2], + ... [4, 4, 4, 5, 1], + ... [9, 6, 3, 1, 0], + ... [8, 4, 3, 2, 7], + ... ]) + 20 + + >>> min_path_sum(None) + Traceback (most recent call last): + ... + TypeError: The grid does not contain the appropriate information + + >>> min_path_sum([[]]) + Traceback (most recent call last): + ... + TypeError: The grid does not contain the appropriate information + """ + + if not grid or not grid[0]: + raise TypeError("The grid does not contain the appropriate information") + + for cell_n in range(1, len(grid[0])): + grid[0][cell_n] += grid[0][cell_n - 1] + row_above = grid[0] + + for row_n in range(1, len(grid)): + current_row = grid[row_n] + grid[row_n] = fill_row(current_row, row_above) + row_above = grid[row_n] + + return grid[-1][-1] + + +def fill_row(current_row: list, row_above: list) -> list: + """ + >>> fill_row([2, 2, 2], [1, 2, 3]) + [3, 4, 5] + """ + + current_row[0] += row_above[0] + for cell_n in range(1, len(current_row)): + current_row[cell_n] += min(current_row[cell_n - 1], row_above[cell_n]) + + return current_row + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 8004671b984a58a86eb010e3add16f7268ed56b8 Mon Sep 17 00:00:00 2001 From: kugiyasan <44143656+kugiyasan@users.noreply.github.com> Date: Thu, 26 May 2022 15:24:23 -0400 Subject: [PATCH 274/726] Add Project Euler 68 Solution (#5552) * updating DIRECTORY.md * Project Euler 68 Solution * updating DIRECTORY.md * Project Euler 68 Fixed doctests, now at 93% coverage * Update sol1.py Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: kugiyasan Co-authored-by: John Law --- DIRECTORY.md | 2 + project_euler/problem_068/__init__.py | 0 project_euler/problem_068/sol1.py | 133 ++++++++++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 project_euler/problem_068/__init__.py create mode 100644 project_euler/problem_068/sol1.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 64a87dc66..f4a470c12 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -793,6 +793,8 @@ * Problem 067 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_067/sol1.py) * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_067/sol2.py) + * Problem 068 + * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_068/sol1.py) * Problem 069 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_069/sol1.py) * Problem 070 diff --git a/project_euler/problem_068/__init__.py b/project_euler/problem_068/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_068/sol1.py b/project_euler/problem_068/sol1.py new file mode 100644 index 000000000..772be359f --- /dev/null +++ b/project_euler/problem_068/sol1.py @@ -0,0 +1,133 @@ +""" +Project Euler Problem 68: https://projecteuler.net/problem=68 + +Magic 5-gon ring + +Problem Statement: +Consider the following "magic" 3-gon ring, +filled with the numbers 1 to 6, and each line adding to nine. + + 4 + \ + 3 + / \ + 1 - 2 - 6 + / + 5 + +Working clockwise, and starting from the group of three +with the numerically lowest external node (4,3,2 in this example), +each solution can be described uniquely. +For example, the above solution can be described by the set: 4,3,2; 6,2,1; 5,1,3. + +It is possible to complete the ring with four different totals: 9, 10, 11, and 12. +There are eight solutions in total. +Total Solution Set +9 4,2,3; 5,3,1; 6,1,2 +9 4,3,2; 6,2,1; 5,1,3 +10 2,3,5; 4,5,1; 6,1,3 +10 2,5,3; 6,3,1; 4,1,5 +11 1,4,6; 3,6,2; 5,2,4 +11 1,6,4; 5,4,2; 3,2,6 +12 1,5,6; 2,6,4; 3,4,5 +12 1,6,5; 3,5,4; 2,4,6 + +By concatenating each group it is possible to form 9-digit strings; +the maximum string for a 3-gon ring is 432621513. + +Using the numbers 1 to 10, and depending on arrangements, +it is possible to form 16- and 17-digit strings. +What is the maximum 16-digit string for a "magic" 5-gon ring? +""" + +from itertools import permutations + + +def solution(gon_side: int = 5) -> int: + """ + Find the maximum number for a "magic" gon_side-gon ring + + The gon_side parameter should be in the range [3, 5], + other side numbers aren't tested + + >>> solution(3) + 432621513 + >>> solution(4) + 426561813732 + >>> solution() + 6531031914842725 + >>> solution(6) + Traceback (most recent call last): + ValueError: gon_side must be in the range [3, 5] + """ + if gon_side < 3 or gon_side > 5: + raise ValueError("gon_side must be in the range [3, 5]") + + # Since it's 16, we know 10 is on the outer ring + # Put the big numbers at the end so that they are never the first number + small_numbers = list(range(gon_side + 1, 0, -1)) + big_numbers = list(range(gon_side + 2, gon_side * 2 + 1)) + + for perm in permutations(small_numbers + big_numbers): + numbers = generate_gon_ring(gon_side, list(perm)) + if is_magic_gon(numbers): + return int("".join(str(n) for n in numbers)) + + raise ValueError(f"Magic {gon_side}-gon ring is impossible") + + +def generate_gon_ring(gon_side: int, perm: list[int]) -> list[int]: + """ + Generate a gon_side-gon ring from a permutation state + The permutation state is the ring, but every duplicate is removed + + >>> generate_gon_ring(3, [4, 2, 3, 5, 1, 6]) + [4, 2, 3, 5, 3, 1, 6, 1, 2] + >>> generate_gon_ring(5, [6, 5, 4, 3, 2, 1, 7, 8, 9, 10]) + [6, 5, 4, 3, 4, 2, 1, 2, 7, 8, 7, 9, 10, 9, 5] + """ + result = [0] * (gon_side * 3) + result[0:3] = perm[0:3] + perm.append(perm[1]) + + magic_number = 1 if gon_side < 5 else 2 + + for i in range(1, len(perm) // 3 + magic_number): + result[3 * i] = perm[2 * i + 1] + result[3 * i + 1] = result[3 * i - 1] + result[3 * i + 2] = perm[2 * i + 2] + + return result + + +def is_magic_gon(numbers: list[int]) -> bool: + """ + Check if the solution set is a magic n-gon ring + Check that the first number is the smallest number on the outer ring + Take a list, and check if the sum of each 3 numbers chunk is equal to the same total + + >>> is_magic_gon([4, 2, 3, 5, 3, 1, 6, 1, 2]) + True + >>> is_magic_gon([4, 3, 2, 6, 2, 1, 5, 1, 3]) + True + >>> is_magic_gon([2, 3, 5, 4, 5, 1, 6, 1, 3]) + True + >>> is_magic_gon([1, 2, 3, 4, 5, 6, 7, 8, 9]) + False + >>> is_magic_gon([1]) + Traceback (most recent call last): + ValueError: a gon ring should have a length that is a multiple of 3 + """ + if len(numbers) % 3 != 0: + raise ValueError("a gon ring should have a length that is a multiple of 3") + + if min(numbers[::3]) != numbers[0]: + return False + + total = sum(numbers[:3]) + + return all(sum(numbers[i : i + 3]) == total for i in range(3, len(numbers), 3)) + + +if __name__ == "__main__": + print(solution()) From a44afc9b7dd74f85f0c54ebdd8f0135b6bc38dc9 Mon Sep 17 00:00:00 2001 From: DongJoon Cha <81581204+dongjji@users.noreply.github.com> Date: Sun, 5 Jun 2022 01:41:52 +0900 Subject: [PATCH 275/726] Add Multi-Level-Feedback-Queue scheduling algorithm (#6165) * Add Multi-Level-Feedback-Queue scheduling algorithm * fix type hint annotation for pre-commit * Update scheduling/multi_level_feedback_queue.py Co-authored-by: John Law * Update scheduling/multi_level_feedback_queue.py Co-authored-by: John Law * Update scheduling/multi_level_feedback_queue.py Co-authored-by: John Law * Update scheduling/multi_level_feedback_queue.py * Update scheduling/multi_level_feedback_queue.py Co-authored-by: John Law Co-authored-by: John Law --- scheduling/multi_level_feedback_queue.py | 312 +++++++++++++++++++++++ 1 file changed, 312 insertions(+) create mode 100644 scheduling/multi_level_feedback_queue.py diff --git a/scheduling/multi_level_feedback_queue.py b/scheduling/multi_level_feedback_queue.py new file mode 100644 index 000000000..95ca827e0 --- /dev/null +++ b/scheduling/multi_level_feedback_queue.py @@ -0,0 +1,312 @@ +from collections import deque + + +class Process: + def __init__(self, process_name: str, arrival_time: int, burst_time: int) -> None: + self.process_name = process_name # process name + self.arrival_time = arrival_time # arrival time of the process + # completion time of finished process or last interrupted time + self.stop_time = arrival_time + self.burst_time = burst_time # remaining burst time + self.waiting_time = 0 # total time of the process wait in ready queue + self.turnaround_time = 0 # time from arrival time to completion time + + +class MLFQ: + """ + MLFQ(Multi Level Feedback Queue) + https://en.wikipedia.org/wiki/Multilevel_feedback_queue + MLFQ has a lot of queues that have different priority + In this MLFQ, + The first Queue(0) to last second Queue(N-2) of MLFQ have Round Robin Algorithm + The last Queue(N-1) has First Come, First Served Algorithm + """ + + def __init__( + self, + number_of_queues: int, + time_slices: list[int], + queue: deque[Process], + current_time: int, + ) -> None: + # total number of mlfq's queues + self.number_of_queues = number_of_queues + # time slice of queues that round robin algorithm applied + self.time_slices = time_slices + # unfinished process is in this ready_queue + self.ready_queue = queue + # current time + self.current_time = current_time + # finished process is in this sequence queue + self.finish_queue: deque[Process] = deque() + + def calculate_sequence_of_finish_queue(self) -> list[str]: + """ + This method returns the sequence of finished processes + >>> P1 = Process("P1", 0, 53) + >>> P2 = Process("P2", 0, 17) + >>> P3 = Process("P3", 0, 68) + >>> P4 = Process("P4", 0, 24) + >>> mlfq = MLFQ(3, [17, 25], deque([P1, P2, P3, P4]), 0) + >>> _ = mlfq.multi_level_feedback_queue() + >>> mlfq.calculate_sequence_of_finish_queue() + ['P2', 'P4', 'P1', 'P3'] + """ + sequence = [] + for i in range(len(self.finish_queue)): + sequence.append(self.finish_queue[i].process_name) + return sequence + + def calculate_waiting_time(self, queue: list[Process]) -> list[int]: + """ + This method calculates waiting time of processes + >>> P1 = Process("P1", 0, 53) + >>> P2 = Process("P2", 0, 17) + >>> P3 = Process("P3", 0, 68) + >>> P4 = Process("P4", 0, 24) + >>> mlfq = MLFQ(3, [17, 25], deque([P1, P2, P3, P4]), 0) + >>> _ = mlfq.multi_level_feedback_queue() + >>> mlfq.calculate_waiting_time([P1, P2, P3, P4]) + [83, 17, 94, 101] + """ + waiting_times = [] + for i in range(len(queue)): + waiting_times.append(queue[i].waiting_time) + return waiting_times + + def calculate_turnaround_time(self, queue: list[Process]) -> list[int]: + """ + This method calculates turnaround time of processes + >>> P1 = Process("P1", 0, 53) + >>> P2 = Process("P2", 0, 17) + >>> P3 = Process("P3", 0, 68) + >>> P4 = Process("P4", 0, 24) + >>> mlfq = MLFQ(3, [17, 25], deque([P1, P2, P3, P4]), 0) + >>> _ = mlfq.multi_level_feedback_queue() + >>> mlfq.calculate_turnaround_time([P1, P2, P3, P4]) + [136, 34, 162, 125] + """ + turnaround_times = [] + for i in range(len(queue)): + turnaround_times.append(queue[i].turnaround_time) + return turnaround_times + + def calculate_completion_time(self, queue: list[Process]) -> list[int]: + """ + This method calculates completion time of processes + >>> P1 = Process("P1", 0, 53) + >>> P2 = Process("P2", 0, 17) + >>> P3 = Process("P3", 0, 68) + >>> P4 = Process("P4", 0, 24) + >>> mlfq = MLFQ(3, [17, 25], deque([P1, P2, P3, P4]), 0) + >>> _ = mlfq.multi_level_feedback_queue() + >>> mlfq.calculate_turnaround_time([P1, P2, P3, P4]) + [136, 34, 162, 125] + """ + completion_times = [] + for i in range(len(queue)): + completion_times.append(queue[i].stop_time) + return completion_times + + def calculate_remaining_burst_time_of_processes( + self, queue: deque[Process] + ) -> list[int]: + """ + This method calculate remaining burst time of processes + >>> P1 = Process("P1", 0, 53) + >>> P2 = Process("P2", 0, 17) + >>> P3 = Process("P3", 0, 68) + >>> P4 = Process("P4", 0, 24) + >>> mlfq = MLFQ(3, [17, 25], deque([P1, P2, P3, P4]), 0) + >>> finish_queue, ready_queue = mlfq.round_robin(deque([P1, P2, P3, P4]), 17) + >>> mlfq.calculate_remaining_burst_time_of_processes(mlfq.finish_queue) + [0] + >>> mlfq.calculate_remaining_burst_time_of_processes(ready_queue) + [36, 51, 7] + >>> finish_queue, ready_queue = mlfq.round_robin(ready_queue, 25) + >>> mlfq.calculate_remaining_burst_time_of_processes(mlfq.finish_queue) + [0, 0] + >>> mlfq.calculate_remaining_burst_time_of_processes(ready_queue) + [11, 26] + """ + return [q.burst_time for q in queue] + + def update_waiting_time(self, process: Process) -> int: + """ + This method updates waiting times of unfinished processes + >>> P1 = Process("P1", 0, 53) + >>> P2 = Process("P2", 0, 17) + >>> P3 = Process("P3", 0, 68) + >>> P4 = Process("P4", 0, 24) + >>> mlfq = MLFQ(3, [17, 25], deque([P1, P2, P3, P4]), 0) + >>> mlfq.current_time = 10 + >>> P1.stop_time = 5 + >>> mlfq.update_waiting_time(P1) + 5 + """ + process.waiting_time += self.current_time - process.stop_time + return process.waiting_time + + def first_come_first_served(self, ready_queue: deque[Process]) -> deque[Process]: + """ + FCFS(First Come, First Served) + FCFS will be applied to MLFQ's last queue + A first came process will be finished at first + >>> P1 = Process("P1", 0, 53) + >>> P2 = Process("P2", 0, 17) + >>> P3 = Process("P3", 0, 68) + >>> P4 = Process("P4", 0, 24) + >>> mlfq = MLFQ(3, [17, 25], deque([P1, P2, P3, P4]), 0) + >>> _ = mlfq.first_come_first_served(mlfq.ready_queue) + >>> mlfq.calculate_sequence_of_finish_queue() + ['P1', 'P2', 'P3', 'P4'] + """ + finished: deque[Process] = deque() # sequence deque of finished process + while len(ready_queue) != 0: + cp = ready_queue.popleft() # current process + + # if process's arrival time is later than current time, update current time + if self.current_time < cp.arrival_time: + self.current_time += cp.arrival_time + + # update waiting time of current process + self.update_waiting_time(cp) + # update current time + self.current_time += cp.burst_time + # finish the process and set the process's burst-time 0 + cp.burst_time = 0 + # set the process's turnaround time because it is finished + cp.turnaround_time = self.current_time - cp.arrival_time + # set the completion time + cp.stop_time = self.current_time + # add the process to queue that has finished queue + finished.append(cp) + + self.finish_queue.extend(finished) # add finished process to finish queue + # FCFS will finish all remaining processes + return finished + + def round_robin( + self, ready_queue: deque[Process], time_slice: int + ) -> tuple[deque[Process], deque[Process]]: + """ + RR(Round Robin) + RR will be applied to MLFQ's all queues except last queue + All processes can't use CPU for time more than time_slice + If the process consume CPU up to time_slice, it will go back to ready queue + >>> P1 = Process("P1", 0, 53) + >>> P2 = Process("P2", 0, 17) + >>> P3 = Process("P3", 0, 68) + >>> P4 = Process("P4", 0, 24) + >>> mlfq = MLFQ(3, [17, 25], deque([P1, P2, P3, P4]), 0) + >>> finish_queue, ready_queue = mlfq.round_robin(mlfq.ready_queue, 17) + >>> mlfq.calculate_sequence_of_finish_queue() + ['P2'] + """ + finished: deque[Process] = deque() # sequence deque of terminated process + # just for 1 cycle and unfinished processes will go back to queue + for i in range(len(ready_queue)): + cp = ready_queue.popleft() # current process + + # if process's arrival time is later than current time, update current time + if self.current_time < cp.arrival_time: + self.current_time += cp.arrival_time + + # update waiting time of unfinished processes + self.update_waiting_time(cp) + # if the burst time of process is bigger than time-slice + if cp.burst_time > time_slice: + # use CPU for only time-slice + self.current_time += time_slice + # update remaining burst time + cp.burst_time -= time_slice + # update end point time + cp.stop_time = self.current_time + # locate the process behind the queue because it is not finished + ready_queue.append(cp) + else: + # use CPU for remaining burst time + self.current_time += cp.burst_time + # set burst time 0 because the process is finished + cp.burst_time = 0 + # set the finish time + cp.stop_time = self.current_time + # update the process' turnaround time because it is finished + cp.turnaround_time = self.current_time - cp.arrival_time + # add the process to queue that has finished queue + finished.append(cp) + + self.finish_queue.extend(finished) # add finished process to finish queue + # return finished processes queue and remaining processes queue + return finished, ready_queue + + def multi_level_feedback_queue(self) -> deque[Process]: + """ + MLFQ(Multi Level Feedback Queue) + >>> P1 = Process("P1", 0, 53) + >>> P2 = Process("P2", 0, 17) + >>> P3 = Process("P3", 0, 68) + >>> P4 = Process("P4", 0, 24) + >>> mlfq = MLFQ(3, [17, 25], deque([P1, P2, P3, P4]), 0) + >>> finish_queue = mlfq.multi_level_feedback_queue() + >>> mlfq.calculate_sequence_of_finish_queue() + ['P2', 'P4', 'P1', 'P3'] + """ + + # all queues except last one have round_robin algorithm + for i in range(self.number_of_queues - 1): + finished, self.ready_queue = self.round_robin( + self.ready_queue, self.time_slices[i] + ) + # the last queue has first_come_first_served algorithm + self.first_come_first_served(self.ready_queue) + + return self.finish_queue + + +if __name__ == "__main__": + import doctest + + P1 = Process("P1", 0, 53) + P2 = Process("P2", 0, 17) + P3 = Process("P3", 0, 68) + P4 = Process("P4", 0, 24) + number_of_queues = 3 + time_slices = [17, 25] + queue = deque([P1, P2, P3, P4]) + + if len(time_slices) != number_of_queues - 1: + exit() + + doctest.testmod(extraglobs={"queue": deque([P1, P2, P3, P4])}) + + P1 = Process("P1", 0, 53) + P2 = Process("P2", 0, 17) + P3 = Process("P3", 0, 68) + P4 = Process("P4", 0, 24) + number_of_queues = 3 + time_slices = [17, 25] + queue = deque([P1, P2, P3, P4]) + mlfq = MLFQ(number_of_queues, time_slices, queue, 0) + finish_queue = mlfq.multi_level_feedback_queue() + + # print total waiting times of processes(P1, P2, P3, P4) + print( + f"waiting time:\ + \t\t\t{MLFQ.calculate_waiting_time(mlfq, [P1, P2, P3, P4])}" + ) + # print completion times of processes(P1, P2, P3, P4) + print( + f"completion time:\ + \t\t{MLFQ.calculate_completion_time(mlfq, [P1, P2, P3, P4])}" + ) + # print total turnaround times of processes(P1, P2, P3, P4) + print( + f"turnaround time:\ + \t\t{MLFQ.calculate_turnaround_time(mlfq, [P1, P2, P3, P4])}" + ) + # print sequence of finished processes + print( + f"sequnece of finished processes:\ + {mlfq.calculate_sequence_of_finish_queue()}" + ) From c86aa72cfa0467bd9a5711d7b5a77ed8243e49f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=B9=88?= <76545238+Bynnn@users.noreply.github.com> Date: Tue, 7 Jun 2022 01:44:49 +0900 Subject: [PATCH 276/726] Create non_preemptive_shortest_job_first.py (#6169) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Create non_preemptive_shortest_job_first.py * 파일 위치 변경 * Delete non_preemptive_shortest_job_first.py * delete Korean comments * change comments, & to and, type annotation * type annotation * delete unnecessary comment --- .../non_preemptive_shortest_job_first.py | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 scheduling/non_preemptive_shortest_job_first.py diff --git a/scheduling/non_preemptive_shortest_job_first.py b/scheduling/non_preemptive_shortest_job_first.py new file mode 100644 index 000000000..96e571230 --- /dev/null +++ b/scheduling/non_preemptive_shortest_job_first.py @@ -0,0 +1,111 @@ +""" +Non-preemptive Shortest Job First +Shortest execution time process is chosen for the next execution. +https://www.guru99.com/shortest-job-first-sjf-scheduling.html +https://en.wikipedia.org/wiki/Shortest_job_next +""" + + +from __future__ import annotations + +from statistics import mean + + +def calculate_waitingtime( + arrival_time: list[int], burst_time: list[int], no_of_processes: int +) -> list[int]: + """ + Calculate the waiting time of each processes + + Return: The waiting time for each process. + >>> calculate_waitingtime([0,1,2], [10, 5, 8], 3) + [0, 9, 13] + >>> calculate_waitingtime([1,2,2,4], [4, 6, 3, 1], 4) + [0, 7, 4, 1] + >>> calculate_waitingtime([0,0,0], [12, 2, 10],3) + [12, 0, 2] + """ + + waiting_time = [0] * no_of_processes + remaining_time = [0] * no_of_processes + + # Initialize remaining_time to waiting_time. + + for i in range(no_of_processes): + remaining_time[i] = burst_time[i] + ready_process: list[int] = [] + + completed = 0 + total_time = 0 + + # When processes are not completed, + # A process whose arrival time has passed \ + # and has remaining execution time is put into the ready_process. + # The shortest process in the ready_process, target_process is executed. + + while completed != no_of_processes: + ready_process = [] + target_process = -1 + + for i in range(no_of_processes): + if (arrival_time[i] <= total_time) and (remaining_time[i] > 0): + ready_process.append(i) + + if len(ready_process) > 0: + target_process = ready_process[0] + for i in ready_process: + if remaining_time[i] < remaining_time[target_process]: + target_process = i + total_time += burst_time[target_process] + completed += 1 + remaining_time[target_process] = 0 + waiting_time[target_process] = ( + total_time - arrival_time[target_process] - burst_time[target_process] + ) + else: + total_time += 1 + + return waiting_time + + +def calculate_turnaroundtime( + burst_time: list[int], no_of_processes: int, waiting_time: list[int] +) -> list[int]: + """ + Calculate the turnaround time of each process. + + Return: The turnaround time for each process. + >>> calculate_turnaroundtime([0,1,2], 3, [0, 10, 15]) + [0, 11, 17] + >>> calculate_turnaroundtime([1,2,2,4], 4, [1, 8, 5, 4]) + [2, 10, 7, 8] + >>> calculate_turnaroundtime([0,0,0], 3, [12, 0, 2]) + [12, 0, 2] + """ + + turn_around_time = [0] * no_of_processes + for i in range(no_of_processes): + turn_around_time[i] = burst_time[i] + waiting_time[i] + return turn_around_time + + +if __name__ == "__main__": + print("[TEST CASE 01]") + + no_of_processes = 4 + burst_time = [2, 5, 3, 7] + arrival_time = [0, 0, 0, 0] + waiting_time = calculate_waitingtime(arrival_time, burst_time, no_of_processes) + turn_around_time = calculate_turnaroundtime( + burst_time, no_of_processes, waiting_time + ) + + # Printing the Result + print("PID\tBurst Time\tArrival Time\tWaiting Time\tTurnaround Time") + for i, process_ID in enumerate(list(range(1, 5))): + print( + f"{process_ID}\t{burst_time[i]}\t\t\t{arrival_time[i]}\t\t\t\t" + f"{waiting_time[i]}\t\t\t\t{turn_around_time[i]}" + ) + print(f"\nAverage waiting time = {mean(waiting_time):.5f}") + print(f"Average turnaround time = {mean(turn_around_time):.5f}") From 69cde43ca1e78980922adaf6b852008840d52e14 Mon Sep 17 00:00:00 2001 From: Vcrostin <52068696+Vcrostin@users.noreply.github.com> Date: Wed, 22 Jun 2022 07:01:05 +0300 Subject: [PATCH 277/726] make DIRECTORY.md paths relative Fixes (#6179) (#6190) --- DIRECTORY.md | 1658 +++++++++++++++++---------------- scripts/build_directory_md.py | 4 +- 2 files changed, 833 insertions(+), 829 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index f4a470c12..d30e275d0 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -1,1049 +1,1055 @@ ## Arithmetic Analysis - * [Bisection](https://github.com/TheAlgorithms/Python/blob/master/arithmetic_analysis/bisection.py) - * [Gaussian Elimination](https://github.com/TheAlgorithms/Python/blob/master/arithmetic_analysis/gaussian_elimination.py) - * [In Static Equilibrium](https://github.com/TheAlgorithms/Python/blob/master/arithmetic_analysis/in_static_equilibrium.py) - * [Intersection](https://github.com/TheAlgorithms/Python/blob/master/arithmetic_analysis/intersection.py) - * [Jacobi Iteration Method](https://github.com/TheAlgorithms/Python/blob/master/arithmetic_analysis/jacobi_iteration_method.py) - * [Lu Decomposition](https://github.com/TheAlgorithms/Python/blob/master/arithmetic_analysis/lu_decomposition.py) - * [Newton Forward Interpolation](https://github.com/TheAlgorithms/Python/blob/master/arithmetic_analysis/newton_forward_interpolation.py) - * [Newton Method](https://github.com/TheAlgorithms/Python/blob/master/arithmetic_analysis/newton_method.py) - * [Newton Raphson](https://github.com/TheAlgorithms/Python/blob/master/arithmetic_analysis/newton_raphson.py) - * [Secant Method](https://github.com/TheAlgorithms/Python/blob/master/arithmetic_analysis/secant_method.py) + * [Bisection](arithmetic_analysis/bisection.py) + * [Gaussian Elimination](arithmetic_analysis/gaussian_elimination.py) + * [In Static Equilibrium](arithmetic_analysis/in_static_equilibrium.py) + * [Intersection](arithmetic_analysis/intersection.py) + * [Jacobi Iteration Method](arithmetic_analysis/jacobi_iteration_method.py) + * [Lu Decomposition](arithmetic_analysis/lu_decomposition.py) + * [Newton Forward Interpolation](arithmetic_analysis/newton_forward_interpolation.py) + * [Newton Method](arithmetic_analysis/newton_method.py) + * [Newton Raphson](arithmetic_analysis/newton_raphson.py) + * [Secant Method](arithmetic_analysis/secant_method.py) ## Audio Filters - * [Butterworth Filter](https://github.com/TheAlgorithms/Python/blob/master/audio_filters/butterworth_filter.py) - * [Iir Filter](https://github.com/TheAlgorithms/Python/blob/master/audio_filters/iir_filter.py) - * [Show Response](https://github.com/TheAlgorithms/Python/blob/master/audio_filters/show_response.py) + * [Butterworth Filter](audio_filters/butterworth_filter.py) + * [Iir Filter](audio_filters/iir_filter.py) + * [Show Response](audio_filters/show_response.py) ## Backtracking - * [All Combinations](https://github.com/TheAlgorithms/Python/blob/master/backtracking/all_combinations.py) - * [All Permutations](https://github.com/TheAlgorithms/Python/blob/master/backtracking/all_permutations.py) - * [All Subsequences](https://github.com/TheAlgorithms/Python/blob/master/backtracking/all_subsequences.py) - * [Coloring](https://github.com/TheAlgorithms/Python/blob/master/backtracking/coloring.py) - * [Hamiltonian Cycle](https://github.com/TheAlgorithms/Python/blob/master/backtracking/hamiltonian_cycle.py) - * [Knight Tour](https://github.com/TheAlgorithms/Python/blob/master/backtracking/knight_tour.py) - * [Minimax](https://github.com/TheAlgorithms/Python/blob/master/backtracking/minimax.py) - * [N Queens](https://github.com/TheAlgorithms/Python/blob/master/backtracking/n_queens.py) - * [N Queens Math](https://github.com/TheAlgorithms/Python/blob/master/backtracking/n_queens_math.py) - * [Rat In Maze](https://github.com/TheAlgorithms/Python/blob/master/backtracking/rat_in_maze.py) - * [Sudoku](https://github.com/TheAlgorithms/Python/blob/master/backtracking/sudoku.py) - * [Sum Of Subsets](https://github.com/TheAlgorithms/Python/blob/master/backtracking/sum_of_subsets.py) + * [All Combinations](backtracking/all_combinations.py) + * [All Permutations](backtracking/all_permutations.py) + * [All Subsequences](backtracking/all_subsequences.py) + * [Coloring](backtracking/coloring.py) + * [Hamiltonian Cycle](backtracking/hamiltonian_cycle.py) + * [Knight Tour](backtracking/knight_tour.py) + * [Minimax](backtracking/minimax.py) + * [N Queens](backtracking/n_queens.py) + * [N Queens Math](backtracking/n_queens_math.py) + * [Rat In Maze](backtracking/rat_in_maze.py) + * [Sudoku](backtracking/sudoku.py) + * [Sum Of Subsets](backtracking/sum_of_subsets.py) ## Bit Manipulation - * [Binary And Operator](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_and_operator.py) - * [Binary Count Setbits](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_count_setbits.py) - * [Binary Count Trailing Zeros](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_count_trailing_zeros.py) - * [Binary Or Operator](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_or_operator.py) - * [Binary Shifts](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_shifts.py) - * [Binary Twos Complement](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_twos_complement.py) - * [Binary Xor Operator](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_xor_operator.py) - * [Count 1S Brian Kernighan Method](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/count_1s_brian_kernighan_method.py) - * [Count Number Of One Bits](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/count_number_of_one_bits.py) - * [Gray Code Sequence](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/gray_code_sequence.py) - * [Reverse Bits](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/reverse_bits.py) - * [Single Bit Manipulation Operations](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/single_bit_manipulation_operations.py) + * [Binary And Operator](bit_manipulation/binary_and_operator.py) + * [Binary Count Setbits](bit_manipulation/binary_count_setbits.py) + * [Binary Count Trailing Zeros](bit_manipulation/binary_count_trailing_zeros.py) + * [Binary Or Operator](bit_manipulation/binary_or_operator.py) + * [Binary Shifts](bit_manipulation/binary_shifts.py) + * [Binary Twos Complement](bit_manipulation/binary_twos_complement.py) + * [Binary Xor Operator](bit_manipulation/binary_xor_operator.py) + * [Count 1S Brian Kernighan Method](bit_manipulation/count_1s_brian_kernighan_method.py) + * [Count Number Of One Bits](bit_manipulation/count_number_of_one_bits.py) + * [Gray Code Sequence](bit_manipulation/gray_code_sequence.py) + * [Reverse Bits](bit_manipulation/reverse_bits.py) + * [Single Bit Manipulation Operations](bit_manipulation/single_bit_manipulation_operations.py) ## Blockchain - * [Chinese Remainder Theorem](https://github.com/TheAlgorithms/Python/blob/master/blockchain/chinese_remainder_theorem.py) - * [Diophantine Equation](https://github.com/TheAlgorithms/Python/blob/master/blockchain/diophantine_equation.py) - * [Modular Division](https://github.com/TheAlgorithms/Python/blob/master/blockchain/modular_division.py) + * [Chinese Remainder Theorem](blockchain/chinese_remainder_theorem.py) + * [Diophantine Equation](blockchain/diophantine_equation.py) + * [Modular Division](blockchain/modular_division.py) ## Boolean Algebra - * [Quine Mc Cluskey](https://github.com/TheAlgorithms/Python/blob/master/boolean_algebra/quine_mc_cluskey.py) + * [Quine Mc Cluskey](boolean_algebra/quine_mc_cluskey.py) ## Cellular Automata - * [Conways Game Of Life](https://github.com/TheAlgorithms/Python/blob/master/cellular_automata/conways_game_of_life.py) - * [Game Of Life](https://github.com/TheAlgorithms/Python/blob/master/cellular_automata/game_of_life.py) - * [Nagel Schrekenberg](https://github.com/TheAlgorithms/Python/blob/master/cellular_automata/nagel_schrekenberg.py) - * [One Dimensional](https://github.com/TheAlgorithms/Python/blob/master/cellular_automata/one_dimensional.py) + * [Conways Game Of Life](cellular_automata/conways_game_of_life.py) + * [Game Of Life](cellular_automata/game_of_life.py) + * [Nagel Schrekenberg](cellular_automata/nagel_schrekenberg.py) + * [One Dimensional](cellular_automata/one_dimensional.py) ## Ciphers - * [A1Z26](https://github.com/TheAlgorithms/Python/blob/master/ciphers/a1z26.py) - * [Affine Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/affine_cipher.py) - * [Atbash](https://github.com/TheAlgorithms/Python/blob/master/ciphers/atbash.py) - * [Baconian Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/baconian_cipher.py) - * [Base16](https://github.com/TheAlgorithms/Python/blob/master/ciphers/base16.py) - * [Base32](https://github.com/TheAlgorithms/Python/blob/master/ciphers/base32.py) - * [Base64](https://github.com/TheAlgorithms/Python/blob/master/ciphers/base64.py) - * [Base85](https://github.com/TheAlgorithms/Python/blob/master/ciphers/base85.py) - * [Beaufort Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/beaufort_cipher.py) - * [Bifid](https://github.com/TheAlgorithms/Python/blob/master/ciphers/bifid.py) - * [Brute Force Caesar Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/brute_force_caesar_cipher.py) - * [Caesar Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/caesar_cipher.py) - * [Cryptomath Module](https://github.com/TheAlgorithms/Python/blob/master/ciphers/cryptomath_module.py) - * [Decrypt Caesar With Chi Squared](https://github.com/TheAlgorithms/Python/blob/master/ciphers/decrypt_caesar_with_chi_squared.py) - * [Deterministic Miller Rabin](https://github.com/TheAlgorithms/Python/blob/master/ciphers/deterministic_miller_rabin.py) - * [Diffie](https://github.com/TheAlgorithms/Python/blob/master/ciphers/diffie.py) - * [Diffie Hellman](https://github.com/TheAlgorithms/Python/blob/master/ciphers/diffie_hellman.py) - * [Elgamal Key Generator](https://github.com/TheAlgorithms/Python/blob/master/ciphers/elgamal_key_generator.py) - * [Enigma Machine2](https://github.com/TheAlgorithms/Python/blob/master/ciphers/enigma_machine2.py) - * [Hill Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/hill_cipher.py) - * [Mixed Keyword Cypher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/mixed_keyword_cypher.py) - * [Mono Alphabetic Ciphers](https://github.com/TheAlgorithms/Python/blob/master/ciphers/mono_alphabetic_ciphers.py) - * [Morse Code](https://github.com/TheAlgorithms/Python/blob/master/ciphers/morse_code.py) - * [Onepad Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/onepad_cipher.py) - * [Playfair Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/playfair_cipher.py) - * [Polybius](https://github.com/TheAlgorithms/Python/blob/master/ciphers/polybius.py) - * [Porta Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/porta_cipher.py) - * [Rabin Miller](https://github.com/TheAlgorithms/Python/blob/master/ciphers/rabin_miller.py) - * [Rail Fence Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/rail_fence_cipher.py) - * [Rot13](https://github.com/TheAlgorithms/Python/blob/master/ciphers/rot13.py) - * [Rsa Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/rsa_cipher.py) - * [Rsa Factorization](https://github.com/TheAlgorithms/Python/blob/master/ciphers/rsa_factorization.py) - * [Rsa Key Generator](https://github.com/TheAlgorithms/Python/blob/master/ciphers/rsa_key_generator.py) - * [Shuffled Shift Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/shuffled_shift_cipher.py) - * [Simple Keyword Cypher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/simple_keyword_cypher.py) - * [Simple Substitution Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/simple_substitution_cipher.py) - * [Trafid Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/trafid_cipher.py) - * [Transposition Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/transposition_cipher.py) - * [Transposition Cipher Encrypt Decrypt File](https://github.com/TheAlgorithms/Python/blob/master/ciphers/transposition_cipher_encrypt_decrypt_file.py) - * [Vigenere Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/vigenere_cipher.py) - * [Xor Cipher](https://github.com/TheAlgorithms/Python/blob/master/ciphers/xor_cipher.py) + * [A1Z26](ciphers/a1z26.py) + * [Affine Cipher](ciphers/affine_cipher.py) + * [Atbash](ciphers/atbash.py) + * [Baconian Cipher](ciphers/baconian_cipher.py) + * [Base16](ciphers/base16.py) + * [Base32](ciphers/base32.py) + * [Base64](ciphers/base64.py) + * [Base85](ciphers/base85.py) + * [Beaufort Cipher](ciphers/beaufort_cipher.py) + * [Bifid](ciphers/bifid.py) + * [Brute Force Caesar Cipher](ciphers/brute_force_caesar_cipher.py) + * [Caesar Cipher](ciphers/caesar_cipher.py) + * [Cryptomath Module](ciphers/cryptomath_module.py) + * [Decrypt Caesar With Chi Squared](ciphers/decrypt_caesar_with_chi_squared.py) + * [Deterministic Miller Rabin](ciphers/deterministic_miller_rabin.py) + * [Diffie](ciphers/diffie.py) + * [Diffie Hellman](ciphers/diffie_hellman.py) + * [Elgamal Key Generator](ciphers/elgamal_key_generator.py) + * [Enigma Machine2](ciphers/enigma_machine2.py) + * [Hill Cipher](ciphers/hill_cipher.py) + * [Mixed Keyword Cypher](ciphers/mixed_keyword_cypher.py) + * [Mono Alphabetic Ciphers](ciphers/mono_alphabetic_ciphers.py) + * [Morse Code](ciphers/morse_code.py) + * [Onepad Cipher](ciphers/onepad_cipher.py) + * [Playfair Cipher](ciphers/playfair_cipher.py) + * [Polybius](ciphers/polybius.py) + * [Porta Cipher](ciphers/porta_cipher.py) + * [Rabin Miller](ciphers/rabin_miller.py) + * [Rail Fence Cipher](ciphers/rail_fence_cipher.py) + * [Rot13](ciphers/rot13.py) + * [Rsa Cipher](ciphers/rsa_cipher.py) + * [Rsa Factorization](ciphers/rsa_factorization.py) + * [Rsa Key Generator](ciphers/rsa_key_generator.py) + * [Shuffled Shift Cipher](ciphers/shuffled_shift_cipher.py) + * [Simple Keyword Cypher](ciphers/simple_keyword_cypher.py) + * [Simple Substitution Cipher](ciphers/simple_substitution_cipher.py) + * [Trafid Cipher](ciphers/trafid_cipher.py) + * [Transposition Cipher](ciphers/transposition_cipher.py) + * [Transposition Cipher Encrypt Decrypt File](ciphers/transposition_cipher_encrypt_decrypt_file.py) + * [Vigenere Cipher](ciphers/vigenere_cipher.py) + * [Xor Cipher](ciphers/xor_cipher.py) ## Compression - * [Burrows Wheeler](https://github.com/TheAlgorithms/Python/blob/master/compression/burrows_wheeler.py) - * [Huffman](https://github.com/TheAlgorithms/Python/blob/master/compression/huffman.py) - * [Lempel Ziv](https://github.com/TheAlgorithms/Python/blob/master/compression/lempel_ziv.py) - * [Lempel Ziv Decompress](https://github.com/TheAlgorithms/Python/blob/master/compression/lempel_ziv_decompress.py) - * [Peak Signal To Noise Ratio](https://github.com/TheAlgorithms/Python/blob/master/compression/peak_signal_to_noise_ratio.py) + * [Burrows Wheeler](compression/burrows_wheeler.py) + * [Huffman](compression/huffman.py) + * [Lempel Ziv](compression/lempel_ziv.py) + * [Lempel Ziv Decompress](compression/lempel_ziv_decompress.py) + * [Peak Signal To Noise Ratio](compression/peak_signal_to_noise_ratio.py) ## Computer Vision - * [Cnn Classification](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/cnn_classification.py) - * [Flip Augmentation](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/flip_augmentation.py) - * [Harris Corner](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/harris_corner.py) - * [Horn Schunck](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/horn_schunck.py) - * [Mean Threshold](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/mean_threshold.py) - * [Mosaic Augmentation](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/mosaic_augmentation.py) - * [Pooling Functions](https://github.com/TheAlgorithms/Python/blob/master/computer_vision/pooling_functions.py) + * [Cnn Classification](computer_vision/cnn_classification.py) + * [Flip Augmentation](computer_vision/flip_augmentation.py) + * [Harris Corner](computer_vision/harris_corner.py) + * [Horn Schunck](computer_vision/horn_schunck.py) + * [Mean Threshold](computer_vision/mean_threshold.py) + * [Mosaic Augmentation](computer_vision/mosaic_augmentation.py) + * [Pooling Functions](computer_vision/pooling_functions.py) ## Conversions - * [Binary To Decimal](https://github.com/TheAlgorithms/Python/blob/master/conversions/binary_to_decimal.py) - * [Binary To Hexadecimal](https://github.com/TheAlgorithms/Python/blob/master/conversions/binary_to_hexadecimal.py) - * [Binary To Octal](https://github.com/TheAlgorithms/Python/blob/master/conversions/binary_to_octal.py) - * [Decimal To Any](https://github.com/TheAlgorithms/Python/blob/master/conversions/decimal_to_any.py) - * [Decimal To Binary](https://github.com/TheAlgorithms/Python/blob/master/conversions/decimal_to_binary.py) - * [Decimal To Binary Recursion](https://github.com/TheAlgorithms/Python/blob/master/conversions/decimal_to_binary_recursion.py) - * [Decimal To Hexadecimal](https://github.com/TheAlgorithms/Python/blob/master/conversions/decimal_to_hexadecimal.py) - * [Decimal To Octal](https://github.com/TheAlgorithms/Python/blob/master/conversions/decimal_to_octal.py) - * [Hex To Bin](https://github.com/TheAlgorithms/Python/blob/master/conversions/hex_to_bin.py) - * [Hexadecimal To Decimal](https://github.com/TheAlgorithms/Python/blob/master/conversions/hexadecimal_to_decimal.py) - * [Length Conversion](https://github.com/TheAlgorithms/Python/blob/master/conversions/length_conversion.py) - * [Molecular Chemistry](https://github.com/TheAlgorithms/Python/blob/master/conversions/molecular_chemistry.py) - * [Octal To Decimal](https://github.com/TheAlgorithms/Python/blob/master/conversions/octal_to_decimal.py) - * [Prefix Conversions](https://github.com/TheAlgorithms/Python/blob/master/conversions/prefix_conversions.py) - * [Prefix Conversions String](https://github.com/TheAlgorithms/Python/blob/master/conversions/prefix_conversions_string.py) - * [Pressure Conversions](https://github.com/TheAlgorithms/Python/blob/master/conversions/pressure_conversions.py) - * [Rgb Hsv Conversion](https://github.com/TheAlgorithms/Python/blob/master/conversions/rgb_hsv_conversion.py) - * [Roman Numerals](https://github.com/TheAlgorithms/Python/blob/master/conversions/roman_numerals.py) - * [Temperature Conversions](https://github.com/TheAlgorithms/Python/blob/master/conversions/temperature_conversions.py) - * [Volume Conversions](https://github.com/TheAlgorithms/Python/blob/master/conversions/volume_conversions.py) - * [Weight Conversion](https://github.com/TheAlgorithms/Python/blob/master/conversions/weight_conversion.py) + * [Binary To Decimal](conversions/binary_to_decimal.py) + * [Binary To Hexadecimal](conversions/binary_to_hexadecimal.py) + * [Binary To Octal](conversions/binary_to_octal.py) + * [Decimal To Any](conversions/decimal_to_any.py) + * [Decimal To Binary](conversions/decimal_to_binary.py) + * [Decimal To Binary Recursion](conversions/decimal_to_binary_recursion.py) + * [Decimal To Hexadecimal](conversions/decimal_to_hexadecimal.py) + * [Decimal To Octal](conversions/decimal_to_octal.py) + * [Excel Title To Column](conversions/excel_title_to_column.py) + * [Hex To Bin](conversions/hex_to_bin.py) + * [Hexadecimal To Decimal](conversions/hexadecimal_to_decimal.py) + * [Length Conversion](conversions/length_conversion.py) + * [Molecular Chemistry](conversions/molecular_chemistry.py) + * [Octal To Decimal](conversions/octal_to_decimal.py) + * [Prefix Conversions](conversions/prefix_conversions.py) + * [Prefix Conversions String](conversions/prefix_conversions_string.py) + * [Pressure Conversions](conversions/pressure_conversions.py) + * [Rgb Hsv Conversion](conversions/rgb_hsv_conversion.py) + * [Roman Numerals](conversions/roman_numerals.py) + * [Temperature Conversions](conversions/temperature_conversions.py) + * [Volume Conversions](conversions/volume_conversions.py) + * [Weight Conversion](conversions/weight_conversion.py) ## Data Structures * Binary Tree - * [Avl Tree](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/avl_tree.py) - * [Basic Binary Tree](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/basic_binary_tree.py) - * [Binary Search Tree](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/binary_search_tree.py) - * [Binary Search Tree Recursive](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/binary_search_tree_recursive.py) - * [Binary Tree Mirror](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/binary_tree_mirror.py) - * [Binary Tree Traversals](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/binary_tree_traversals.py) - * [Fenwick Tree](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/fenwick_tree.py) - * [Lazy Segment Tree](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/lazy_segment_tree.py) - * [Lowest Common Ancestor](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/lowest_common_ancestor.py) - * [Merge Two Binary Trees](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/merge_two_binary_trees.py) - * [Non Recursive Segment Tree](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/non_recursive_segment_tree.py) - * [Number Of Possible Binary Trees](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/number_of_possible_binary_trees.py) - * [Red Black Tree](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/red_black_tree.py) - * [Segment Tree](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/segment_tree.py) - * [Segment Tree Other](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/segment_tree_other.py) - * [Treap](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/treap.py) - * [Wavelet Tree](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/wavelet_tree.py) + * [Avl Tree](data_structures/binary_tree/avl_tree.py) + * [Basic Binary Tree](data_structures/binary_tree/basic_binary_tree.py) + * [Binary Search Tree](data_structures/binary_tree/binary_search_tree.py) + * [Binary Search Tree Recursive](data_structures/binary_tree/binary_search_tree_recursive.py) + * [Binary Tree Mirror](data_structures/binary_tree/binary_tree_mirror.py) + * [Binary Tree Traversals](data_structures/binary_tree/binary_tree_traversals.py) + * [Fenwick Tree](data_structures/binary_tree/fenwick_tree.py) + * [Lazy Segment Tree](data_structures/binary_tree/lazy_segment_tree.py) + * [Lowest Common Ancestor](data_structures/binary_tree/lowest_common_ancestor.py) + * [Merge Two Binary Trees](data_structures/binary_tree/merge_two_binary_trees.py) + * [Non Recursive Segment Tree](data_structures/binary_tree/non_recursive_segment_tree.py) + * [Number Of Possible Binary Trees](data_structures/binary_tree/number_of_possible_binary_trees.py) + * [Red Black Tree](data_structures/binary_tree/red_black_tree.py) + * [Segment Tree](data_structures/binary_tree/segment_tree.py) + * [Segment Tree Other](data_structures/binary_tree/segment_tree_other.py) + * [Treap](data_structures/binary_tree/treap.py) + * [Wavelet Tree](data_structures/binary_tree/wavelet_tree.py) * Disjoint Set - * [Alternate Disjoint Set](https://github.com/TheAlgorithms/Python/blob/master/data_structures/disjoint_set/alternate_disjoint_set.py) - * [Disjoint Set](https://github.com/TheAlgorithms/Python/blob/master/data_structures/disjoint_set/disjoint_set.py) + * [Alternate Disjoint Set](data_structures/disjoint_set/alternate_disjoint_set.py) + * [Disjoint Set](data_structures/disjoint_set/disjoint_set.py) * Hashing - * [Double Hash](https://github.com/TheAlgorithms/Python/blob/master/data_structures/hashing/double_hash.py) - * [Hash Table](https://github.com/TheAlgorithms/Python/blob/master/data_structures/hashing/hash_table.py) - * [Hash Table With Linked List](https://github.com/TheAlgorithms/Python/blob/master/data_structures/hashing/hash_table_with_linked_list.py) + * [Double Hash](data_structures/hashing/double_hash.py) + * [Hash Table](data_structures/hashing/hash_table.py) + * [Hash Table With Linked List](data_structures/hashing/hash_table_with_linked_list.py) * Number Theory - * [Prime Numbers](https://github.com/TheAlgorithms/Python/blob/master/data_structures/hashing/number_theory/prime_numbers.py) - * [Quadratic Probing](https://github.com/TheAlgorithms/Python/blob/master/data_structures/hashing/quadratic_probing.py) + * [Prime Numbers](data_structures/hashing/number_theory/prime_numbers.py) + * [Quadratic Probing](data_structures/hashing/quadratic_probing.py) * Heap - * [Binomial Heap](https://github.com/TheAlgorithms/Python/blob/master/data_structures/heap/binomial_heap.py) - * [Heap](https://github.com/TheAlgorithms/Python/blob/master/data_structures/heap/heap.py) - * [Heap Generic](https://github.com/TheAlgorithms/Python/blob/master/data_structures/heap/heap_generic.py) - * [Max Heap](https://github.com/TheAlgorithms/Python/blob/master/data_structures/heap/max_heap.py) - * [Min Heap](https://github.com/TheAlgorithms/Python/blob/master/data_structures/heap/min_heap.py) - * [Randomized Heap](https://github.com/TheAlgorithms/Python/blob/master/data_structures/heap/randomized_heap.py) - * [Skew Heap](https://github.com/TheAlgorithms/Python/blob/master/data_structures/heap/skew_heap.py) + * [Binomial Heap](data_structures/heap/binomial_heap.py) + * [Heap](data_structures/heap/heap.py) + * [Heap Generic](data_structures/heap/heap_generic.py) + * [Max Heap](data_structures/heap/max_heap.py) + * [Min Heap](data_structures/heap/min_heap.py) + * [Randomized Heap](data_structures/heap/randomized_heap.py) + * [Skew Heap](data_structures/heap/skew_heap.py) * Linked List - * [Circular Linked List](https://github.com/TheAlgorithms/Python/blob/master/data_structures/linked_list/circular_linked_list.py) - * [Deque Doubly](https://github.com/TheAlgorithms/Python/blob/master/data_structures/linked_list/deque_doubly.py) - * [Doubly Linked List](https://github.com/TheAlgorithms/Python/blob/master/data_structures/linked_list/doubly_linked_list.py) - * [Doubly Linked List Two](https://github.com/TheAlgorithms/Python/blob/master/data_structures/linked_list/doubly_linked_list_two.py) - * [From Sequence](https://github.com/TheAlgorithms/Python/blob/master/data_structures/linked_list/from_sequence.py) - * [Has Loop](https://github.com/TheAlgorithms/Python/blob/master/data_structures/linked_list/has_loop.py) - * [Is Palindrome](https://github.com/TheAlgorithms/Python/blob/master/data_structures/linked_list/is_palindrome.py) - * [Merge Two Lists](https://github.com/TheAlgorithms/Python/blob/master/data_structures/linked_list/merge_two_lists.py) - * [Middle Element Of Linked List](https://github.com/TheAlgorithms/Python/blob/master/data_structures/linked_list/middle_element_of_linked_list.py) - * [Print Reverse](https://github.com/TheAlgorithms/Python/blob/master/data_structures/linked_list/print_reverse.py) - * [Singly Linked List](https://github.com/TheAlgorithms/Python/blob/master/data_structures/linked_list/singly_linked_list.py) - * [Skip List](https://github.com/TheAlgorithms/Python/blob/master/data_structures/linked_list/skip_list.py) - * [Swap Nodes](https://github.com/TheAlgorithms/Python/blob/master/data_structures/linked_list/swap_nodes.py) + * [Circular Linked List](data_structures/linked_list/circular_linked_list.py) + * [Deque Doubly](data_structures/linked_list/deque_doubly.py) + * [Doubly Linked List](data_structures/linked_list/doubly_linked_list.py) + * [Doubly Linked List Two](data_structures/linked_list/doubly_linked_list_two.py) + * [From Sequence](data_structures/linked_list/from_sequence.py) + * [Has Loop](data_structures/linked_list/has_loop.py) + * [Is Palindrome](data_structures/linked_list/is_palindrome.py) + * [Merge Two Lists](data_structures/linked_list/merge_two_lists.py) + * [Middle Element Of Linked List](data_structures/linked_list/middle_element_of_linked_list.py) + * [Print Reverse](data_structures/linked_list/print_reverse.py) + * [Singly Linked List](data_structures/linked_list/singly_linked_list.py) + * [Skip List](data_structures/linked_list/skip_list.py) + * [Swap Nodes](data_structures/linked_list/swap_nodes.py) * Queue - * [Circular Queue](https://github.com/TheAlgorithms/Python/blob/master/data_structures/queue/circular_queue.py) - * [Circular Queue Linked List](https://github.com/TheAlgorithms/Python/blob/master/data_structures/queue/circular_queue_linked_list.py) - * [Double Ended Queue](https://github.com/TheAlgorithms/Python/blob/master/data_structures/queue/double_ended_queue.py) - * [Linked Queue](https://github.com/TheAlgorithms/Python/blob/master/data_structures/queue/linked_queue.py) - * [Priority Queue Using List](https://github.com/TheAlgorithms/Python/blob/master/data_structures/queue/priority_queue_using_list.py) - * [Queue On List](https://github.com/TheAlgorithms/Python/blob/master/data_structures/queue/queue_on_list.py) - * [Queue On Pseudo Stack](https://github.com/TheAlgorithms/Python/blob/master/data_structures/queue/queue_on_pseudo_stack.py) + * [Circular Queue](data_structures/queue/circular_queue.py) + * [Circular Queue Linked List](data_structures/queue/circular_queue_linked_list.py) + * [Double Ended Queue](data_structures/queue/double_ended_queue.py) + * [Linked Queue](data_structures/queue/linked_queue.py) + * [Priority Queue Using List](data_structures/queue/priority_queue_using_list.py) + * [Queue On List](data_structures/queue/queue_on_list.py) + * [Queue On Pseudo Stack](data_structures/queue/queue_on_pseudo_stack.py) * Stacks - * [Balanced Parentheses](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/balanced_parentheses.py) - * [Dijkstras Two Stack Algorithm](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/dijkstras_two_stack_algorithm.py) - * [Evaluate Postfix Notations](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/evaluate_postfix_notations.py) - * [Infix To Postfix Conversion](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/infix_to_postfix_conversion.py) - * [Infix To Prefix Conversion](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/infix_to_prefix_conversion.py) - * [Next Greater Element](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/next_greater_element.py) - * [Postfix Evaluation](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/postfix_evaluation.py) - * [Prefix Evaluation](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/prefix_evaluation.py) - * [Stack](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/stack.py) - * [Stack With Doubly Linked List](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/stack_with_doubly_linked_list.py) - * [Stack With Singly Linked List](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/stack_with_singly_linked_list.py) - * [Stock Span Problem](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/stock_span_problem.py) + * [Balanced Parentheses](data_structures/stacks/balanced_parentheses.py) + * [Dijkstras Two Stack Algorithm](data_structures/stacks/dijkstras_two_stack_algorithm.py) + * [Evaluate Postfix Notations](data_structures/stacks/evaluate_postfix_notations.py) + * [Infix To Postfix Conversion](data_structures/stacks/infix_to_postfix_conversion.py) + * [Infix To Prefix Conversion](data_structures/stacks/infix_to_prefix_conversion.py) + * [Next Greater Element](data_structures/stacks/next_greater_element.py) + * [Postfix Evaluation](data_structures/stacks/postfix_evaluation.py) + * [Prefix Evaluation](data_structures/stacks/prefix_evaluation.py) + * [Stack](data_structures/stacks/stack.py) + * [Stack With Doubly Linked List](data_structures/stacks/stack_with_doubly_linked_list.py) + * [Stack With Singly Linked List](data_structures/stacks/stack_with_singly_linked_list.py) + * [Stock Span Problem](data_structures/stacks/stock_span_problem.py) * Trie - * [Trie](https://github.com/TheAlgorithms/Python/blob/master/data_structures/trie/trie.py) + * [Trie](data_structures/trie/trie.py) ## Digital Image Processing - * [Change Brightness](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/change_brightness.py) - * [Change Contrast](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/change_contrast.py) - * [Convert To Negative](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/convert_to_negative.py) + * [Change Brightness](digital_image_processing/change_brightness.py) + * [Change Contrast](digital_image_processing/change_contrast.py) + * [Convert To Negative](digital_image_processing/convert_to_negative.py) * Dithering - * [Burkes](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/dithering/burkes.py) + * [Burkes](digital_image_processing/dithering/burkes.py) * Edge Detection - * [Canny](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/edge_detection/canny.py) + * [Canny](digital_image_processing/edge_detection/canny.py) * Filters - * [Bilateral Filter](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/filters/bilateral_filter.py) - * [Convolve](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/filters/convolve.py) - * [Gabor Filter](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/filters/gabor_filter.py) - * [Gaussian Filter](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/filters/gaussian_filter.py) - * [Median Filter](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/filters/median_filter.py) - * [Sobel Filter](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/filters/sobel_filter.py) + * [Bilateral Filter](digital_image_processing/filters/bilateral_filter.py) + * [Convolve](digital_image_processing/filters/convolve.py) + * [Gabor Filter](digital_image_processing/filters/gabor_filter.py) + * [Gaussian Filter](digital_image_processing/filters/gaussian_filter.py) + * [Median Filter](digital_image_processing/filters/median_filter.py) + * [Sobel Filter](digital_image_processing/filters/sobel_filter.py) * Histogram Equalization - * [Histogram Stretch](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/histogram_equalization/histogram_stretch.py) - * [Index Calculation](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/index_calculation.py) + * [Histogram Stretch](digital_image_processing/histogram_equalization/histogram_stretch.py) + * [Index Calculation](digital_image_processing/index_calculation.py) * Morphological Operations - * [Dilation Operation](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/morphological_operations/dilation_operation.py) - * [Erosion Operation](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/morphological_operations/erosion_operation.py) + * [Dilation Operation](digital_image_processing/morphological_operations/dilation_operation.py) + * [Erosion Operation](digital_image_processing/morphological_operations/erosion_operation.py) * Resize - * [Resize](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/resize/resize.py) + * [Resize](digital_image_processing/resize/resize.py) * Rotation - * [Rotation](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/rotation/rotation.py) - * [Sepia](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/sepia.py) - * [Test Digital Image Processing](https://github.com/TheAlgorithms/Python/blob/master/digital_image_processing/test_digital_image_processing.py) + * [Rotation](digital_image_processing/rotation/rotation.py) + * [Sepia](digital_image_processing/sepia.py) + * [Test Digital Image Processing](digital_image_processing/test_digital_image_processing.py) ## Divide And Conquer - * [Closest Pair Of Points](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/closest_pair_of_points.py) - * [Convex Hull](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/convex_hull.py) - * [Heaps Algorithm](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/heaps_algorithm.py) - * [Heaps Algorithm Iterative](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/heaps_algorithm_iterative.py) - * [Inversions](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/inversions.py) - * [Kth Order Statistic](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/kth_order_statistic.py) - * [Max Difference Pair](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/max_difference_pair.py) - * [Max Subarray Sum](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/max_subarray_sum.py) - * [Mergesort](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/mergesort.py) - * [Peak](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/peak.py) - * [Power](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/power.py) - * [Strassen Matrix Multiplication](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/strassen_matrix_multiplication.py) + * [Closest Pair Of Points](divide_and_conquer/closest_pair_of_points.py) + * [Convex Hull](divide_and_conquer/convex_hull.py) + * [Heaps Algorithm](divide_and_conquer/heaps_algorithm.py) + * [Heaps Algorithm Iterative](divide_and_conquer/heaps_algorithm_iterative.py) + * [Inversions](divide_and_conquer/inversions.py) + * [Kth Order Statistic](divide_and_conquer/kth_order_statistic.py) + * [Max Difference Pair](divide_and_conquer/max_difference_pair.py) + * [Max Subarray Sum](divide_and_conquer/max_subarray_sum.py) + * [Mergesort](divide_and_conquer/mergesort.py) + * [Peak](divide_and_conquer/peak.py) + * [Power](divide_and_conquer/power.py) + * [Strassen Matrix Multiplication](divide_and_conquer/strassen_matrix_multiplication.py) ## Dynamic Programming - * [Abbreviation](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/abbreviation.py) - * [All Construct](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/all_construct.py) - * [Bitmask](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/bitmask.py) - * [Catalan Numbers](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/catalan_numbers.py) - * [Climbing Stairs](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/climbing_stairs.py) - * [Edit Distance](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/edit_distance.py) - * [Factorial](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/factorial.py) - * [Fast Fibonacci](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/fast_fibonacci.py) - * [Fibonacci](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/fibonacci.py) - * [Floyd Warshall](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/floyd_warshall.py) - * [Fractional Knapsack](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/fractional_knapsack.py) - * [Fractional Knapsack 2](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/fractional_knapsack_2.py) - * [Integer Partition](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/integer_partition.py) - * [Iterating Through Submasks](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/iterating_through_submasks.py) - * [Knapsack](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/knapsack.py) - * [Longest Common Subsequence](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/longest_common_subsequence.py) - * [Longest Increasing Subsequence](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/longest_increasing_subsequence.py) - * [Longest Increasing Subsequence O(Nlogn)](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/longest_increasing_subsequence_o(nlogn).py) - * [Longest Sub Array](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/longest_sub_array.py) - * [Matrix Chain Order](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/matrix_chain_order.py) - * [Max Non Adjacent Sum](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/max_non_adjacent_sum.py) - * [Max Sub Array](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/max_sub_array.py) - * [Max Sum Contiguous Subsequence](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/max_sum_contiguous_subsequence.py) - * [Minimum Coin Change](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/minimum_coin_change.py) - * [Minimum Cost Path](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/minimum_cost_path.py) - * [Minimum Partition](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/minimum_partition.py) - * [Minimum Steps To One](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/minimum_steps_to_one.py) - * [Optimal Binary Search Tree](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/optimal_binary_search_tree.py) - * [Rod Cutting](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/rod_cutting.py) - * [Subset Generation](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/subset_generation.py) - * [Sum Of Subset](https://github.com/TheAlgorithms/Python/blob/master/dynamic_programming/sum_of_subset.py) + * [Abbreviation](dynamic_programming/abbreviation.py) + * [All Construct](dynamic_programming/all_construct.py) + * [Bitmask](dynamic_programming/bitmask.py) + * [Catalan Numbers](dynamic_programming/catalan_numbers.py) + * [Climbing Stairs](dynamic_programming/climbing_stairs.py) + * [Edit Distance](dynamic_programming/edit_distance.py) + * [Factorial](dynamic_programming/factorial.py) + * [Fast Fibonacci](dynamic_programming/fast_fibonacci.py) + * [Fibonacci](dynamic_programming/fibonacci.py) + * [Floyd Warshall](dynamic_programming/floyd_warshall.py) + * [Fractional Knapsack](dynamic_programming/fractional_knapsack.py) + * [Fractional Knapsack 2](dynamic_programming/fractional_knapsack_2.py) + * [Integer Partition](dynamic_programming/integer_partition.py) + * [Iterating Through Submasks](dynamic_programming/iterating_through_submasks.py) + * [Knapsack](dynamic_programming/knapsack.py) + * [Longest Common Subsequence](dynamic_programming/longest_common_subsequence.py) + * [Longest Increasing Subsequence](dynamic_programming/longest_increasing_subsequence.py) + * [Longest Increasing Subsequence O(Nlogn)](dynamic_programming/longest_increasing_subsequence_o(nlogn).py) + * [Longest Sub Array](dynamic_programming/longest_sub_array.py) + * [Matrix Chain Order](dynamic_programming/matrix_chain_order.py) + * [Max Non Adjacent Sum](dynamic_programming/max_non_adjacent_sum.py) + * [Max Sub Array](dynamic_programming/max_sub_array.py) + * [Max Sum Contiguous Subsequence](dynamic_programming/max_sum_contiguous_subsequence.py) + * [Minimum Coin Change](dynamic_programming/minimum_coin_change.py) + * [Minimum Cost Path](dynamic_programming/minimum_cost_path.py) + * [Minimum Partition](dynamic_programming/minimum_partition.py) + * [Minimum Steps To One](dynamic_programming/minimum_steps_to_one.py) + * [Optimal Binary Search Tree](dynamic_programming/optimal_binary_search_tree.py) + * [Rod Cutting](dynamic_programming/rod_cutting.py) + * [Subset Generation](dynamic_programming/subset_generation.py) + * [Sum Of Subset](dynamic_programming/sum_of_subset.py) ## Electronics - * [Carrier Concentration](https://github.com/TheAlgorithms/Python/blob/master/electronics/carrier_concentration.py) - * [Coulombs Law](https://github.com/TheAlgorithms/Python/blob/master/electronics/coulombs_law.py) - * [Electric Power](https://github.com/TheAlgorithms/Python/blob/master/electronics/electric_power.py) - * [Ohms Law](https://github.com/TheAlgorithms/Python/blob/master/electronics/ohms_law.py) + * [Carrier Concentration](electronics/carrier_concentration.py) + * [Coulombs Law](electronics/coulombs_law.py) + * [Electric Power](electronics/electric_power.py) + * [Ohms Law](electronics/ohms_law.py) ## File Transfer - * [Receive File](https://github.com/TheAlgorithms/Python/blob/master/file_transfer/receive_file.py) - * [Send File](https://github.com/TheAlgorithms/Python/blob/master/file_transfer/send_file.py) + * [Receive File](file_transfer/receive_file.py) + * [Send File](file_transfer/send_file.py) * Tests - * [Test Send File](https://github.com/TheAlgorithms/Python/blob/master/file_transfer/tests/test_send_file.py) + * [Test Send File](file_transfer/tests/test_send_file.py) ## Financial - * [Equated Monthly Installments](https://github.com/TheAlgorithms/Python/blob/master/financial/equated_monthly_installments.py) - * [Interest](https://github.com/TheAlgorithms/Python/blob/master/financial/interest.py) + * [Equated Monthly Installments](financial/equated_monthly_installments.py) + * [Interest](financial/interest.py) ## Fractals - * [Julia Sets](https://github.com/TheAlgorithms/Python/blob/master/fractals/julia_sets.py) - * [Koch Snowflake](https://github.com/TheAlgorithms/Python/blob/master/fractals/koch_snowflake.py) - * [Mandelbrot](https://github.com/TheAlgorithms/Python/blob/master/fractals/mandelbrot.py) - * [Sierpinski Triangle](https://github.com/TheAlgorithms/Python/blob/master/fractals/sierpinski_triangle.py) + * [Julia Sets](fractals/julia_sets.py) + * [Koch Snowflake](fractals/koch_snowflake.py) + * [Mandelbrot](fractals/mandelbrot.py) + * [Sierpinski Triangle](fractals/sierpinski_triangle.py) ## Fuzzy Logic - * [Fuzzy Operations](https://github.com/TheAlgorithms/Python/blob/master/fuzzy_logic/fuzzy_operations.py) + * [Fuzzy Operations](fuzzy_logic/fuzzy_operations.py) ## Genetic Algorithm - * [Basic String](https://github.com/TheAlgorithms/Python/blob/master/genetic_algorithm/basic_string.py) + * [Basic String](genetic_algorithm/basic_string.py) ## Geodesy - * [Haversine Distance](https://github.com/TheAlgorithms/Python/blob/master/geodesy/haversine_distance.py) - * [Lamberts Ellipsoidal Distance](https://github.com/TheAlgorithms/Python/blob/master/geodesy/lamberts_ellipsoidal_distance.py) + * [Haversine Distance](geodesy/haversine_distance.py) + * [Lamberts Ellipsoidal Distance](geodesy/lamberts_ellipsoidal_distance.py) ## Graphics - * [Bezier Curve](https://github.com/TheAlgorithms/Python/blob/master/graphics/bezier_curve.py) - * [Vector3 For 2D Rendering](https://github.com/TheAlgorithms/Python/blob/master/graphics/vector3_for_2d_rendering.py) + * [Bezier Curve](graphics/bezier_curve.py) + * [Vector3 For 2D Rendering](graphics/vector3_for_2d_rendering.py) ## Graphs - * [A Star](https://github.com/TheAlgorithms/Python/blob/master/graphs/a_star.py) - * [Articulation Points](https://github.com/TheAlgorithms/Python/blob/master/graphs/articulation_points.py) - * [Basic Graphs](https://github.com/TheAlgorithms/Python/blob/master/graphs/basic_graphs.py) - * [Bellman Ford](https://github.com/TheAlgorithms/Python/blob/master/graphs/bellman_ford.py) - * [Bfs Shortest Path](https://github.com/TheAlgorithms/Python/blob/master/graphs/bfs_shortest_path.py) - * [Bfs Zero One Shortest Path](https://github.com/TheAlgorithms/Python/blob/master/graphs/bfs_zero_one_shortest_path.py) - * [Bidirectional A Star](https://github.com/TheAlgorithms/Python/blob/master/graphs/bidirectional_a_star.py) - * [Bidirectional Breadth First Search](https://github.com/TheAlgorithms/Python/blob/master/graphs/bidirectional_breadth_first_search.py) - * [Boruvka](https://github.com/TheAlgorithms/Python/blob/master/graphs/boruvka.py) - * [Breadth First Search](https://github.com/TheAlgorithms/Python/blob/master/graphs/breadth_first_search.py) - * [Breadth First Search 2](https://github.com/TheAlgorithms/Python/blob/master/graphs/breadth_first_search_2.py) - * [Breadth First Search Shortest Path](https://github.com/TheAlgorithms/Python/blob/master/graphs/breadth_first_search_shortest_path.py) - * [Check Bipartite Graph Bfs](https://github.com/TheAlgorithms/Python/blob/master/graphs/check_bipartite_graph_bfs.py) - * [Check Bipartite Graph Dfs](https://github.com/TheAlgorithms/Python/blob/master/graphs/check_bipartite_graph_dfs.py) - * [Check Cycle](https://github.com/TheAlgorithms/Python/blob/master/graphs/check_cycle.py) - * [Connected Components](https://github.com/TheAlgorithms/Python/blob/master/graphs/connected_components.py) - * [Depth First Search](https://github.com/TheAlgorithms/Python/blob/master/graphs/depth_first_search.py) - * [Depth First Search 2](https://github.com/TheAlgorithms/Python/blob/master/graphs/depth_first_search_2.py) - * [Dijkstra](https://github.com/TheAlgorithms/Python/blob/master/graphs/dijkstra.py) - * [Dijkstra 2](https://github.com/TheAlgorithms/Python/blob/master/graphs/dijkstra_2.py) - * [Dijkstra Algorithm](https://github.com/TheAlgorithms/Python/blob/master/graphs/dijkstra_algorithm.py) - * [Dinic](https://github.com/TheAlgorithms/Python/blob/master/graphs/dinic.py) - * [Directed And Undirected (Weighted) Graph](https://github.com/TheAlgorithms/Python/blob/master/graphs/directed_and_undirected_(weighted)_graph.py) - * [Edmonds Karp Multiple Source And Sink](https://github.com/TheAlgorithms/Python/blob/master/graphs/edmonds_karp_multiple_source_and_sink.py) - * [Eulerian Path And Circuit For Undirected Graph](https://github.com/TheAlgorithms/Python/blob/master/graphs/eulerian_path_and_circuit_for_undirected_graph.py) - * [Even Tree](https://github.com/TheAlgorithms/Python/blob/master/graphs/even_tree.py) - * [Finding Bridges](https://github.com/TheAlgorithms/Python/blob/master/graphs/finding_bridges.py) - * [Frequent Pattern Graph Miner](https://github.com/TheAlgorithms/Python/blob/master/graphs/frequent_pattern_graph_miner.py) - * [G Topological Sort](https://github.com/TheAlgorithms/Python/blob/master/graphs/g_topological_sort.py) - * [Gale Shapley Bigraph](https://github.com/TheAlgorithms/Python/blob/master/graphs/gale_shapley_bigraph.py) - * [Graph List](https://github.com/TheAlgorithms/Python/blob/master/graphs/graph_list.py) - * [Graph Matrix](https://github.com/TheAlgorithms/Python/blob/master/graphs/graph_matrix.py) - * [Graphs Floyd Warshall](https://github.com/TheAlgorithms/Python/blob/master/graphs/graphs_floyd_warshall.py) - * [Greedy Best First](https://github.com/TheAlgorithms/Python/blob/master/graphs/greedy_best_first.py) - * [Greedy Min Vertex Cover](https://github.com/TheAlgorithms/Python/blob/master/graphs/greedy_min_vertex_cover.py) - * [Kahns Algorithm Long](https://github.com/TheAlgorithms/Python/blob/master/graphs/kahns_algorithm_long.py) - * [Kahns Algorithm Topo](https://github.com/TheAlgorithms/Python/blob/master/graphs/kahns_algorithm_topo.py) - * [Karger](https://github.com/TheAlgorithms/Python/blob/master/graphs/karger.py) - * [Markov Chain](https://github.com/TheAlgorithms/Python/blob/master/graphs/markov_chain.py) - * [Matching Min Vertex Cover](https://github.com/TheAlgorithms/Python/blob/master/graphs/matching_min_vertex_cover.py) - * [Minimum Spanning Tree Boruvka](https://github.com/TheAlgorithms/Python/blob/master/graphs/minimum_spanning_tree_boruvka.py) - * [Minimum Spanning Tree Kruskal](https://github.com/TheAlgorithms/Python/blob/master/graphs/minimum_spanning_tree_kruskal.py) - * [Minimum Spanning Tree Kruskal2](https://github.com/TheAlgorithms/Python/blob/master/graphs/minimum_spanning_tree_kruskal2.py) - * [Minimum Spanning Tree Prims](https://github.com/TheAlgorithms/Python/blob/master/graphs/minimum_spanning_tree_prims.py) - * [Minimum Spanning Tree Prims2](https://github.com/TheAlgorithms/Python/blob/master/graphs/minimum_spanning_tree_prims2.py) - * [Multi Heuristic Astar](https://github.com/TheAlgorithms/Python/blob/master/graphs/multi_heuristic_astar.py) - * [Page Rank](https://github.com/TheAlgorithms/Python/blob/master/graphs/page_rank.py) - * [Prim](https://github.com/TheAlgorithms/Python/blob/master/graphs/prim.py) - * [Random Graph Generator](https://github.com/TheAlgorithms/Python/blob/master/graphs/random_graph_generator.py) - * [Scc Kosaraju](https://github.com/TheAlgorithms/Python/blob/master/graphs/scc_kosaraju.py) - * [Strongly Connected Components](https://github.com/TheAlgorithms/Python/blob/master/graphs/strongly_connected_components.py) - * [Tarjans Scc](https://github.com/TheAlgorithms/Python/blob/master/graphs/tarjans_scc.py) + * [A Star](graphs/a_star.py) + * [Articulation Points](graphs/articulation_points.py) + * [Basic Graphs](graphs/basic_graphs.py) + * [Bellman Ford](graphs/bellman_ford.py) + * [Bfs Shortest Path](graphs/bfs_shortest_path.py) + * [Bfs Zero One Shortest Path](graphs/bfs_zero_one_shortest_path.py) + * [Bidirectional A Star](graphs/bidirectional_a_star.py) + * [Bidirectional Breadth First Search](graphs/bidirectional_breadth_first_search.py) + * [Boruvka](graphs/boruvka.py) + * [Breadth First Search](graphs/breadth_first_search.py) + * [Breadth First Search 2](graphs/breadth_first_search_2.py) + * [Breadth First Search Shortest Path](graphs/breadth_first_search_shortest_path.py) + * [Check Bipartite Graph Bfs](graphs/check_bipartite_graph_bfs.py) + * [Check Bipartite Graph Dfs](graphs/check_bipartite_graph_dfs.py) + * [Check Cycle](graphs/check_cycle.py) + * [Connected Components](graphs/connected_components.py) + * [Depth First Search](graphs/depth_first_search.py) + * [Depth First Search 2](graphs/depth_first_search_2.py) + * [Dijkstra](graphs/dijkstra.py) + * [Dijkstra 2](graphs/dijkstra_2.py) + * [Dijkstra Algorithm](graphs/dijkstra_algorithm.py) + * [Dinic](graphs/dinic.py) + * [Directed And Undirected (Weighted) Graph](graphs/directed_and_undirected_(weighted)_graph.py) + * [Edmonds Karp Multiple Source And Sink](graphs/edmonds_karp_multiple_source_and_sink.py) + * [Eulerian Path And Circuit For Undirected Graph](graphs/eulerian_path_and_circuit_for_undirected_graph.py) + * [Even Tree](graphs/even_tree.py) + * [Finding Bridges](graphs/finding_bridges.py) + * [Frequent Pattern Graph Miner](graphs/frequent_pattern_graph_miner.py) + * [G Topological Sort](graphs/g_topological_sort.py) + * [Gale Shapley Bigraph](graphs/gale_shapley_bigraph.py) + * [Graph List](graphs/graph_list.py) + * [Graph Matrix](graphs/graph_matrix.py) + * [Graphs Floyd Warshall](graphs/graphs_floyd_warshall.py) + * [Greedy Best First](graphs/greedy_best_first.py) + * [Greedy Min Vertex Cover](graphs/greedy_min_vertex_cover.py) + * [Kahns Algorithm Long](graphs/kahns_algorithm_long.py) + * [Kahns Algorithm Topo](graphs/kahns_algorithm_topo.py) + * [Karger](graphs/karger.py) + * [Markov Chain](graphs/markov_chain.py) + * [Matching Min Vertex Cover](graphs/matching_min_vertex_cover.py) + * [Minimum Path Sum](graphs/minimum_path_sum.py) + * [Minimum Spanning Tree Boruvka](graphs/minimum_spanning_tree_boruvka.py) + * [Minimum Spanning Tree Kruskal](graphs/minimum_spanning_tree_kruskal.py) + * [Minimum Spanning Tree Kruskal2](graphs/minimum_spanning_tree_kruskal2.py) + * [Minimum Spanning Tree Prims](graphs/minimum_spanning_tree_prims.py) + * [Minimum Spanning Tree Prims2](graphs/minimum_spanning_tree_prims2.py) + * [Multi Heuristic Astar](graphs/multi_heuristic_astar.py) + * [Page Rank](graphs/page_rank.py) + * [Prim](graphs/prim.py) + * [Random Graph Generator](graphs/random_graph_generator.py) + * [Scc Kosaraju](graphs/scc_kosaraju.py) + * [Strongly Connected Components](graphs/strongly_connected_components.py) + * [Tarjans Scc](graphs/tarjans_scc.py) * Tests - * [Test Min Spanning Tree Kruskal](https://github.com/TheAlgorithms/Python/blob/master/graphs/tests/test_min_spanning_tree_kruskal.py) - * [Test Min Spanning Tree Prim](https://github.com/TheAlgorithms/Python/blob/master/graphs/tests/test_min_spanning_tree_prim.py) + * [Test Min Spanning Tree Kruskal](graphs/tests/test_min_spanning_tree_kruskal.py) + * [Test Min Spanning Tree Prim](graphs/tests/test_min_spanning_tree_prim.py) ## Greedy Methods - * [Optimal Merge Pattern](https://github.com/TheAlgorithms/Python/blob/master/greedy_methods/optimal_merge_pattern.py) + * [Optimal Merge Pattern](greedy_methods/optimal_merge_pattern.py) ## Hashes - * [Adler32](https://github.com/TheAlgorithms/Python/blob/master/hashes/adler32.py) - * [Chaos Machine](https://github.com/TheAlgorithms/Python/blob/master/hashes/chaos_machine.py) - * [Djb2](https://github.com/TheAlgorithms/Python/blob/master/hashes/djb2.py) - * [Enigma Machine](https://github.com/TheAlgorithms/Python/blob/master/hashes/enigma_machine.py) - * [Hamming Code](https://github.com/TheAlgorithms/Python/blob/master/hashes/hamming_code.py) - * [Luhn](https://github.com/TheAlgorithms/Python/blob/master/hashes/luhn.py) - * [Md5](https://github.com/TheAlgorithms/Python/blob/master/hashes/md5.py) - * [Sdbm](https://github.com/TheAlgorithms/Python/blob/master/hashes/sdbm.py) - * [Sha1](https://github.com/TheAlgorithms/Python/blob/master/hashes/sha1.py) - * [Sha256](https://github.com/TheAlgorithms/Python/blob/master/hashes/sha256.py) + * [Adler32](hashes/adler32.py) + * [Chaos Machine](hashes/chaos_machine.py) + * [Djb2](hashes/djb2.py) + * [Enigma Machine](hashes/enigma_machine.py) + * [Hamming Code](hashes/hamming_code.py) + * [Luhn](hashes/luhn.py) + * [Md5](hashes/md5.py) + * [Sdbm](hashes/sdbm.py) + * [Sha1](hashes/sha1.py) + * [Sha256](hashes/sha256.py) ## Knapsack - * [Greedy Knapsack](https://github.com/TheAlgorithms/Python/blob/master/knapsack/greedy_knapsack.py) - * [Knapsack](https://github.com/TheAlgorithms/Python/blob/master/knapsack/knapsack.py) + * [Greedy Knapsack](knapsack/greedy_knapsack.py) + * [Knapsack](knapsack/knapsack.py) * Tests - * [Test Greedy Knapsack](https://github.com/TheAlgorithms/Python/blob/master/knapsack/tests/test_greedy_knapsack.py) - * [Test Knapsack](https://github.com/TheAlgorithms/Python/blob/master/knapsack/tests/test_knapsack.py) + * [Test Greedy Knapsack](knapsack/tests/test_greedy_knapsack.py) + * [Test Knapsack](knapsack/tests/test_knapsack.py) ## Linear Algebra * Src - * [Conjugate Gradient](https://github.com/TheAlgorithms/Python/blob/master/linear_algebra/src/conjugate_gradient.py) - * [Lib](https://github.com/TheAlgorithms/Python/blob/master/linear_algebra/src/lib.py) - * [Polynom For Points](https://github.com/TheAlgorithms/Python/blob/master/linear_algebra/src/polynom_for_points.py) - * [Power Iteration](https://github.com/TheAlgorithms/Python/blob/master/linear_algebra/src/power_iteration.py) - * [Rayleigh Quotient](https://github.com/TheAlgorithms/Python/blob/master/linear_algebra/src/rayleigh_quotient.py) - * [Schur Complement](https://github.com/TheAlgorithms/Python/blob/master/linear_algebra/src/schur_complement.py) - * [Test Linear Algebra](https://github.com/TheAlgorithms/Python/blob/master/linear_algebra/src/test_linear_algebra.py) - * [Transformations 2D](https://github.com/TheAlgorithms/Python/blob/master/linear_algebra/src/transformations_2d.py) + * [Conjugate Gradient](linear_algebra/src/conjugate_gradient.py) + * [Lib](linear_algebra/src/lib.py) + * [Polynom For Points](linear_algebra/src/polynom_for_points.py) + * [Power Iteration](linear_algebra/src/power_iteration.py) + * [Rayleigh Quotient](linear_algebra/src/rayleigh_quotient.py) + * [Schur Complement](linear_algebra/src/schur_complement.py) + * [Test Linear Algebra](linear_algebra/src/test_linear_algebra.py) + * [Transformations 2D](linear_algebra/src/transformations_2d.py) ## Machine Learning - * [Astar](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/astar.py) - * [Data Transformations](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/data_transformations.py) - * [Decision Tree](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/decision_tree.py) + * [Astar](machine_learning/astar.py) + * [Data Transformations](machine_learning/data_transformations.py) + * [Decision Tree](machine_learning/decision_tree.py) * Forecasting - * [Run](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/forecasting/run.py) - * [Gaussian Naive Bayes](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/gaussian_naive_bayes.py) - * [Gradient Boosting Regressor](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/gradient_boosting_regressor.py) - * [Gradient Descent](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/gradient_descent.py) - * [K Means Clust](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/k_means_clust.py) - * [K Nearest Neighbours](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/k_nearest_neighbours.py) - * [Knn Sklearn](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/knn_sklearn.py) - * [Linear Discriminant Analysis](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/linear_discriminant_analysis.py) - * [Linear Regression](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/linear_regression.py) + * [Run](machine_learning/forecasting/run.py) + * [Gaussian Naive Bayes](machine_learning/gaussian_naive_bayes.py) + * [Gradient Boosting Regressor](machine_learning/gradient_boosting_regressor.py) + * [Gradient Descent](machine_learning/gradient_descent.py) + * [K Means Clust](machine_learning/k_means_clust.py) + * [K Nearest Neighbours](machine_learning/k_nearest_neighbours.py) + * [Knn Sklearn](machine_learning/knn_sklearn.py) + * [Linear Discriminant Analysis](machine_learning/linear_discriminant_analysis.py) + * [Linear Regression](machine_learning/linear_regression.py) * Local Weighted Learning - * [Local Weighted Learning](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/local_weighted_learning/local_weighted_learning.py) - * [Logistic Regression](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/logistic_regression.py) + * [Local Weighted Learning](machine_learning/local_weighted_learning/local_weighted_learning.py) + * [Logistic Regression](machine_learning/logistic_regression.py) * Lstm - * [Lstm Prediction](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/lstm/lstm_prediction.py) - * [Multilayer Perceptron Classifier](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/multilayer_perceptron_classifier.py) - * [Polymonial Regression](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/polymonial_regression.py) - * [Random Forest Classifier](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/random_forest_classifier.py) - * [Random Forest Regressor](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/random_forest_regressor.py) - * [Scoring Functions](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/scoring_functions.py) - * [Sequential Minimum Optimization](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/sequential_minimum_optimization.py) - * [Similarity Search](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/similarity_search.py) - * [Support Vector Machines](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/support_vector_machines.py) - * [Word Frequency Functions](https://github.com/TheAlgorithms/Python/blob/master/machine_learning/word_frequency_functions.py) + * [Lstm Prediction](machine_learning/lstm/lstm_prediction.py) + * [Multilayer Perceptron Classifier](machine_learning/multilayer_perceptron_classifier.py) + * [Polymonial Regression](machine_learning/polymonial_regression.py) + * [Random Forest Classifier](machine_learning/random_forest_classifier.py) + * [Random Forest Regressor](machine_learning/random_forest_regressor.py) + * [Scoring Functions](machine_learning/scoring_functions.py) + * [Sequential Minimum Optimization](machine_learning/sequential_minimum_optimization.py) + * [Similarity Search](machine_learning/similarity_search.py) + * [Support Vector Machines](machine_learning/support_vector_machines.py) + * [Word Frequency Functions](machine_learning/word_frequency_functions.py) ## Maths - * [3N Plus 1](https://github.com/TheAlgorithms/Python/blob/master/maths/3n_plus_1.py) - * [Abs](https://github.com/TheAlgorithms/Python/blob/master/maths/abs.py) - * [Abs Max](https://github.com/TheAlgorithms/Python/blob/master/maths/abs_max.py) - * [Abs Min](https://github.com/TheAlgorithms/Python/blob/master/maths/abs_min.py) - * [Add](https://github.com/TheAlgorithms/Python/blob/master/maths/add.py) - * [Aliquot Sum](https://github.com/TheAlgorithms/Python/blob/master/maths/aliquot_sum.py) - * [Allocation Number](https://github.com/TheAlgorithms/Python/blob/master/maths/allocation_number.py) - * [Area](https://github.com/TheAlgorithms/Python/blob/master/maths/area.py) - * [Area Under Curve](https://github.com/TheAlgorithms/Python/blob/master/maths/area_under_curve.py) - * [Armstrong Numbers](https://github.com/TheAlgorithms/Python/blob/master/maths/armstrong_numbers.py) - * [Average Absolute Deviation](https://github.com/TheAlgorithms/Python/blob/master/maths/average_absolute_deviation.py) - * [Average Mean](https://github.com/TheAlgorithms/Python/blob/master/maths/average_mean.py) - * [Average Median](https://github.com/TheAlgorithms/Python/blob/master/maths/average_median.py) - * [Average Mode](https://github.com/TheAlgorithms/Python/blob/master/maths/average_mode.py) - * [Bailey Borwein Plouffe](https://github.com/TheAlgorithms/Python/blob/master/maths/bailey_borwein_plouffe.py) - * [Basic Maths](https://github.com/TheAlgorithms/Python/blob/master/maths/basic_maths.py) - * [Binary Exp Mod](https://github.com/TheAlgorithms/Python/blob/master/maths/binary_exp_mod.py) - * [Binary Exponentiation](https://github.com/TheAlgorithms/Python/blob/master/maths/binary_exponentiation.py) - * [Binary Exponentiation 2](https://github.com/TheAlgorithms/Python/blob/master/maths/binary_exponentiation_2.py) - * [Binary Exponentiation 3](https://github.com/TheAlgorithms/Python/blob/master/maths/binary_exponentiation_3.py) - * [Binomial Coefficient](https://github.com/TheAlgorithms/Python/blob/master/maths/binomial_coefficient.py) - * [Binomial Distribution](https://github.com/TheAlgorithms/Python/blob/master/maths/binomial_distribution.py) - * [Bisection](https://github.com/TheAlgorithms/Python/blob/master/maths/bisection.py) - * [Ceil](https://github.com/TheAlgorithms/Python/blob/master/maths/ceil.py) - * [Check Polygon](https://github.com/TheAlgorithms/Python/blob/master/maths/check_polygon.py) - * [Chudnovsky Algorithm](https://github.com/TheAlgorithms/Python/blob/master/maths/chudnovsky_algorithm.py) - * [Collatz Sequence](https://github.com/TheAlgorithms/Python/blob/master/maths/collatz_sequence.py) - * [Combinations](https://github.com/TheAlgorithms/Python/blob/master/maths/combinations.py) - * [Decimal Isolate](https://github.com/TheAlgorithms/Python/blob/master/maths/decimal_isolate.py) - * [Double Factorial Iterative](https://github.com/TheAlgorithms/Python/blob/master/maths/double_factorial_iterative.py) - * [Double Factorial Recursive](https://github.com/TheAlgorithms/Python/blob/master/maths/double_factorial_recursive.py) - * [Entropy](https://github.com/TheAlgorithms/Python/blob/master/maths/entropy.py) - * [Euclidean Distance](https://github.com/TheAlgorithms/Python/blob/master/maths/euclidean_distance.py) - * [Euclidean Gcd](https://github.com/TheAlgorithms/Python/blob/master/maths/euclidean_gcd.py) - * [Euler Method](https://github.com/TheAlgorithms/Python/blob/master/maths/euler_method.py) - * [Euler Modified](https://github.com/TheAlgorithms/Python/blob/master/maths/euler_modified.py) - * [Eulers Totient](https://github.com/TheAlgorithms/Python/blob/master/maths/eulers_totient.py) - * [Extended Euclidean Algorithm](https://github.com/TheAlgorithms/Python/blob/master/maths/extended_euclidean_algorithm.py) - * [Factorial Iterative](https://github.com/TheAlgorithms/Python/blob/master/maths/factorial_iterative.py) - * [Factorial Recursive](https://github.com/TheAlgorithms/Python/blob/master/maths/factorial_recursive.py) - * [Factors](https://github.com/TheAlgorithms/Python/blob/master/maths/factors.py) - * [Fermat Little Theorem](https://github.com/TheAlgorithms/Python/blob/master/maths/fermat_little_theorem.py) - * [Fibonacci](https://github.com/TheAlgorithms/Python/blob/master/maths/fibonacci.py) - * [Find Max](https://github.com/TheAlgorithms/Python/blob/master/maths/find_max.py) - * [Find Max Recursion](https://github.com/TheAlgorithms/Python/blob/master/maths/find_max_recursion.py) - * [Find Min](https://github.com/TheAlgorithms/Python/blob/master/maths/find_min.py) - * [Find Min Recursion](https://github.com/TheAlgorithms/Python/blob/master/maths/find_min_recursion.py) - * [Floor](https://github.com/TheAlgorithms/Python/blob/master/maths/floor.py) - * [Gamma](https://github.com/TheAlgorithms/Python/blob/master/maths/gamma.py) - * [Gamma Recursive](https://github.com/TheAlgorithms/Python/blob/master/maths/gamma_recursive.py) - * [Gaussian](https://github.com/TheAlgorithms/Python/blob/master/maths/gaussian.py) - * [Greatest Common Divisor](https://github.com/TheAlgorithms/Python/blob/master/maths/greatest_common_divisor.py) - * [Greedy Coin Change](https://github.com/TheAlgorithms/Python/blob/master/maths/greedy_coin_change.py) - * [Hardy Ramanujanalgo](https://github.com/TheAlgorithms/Python/blob/master/maths/hardy_ramanujanalgo.py) - * [Integration By Simpson Approx](https://github.com/TheAlgorithms/Python/blob/master/maths/integration_by_simpson_approx.py) - * [Is Ip V4 Address Valid](https://github.com/TheAlgorithms/Python/blob/master/maths/is_ip_v4_address_valid.py) - * [Is Square Free](https://github.com/TheAlgorithms/Python/blob/master/maths/is_square_free.py) - * [Jaccard Similarity](https://github.com/TheAlgorithms/Python/blob/master/maths/jaccard_similarity.py) - * [Kadanes](https://github.com/TheAlgorithms/Python/blob/master/maths/kadanes.py) - * [Karatsuba](https://github.com/TheAlgorithms/Python/blob/master/maths/karatsuba.py) - * [Krishnamurthy Number](https://github.com/TheAlgorithms/Python/blob/master/maths/krishnamurthy_number.py) - * [Kth Lexicographic Permutation](https://github.com/TheAlgorithms/Python/blob/master/maths/kth_lexicographic_permutation.py) - * [Largest Of Very Large Numbers](https://github.com/TheAlgorithms/Python/blob/master/maths/largest_of_very_large_numbers.py) - * [Largest Subarray Sum](https://github.com/TheAlgorithms/Python/blob/master/maths/largest_subarray_sum.py) - * [Least Common Multiple](https://github.com/TheAlgorithms/Python/blob/master/maths/least_common_multiple.py) - * [Line Length](https://github.com/TheAlgorithms/Python/blob/master/maths/line_length.py) - * [Lucas Lehmer Primality Test](https://github.com/TheAlgorithms/Python/blob/master/maths/lucas_lehmer_primality_test.py) - * [Lucas Series](https://github.com/TheAlgorithms/Python/blob/master/maths/lucas_series.py) - * [Matrix Exponentiation](https://github.com/TheAlgorithms/Python/blob/master/maths/matrix_exponentiation.py) - * [Max Sum Sliding Window](https://github.com/TheAlgorithms/Python/blob/master/maths/max_sum_sliding_window.py) - * [Median Of Two Arrays](https://github.com/TheAlgorithms/Python/blob/master/maths/median_of_two_arrays.py) - * [Miller Rabin](https://github.com/TheAlgorithms/Python/blob/master/maths/miller_rabin.py) - * [Mobius Function](https://github.com/TheAlgorithms/Python/blob/master/maths/mobius_function.py) - * [Modular Exponential](https://github.com/TheAlgorithms/Python/blob/master/maths/modular_exponential.py) - * [Monte Carlo](https://github.com/TheAlgorithms/Python/blob/master/maths/monte_carlo.py) - * [Monte Carlo Dice](https://github.com/TheAlgorithms/Python/blob/master/maths/monte_carlo_dice.py) - * [Nevilles Method](https://github.com/TheAlgorithms/Python/blob/master/maths/nevilles_method.py) - * [Newton Raphson](https://github.com/TheAlgorithms/Python/blob/master/maths/newton_raphson.py) - * [Number Of Digits](https://github.com/TheAlgorithms/Python/blob/master/maths/number_of_digits.py) - * [Numerical Integration](https://github.com/TheAlgorithms/Python/blob/master/maths/numerical_integration.py) - * [Perfect Cube](https://github.com/TheAlgorithms/Python/blob/master/maths/perfect_cube.py) - * [Perfect Number](https://github.com/TheAlgorithms/Python/blob/master/maths/perfect_number.py) - * [Perfect Square](https://github.com/TheAlgorithms/Python/blob/master/maths/perfect_square.py) - * [Persistence](https://github.com/TheAlgorithms/Python/blob/master/maths/persistence.py) - * [Pi Monte Carlo Estimation](https://github.com/TheAlgorithms/Python/blob/master/maths/pi_monte_carlo_estimation.py) - * [Points Are Collinear 3D](https://github.com/TheAlgorithms/Python/blob/master/maths/points_are_collinear_3d.py) - * [Pollard Rho](https://github.com/TheAlgorithms/Python/blob/master/maths/pollard_rho.py) - * [Polynomial Evaluation](https://github.com/TheAlgorithms/Python/blob/master/maths/polynomial_evaluation.py) - * [Power Using Recursion](https://github.com/TheAlgorithms/Python/blob/master/maths/power_using_recursion.py) - * [Prime Check](https://github.com/TheAlgorithms/Python/blob/master/maths/prime_check.py) - * [Prime Factors](https://github.com/TheAlgorithms/Python/blob/master/maths/prime_factors.py) - * [Prime Numbers](https://github.com/TheAlgorithms/Python/blob/master/maths/prime_numbers.py) - * [Prime Sieve Eratosthenes](https://github.com/TheAlgorithms/Python/blob/master/maths/prime_sieve_eratosthenes.py) - * [Primelib](https://github.com/TheAlgorithms/Python/blob/master/maths/primelib.py) - * [Proth Number](https://github.com/TheAlgorithms/Python/blob/master/maths/proth_number.py) - * [Pythagoras](https://github.com/TheAlgorithms/Python/blob/master/maths/pythagoras.py) - * [Qr Decomposition](https://github.com/TheAlgorithms/Python/blob/master/maths/qr_decomposition.py) - * [Quadratic Equations Complex Numbers](https://github.com/TheAlgorithms/Python/blob/master/maths/quadratic_equations_complex_numbers.py) - * [Radians](https://github.com/TheAlgorithms/Python/blob/master/maths/radians.py) - * [Radix2 Fft](https://github.com/TheAlgorithms/Python/blob/master/maths/radix2_fft.py) - * [Relu](https://github.com/TheAlgorithms/Python/blob/master/maths/relu.py) - * [Runge Kutta](https://github.com/TheAlgorithms/Python/blob/master/maths/runge_kutta.py) - * [Segmented Sieve](https://github.com/TheAlgorithms/Python/blob/master/maths/segmented_sieve.py) + * [3N Plus 1](maths/3n_plus_1.py) + * [Abs](maths/abs.py) + * [Abs Max](maths/abs_max.py) + * [Abs Min](maths/abs_min.py) + * [Add](maths/add.py) + * [Aliquot Sum](maths/aliquot_sum.py) + * [Allocation Number](maths/allocation_number.py) + * [Area](maths/area.py) + * [Area Under Curve](maths/area_under_curve.py) + * [Armstrong Numbers](maths/armstrong_numbers.py) + * [Average Absolute Deviation](maths/average_absolute_deviation.py) + * [Average Mean](maths/average_mean.py) + * [Average Median](maths/average_median.py) + * [Average Mode](maths/average_mode.py) + * [Bailey Borwein Plouffe](maths/bailey_borwein_plouffe.py) + * [Basic Maths](maths/basic_maths.py) + * [Binary Exp Mod](maths/binary_exp_mod.py) + * [Binary Exponentiation](maths/binary_exponentiation.py) + * [Binary Exponentiation 2](maths/binary_exponentiation_2.py) + * [Binary Exponentiation 3](maths/binary_exponentiation_3.py) + * [Binomial Coefficient](maths/binomial_coefficient.py) + * [Binomial Distribution](maths/binomial_distribution.py) + * [Bisection](maths/bisection.py) + * [Ceil](maths/ceil.py) + * [Check Polygon](maths/check_polygon.py) + * [Chudnovsky Algorithm](maths/chudnovsky_algorithm.py) + * [Collatz Sequence](maths/collatz_sequence.py) + * [Combinations](maths/combinations.py) + * [Decimal Isolate](maths/decimal_isolate.py) + * [Double Factorial Iterative](maths/double_factorial_iterative.py) + * [Double Factorial Recursive](maths/double_factorial_recursive.py) + * [Entropy](maths/entropy.py) + * [Euclidean Distance](maths/euclidean_distance.py) + * [Euclidean Gcd](maths/euclidean_gcd.py) + * [Euler Method](maths/euler_method.py) + * [Euler Modified](maths/euler_modified.py) + * [Eulers Totient](maths/eulers_totient.py) + * [Extended Euclidean Algorithm](maths/extended_euclidean_algorithm.py) + * [Factorial Iterative](maths/factorial_iterative.py) + * [Factorial Recursive](maths/factorial_recursive.py) + * [Factors](maths/factors.py) + * [Fermat Little Theorem](maths/fermat_little_theorem.py) + * [Fibonacci](maths/fibonacci.py) + * [Find Max](maths/find_max.py) + * [Find Max Recursion](maths/find_max_recursion.py) + * [Find Min](maths/find_min.py) + * [Find Min Recursion](maths/find_min_recursion.py) + * [Floor](maths/floor.py) + * [Gamma](maths/gamma.py) + * [Gamma Recursive](maths/gamma_recursive.py) + * [Gaussian](maths/gaussian.py) + * [Greatest Common Divisor](maths/greatest_common_divisor.py) + * [Greedy Coin Change](maths/greedy_coin_change.py) + * [Hardy Ramanujanalgo](maths/hardy_ramanujanalgo.py) + * [Integration By Simpson Approx](maths/integration_by_simpson_approx.py) + * [Is Ip V4 Address Valid](maths/is_ip_v4_address_valid.py) + * [Is Square Free](maths/is_square_free.py) + * [Jaccard Similarity](maths/jaccard_similarity.py) + * [Kadanes](maths/kadanes.py) + * [Karatsuba](maths/karatsuba.py) + * [Krishnamurthy Number](maths/krishnamurthy_number.py) + * [Kth Lexicographic Permutation](maths/kth_lexicographic_permutation.py) + * [Largest Of Very Large Numbers](maths/largest_of_very_large_numbers.py) + * [Largest Subarray Sum](maths/largest_subarray_sum.py) + * [Least Common Multiple](maths/least_common_multiple.py) + * [Line Length](maths/line_length.py) + * [Lucas Lehmer Primality Test](maths/lucas_lehmer_primality_test.py) + * [Lucas Series](maths/lucas_series.py) + * [Matrix Exponentiation](maths/matrix_exponentiation.py) + * [Max Sum Sliding Window](maths/max_sum_sliding_window.py) + * [Median Of Two Arrays](maths/median_of_two_arrays.py) + * [Miller Rabin](maths/miller_rabin.py) + * [Mobius Function](maths/mobius_function.py) + * [Modular Exponential](maths/modular_exponential.py) + * [Monte Carlo](maths/monte_carlo.py) + * [Monte Carlo Dice](maths/monte_carlo_dice.py) + * [Nevilles Method](maths/nevilles_method.py) + * [Newton Raphson](maths/newton_raphson.py) + * [Number Of Digits](maths/number_of_digits.py) + * [Numerical Integration](maths/numerical_integration.py) + * [Perfect Cube](maths/perfect_cube.py) + * [Perfect Number](maths/perfect_number.py) + * [Perfect Square](maths/perfect_square.py) + * [Persistence](maths/persistence.py) + * [Pi Monte Carlo Estimation](maths/pi_monte_carlo_estimation.py) + * [Points Are Collinear 3D](maths/points_are_collinear_3d.py) + * [Pollard Rho](maths/pollard_rho.py) + * [Polynomial Evaluation](maths/polynomial_evaluation.py) + * [Power Using Recursion](maths/power_using_recursion.py) + * [Prime Check](maths/prime_check.py) + * [Prime Factors](maths/prime_factors.py) + * [Prime Numbers](maths/prime_numbers.py) + * [Prime Sieve Eratosthenes](maths/prime_sieve_eratosthenes.py) + * [Primelib](maths/primelib.py) + * [Proth Number](maths/proth_number.py) + * [Pythagoras](maths/pythagoras.py) + * [Qr Decomposition](maths/qr_decomposition.py) + * [Quadratic Equations Complex Numbers](maths/quadratic_equations_complex_numbers.py) + * [Radians](maths/radians.py) + * [Radix2 Fft](maths/radix2_fft.py) + * [Relu](maths/relu.py) + * [Runge Kutta](maths/runge_kutta.py) + * [Segmented Sieve](maths/segmented_sieve.py) * Series - * [Arithmetic](https://github.com/TheAlgorithms/Python/blob/master/maths/series/arithmetic.py) - * [Geometric](https://github.com/TheAlgorithms/Python/blob/master/maths/series/geometric.py) - * [Geometric Series](https://github.com/TheAlgorithms/Python/blob/master/maths/series/geometric_series.py) - * [Harmonic](https://github.com/TheAlgorithms/Python/blob/master/maths/series/harmonic.py) - * [Harmonic Series](https://github.com/TheAlgorithms/Python/blob/master/maths/series/harmonic_series.py) - * [Hexagonal Numbers](https://github.com/TheAlgorithms/Python/blob/master/maths/series/hexagonal_numbers.py) - * [P Series](https://github.com/TheAlgorithms/Python/blob/master/maths/series/p_series.py) - * [Sieve Of Eratosthenes](https://github.com/TheAlgorithms/Python/blob/master/maths/sieve_of_eratosthenes.py) - * [Sigmoid](https://github.com/TheAlgorithms/Python/blob/master/maths/sigmoid.py) - * [Simpson Rule](https://github.com/TheAlgorithms/Python/blob/master/maths/simpson_rule.py) - * [Sock Merchant](https://github.com/TheAlgorithms/Python/blob/master/maths/sock_merchant.py) - * [Softmax](https://github.com/TheAlgorithms/Python/blob/master/maths/softmax.py) - * [Square Root](https://github.com/TheAlgorithms/Python/blob/master/maths/square_root.py) - * [Sum Of Arithmetic Series](https://github.com/TheAlgorithms/Python/blob/master/maths/sum_of_arithmetic_series.py) - * [Sum Of Digits](https://github.com/TheAlgorithms/Python/blob/master/maths/sum_of_digits.py) - * [Sum Of Geometric Progression](https://github.com/TheAlgorithms/Python/blob/master/maths/sum_of_geometric_progression.py) - * [Sylvester Sequence](https://github.com/TheAlgorithms/Python/blob/master/maths/sylvester_sequence.py) - * [Test Prime Check](https://github.com/TheAlgorithms/Python/blob/master/maths/test_prime_check.py) - * [Trapezoidal Rule](https://github.com/TheAlgorithms/Python/blob/master/maths/trapezoidal_rule.py) - * [Triplet Sum](https://github.com/TheAlgorithms/Python/blob/master/maths/triplet_sum.py) - * [Two Pointer](https://github.com/TheAlgorithms/Python/blob/master/maths/two_pointer.py) - * [Two Sum](https://github.com/TheAlgorithms/Python/blob/master/maths/two_sum.py) - * [Ugly Numbers](https://github.com/TheAlgorithms/Python/blob/master/maths/ugly_numbers.py) - * [Volume](https://github.com/TheAlgorithms/Python/blob/master/maths/volume.py) - * [Zellers Congruence](https://github.com/TheAlgorithms/Python/blob/master/maths/zellers_congruence.py) + * [Arithmetic](maths/series/arithmetic.py) + * [Geometric](maths/series/geometric.py) + * [Geometric Series](maths/series/geometric_series.py) + * [Harmonic](maths/series/harmonic.py) + * [Harmonic Series](maths/series/harmonic_series.py) + * [Hexagonal Numbers](maths/series/hexagonal_numbers.py) + * [P Series](maths/series/p_series.py) + * [Sieve Of Eratosthenes](maths/sieve_of_eratosthenes.py) + * [Sigmoid](maths/sigmoid.py) + * [Simpson Rule](maths/simpson_rule.py) + * [Sin](maths/sin.py) + * [Sock Merchant](maths/sock_merchant.py) + * [Softmax](maths/softmax.py) + * [Square Root](maths/square_root.py) + * [Sum Of Arithmetic Series](maths/sum_of_arithmetic_series.py) + * [Sum Of Digits](maths/sum_of_digits.py) + * [Sum Of Geometric Progression](maths/sum_of_geometric_progression.py) + * [Sylvester Sequence](maths/sylvester_sequence.py) + * [Test Prime Check](maths/test_prime_check.py) + * [Trapezoidal Rule](maths/trapezoidal_rule.py) + * [Triplet Sum](maths/triplet_sum.py) + * [Two Pointer](maths/two_pointer.py) + * [Two Sum](maths/two_sum.py) + * [Ugly Numbers](maths/ugly_numbers.py) + * [Volume](maths/volume.py) + * [Zellers Congruence](maths/zellers_congruence.py) ## Matrix - * [Count Islands In Matrix](https://github.com/TheAlgorithms/Python/blob/master/matrix/count_islands_in_matrix.py) - * [Inverse Of Matrix](https://github.com/TheAlgorithms/Python/blob/master/matrix/inverse_of_matrix.py) - * [Matrix Class](https://github.com/TheAlgorithms/Python/blob/master/matrix/matrix_class.py) - * [Matrix Operation](https://github.com/TheAlgorithms/Python/blob/master/matrix/matrix_operation.py) - * [Nth Fibonacci Using Matrix Exponentiation](https://github.com/TheAlgorithms/Python/blob/master/matrix/nth_fibonacci_using_matrix_exponentiation.py) - * [Rotate Matrix](https://github.com/TheAlgorithms/Python/blob/master/matrix/rotate_matrix.py) - * [Searching In Sorted Matrix](https://github.com/TheAlgorithms/Python/blob/master/matrix/searching_in_sorted_matrix.py) - * [Sherman Morrison](https://github.com/TheAlgorithms/Python/blob/master/matrix/sherman_morrison.py) - * [Spiral Print](https://github.com/TheAlgorithms/Python/blob/master/matrix/spiral_print.py) + * [Count Islands In Matrix](matrix/count_islands_in_matrix.py) + * [Inverse Of Matrix](matrix/inverse_of_matrix.py) + * [Matrix Class](matrix/matrix_class.py) + * [Matrix Operation](matrix/matrix_operation.py) + * [Nth Fibonacci Using Matrix Exponentiation](matrix/nth_fibonacci_using_matrix_exponentiation.py) + * [Rotate Matrix](matrix/rotate_matrix.py) + * [Searching In Sorted Matrix](matrix/searching_in_sorted_matrix.py) + * [Sherman Morrison](matrix/sherman_morrison.py) + * [Spiral Print](matrix/spiral_print.py) * Tests - * [Test Matrix Operation](https://github.com/TheAlgorithms/Python/blob/master/matrix/tests/test_matrix_operation.py) + * [Test Matrix Operation](matrix/tests/test_matrix_operation.py) ## Networking Flow - * [Ford Fulkerson](https://github.com/TheAlgorithms/Python/blob/master/networking_flow/ford_fulkerson.py) - * [Minimum Cut](https://github.com/TheAlgorithms/Python/blob/master/networking_flow/minimum_cut.py) + * [Ford Fulkerson](networking_flow/ford_fulkerson.py) + * [Minimum Cut](networking_flow/minimum_cut.py) ## Neural Network - * [2 Hidden Layers Neural Network](https://github.com/TheAlgorithms/Python/blob/master/neural_network/2_hidden_layers_neural_network.py) - * [Back Propagation Neural Network](https://github.com/TheAlgorithms/Python/blob/master/neural_network/back_propagation_neural_network.py) - * [Convolution Neural Network](https://github.com/TheAlgorithms/Python/blob/master/neural_network/convolution_neural_network.py) - * [Perceptron](https://github.com/TheAlgorithms/Python/blob/master/neural_network/perceptron.py) + * [2 Hidden Layers Neural Network](neural_network/2_hidden_layers_neural_network.py) + * [Back Propagation Neural Network](neural_network/back_propagation_neural_network.py) + * [Convolution Neural Network](neural_network/convolution_neural_network.py) + * [Perceptron](neural_network/perceptron.py) ## Other - * [Activity Selection](https://github.com/TheAlgorithms/Python/blob/master/other/activity_selection.py) - * [Alternative List Arrange](https://github.com/TheAlgorithms/Python/blob/master/other/alternative_list_arrange.py) - * [Check Strong Password](https://github.com/TheAlgorithms/Python/blob/master/other/check_strong_password.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) - * [Gauss Easter](https://github.com/TheAlgorithms/Python/blob/master/other/gauss_easter.py) - * [Graham Scan](https://github.com/TheAlgorithms/Python/blob/master/other/graham_scan.py) - * [Greedy](https://github.com/TheAlgorithms/Python/blob/master/other/greedy.py) - * [Least Recently Used](https://github.com/TheAlgorithms/Python/blob/master/other/least_recently_used.py) - * [Lfu Cache](https://github.com/TheAlgorithms/Python/blob/master/other/lfu_cache.py) - * [Linear Congruential Generator](https://github.com/TheAlgorithms/Python/blob/master/other/linear_congruential_generator.py) - * [Lru Cache](https://github.com/TheAlgorithms/Python/blob/master/other/lru_cache.py) - * [Magicdiamondpattern](https://github.com/TheAlgorithms/Python/blob/master/other/magicdiamondpattern.py) - * [Nested Brackets](https://github.com/TheAlgorithms/Python/blob/master/other/nested_brackets.py) - * [Password Generator](https://github.com/TheAlgorithms/Python/blob/master/other/password_generator.py) - * [Scoring Algorithm](https://github.com/TheAlgorithms/Python/blob/master/other/scoring_algorithm.py) - * [Sdes](https://github.com/TheAlgorithms/Python/blob/master/other/sdes.py) - * [Tower Of Hanoi](https://github.com/TheAlgorithms/Python/blob/master/other/tower_of_hanoi.py) + * [Activity Selection](other/activity_selection.py) + * [Alternative List Arrange](other/alternative_list_arrange.py) + * [Check Strong Password](other/check_strong_password.py) + * [Davisb Putnamb Logemannb Loveland](other/davisb_putnamb_logemannb_loveland.py) + * [Dijkstra Bankers Algorithm](other/dijkstra_bankers_algorithm.py) + * [Doomsday](other/doomsday.py) + * [Fischer Yates Shuffle](other/fischer_yates_shuffle.py) + * [Gauss Easter](other/gauss_easter.py) + * [Graham Scan](other/graham_scan.py) + * [Greedy](other/greedy.py) + * [Least Recently Used](other/least_recently_used.py) + * [Lfu Cache](other/lfu_cache.py) + * [Linear Congruential Generator](other/linear_congruential_generator.py) + * [Lru Cache](other/lru_cache.py) + * [Magicdiamondpattern](other/magicdiamondpattern.py) + * [Nested Brackets](other/nested_brackets.py) + * [Password Generator](other/password_generator.py) + * [Scoring Algorithm](other/scoring_algorithm.py) + * [Sdes](other/sdes.py) + * [Tower Of Hanoi](other/tower_of_hanoi.py) ## Physics - * [Horizontal Projectile Motion](https://github.com/TheAlgorithms/Python/blob/master/physics/horizontal_projectile_motion.py) - * [N Body Simulation](https://github.com/TheAlgorithms/Python/blob/master/physics/n_body_simulation.py) - * [Newtons Second Law Of Motion](https://github.com/TheAlgorithms/Python/blob/master/physics/newtons_second_law_of_motion.py) + * [Horizontal Projectile Motion](physics/horizontal_projectile_motion.py) + * [Lorenz Transformation Four Vector](physics/lorenz_transformation_four_vector.py) + * [N Body Simulation](physics/n_body_simulation.py) + * [Newtons Second Law Of Motion](physics/newtons_second_law_of_motion.py) ## Project Euler * Problem 001 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_001/sol1.py) - * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_001/sol2.py) - * [Sol3](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_001/sol3.py) - * [Sol4](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_001/sol4.py) - * [Sol5](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_001/sol5.py) - * [Sol6](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_001/sol6.py) - * [Sol7](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_001/sol7.py) + * [Sol1](project_euler/problem_001/sol1.py) + * [Sol2](project_euler/problem_001/sol2.py) + * [Sol3](project_euler/problem_001/sol3.py) + * [Sol4](project_euler/problem_001/sol4.py) + * [Sol5](project_euler/problem_001/sol5.py) + * [Sol6](project_euler/problem_001/sol6.py) + * [Sol7](project_euler/problem_001/sol7.py) * Problem 002 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_002/sol1.py) - * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_002/sol2.py) - * [Sol3](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_002/sol3.py) - * [Sol4](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_002/sol4.py) - * [Sol5](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_002/sol5.py) + * [Sol1](project_euler/problem_002/sol1.py) + * [Sol2](project_euler/problem_002/sol2.py) + * [Sol3](project_euler/problem_002/sol3.py) + * [Sol4](project_euler/problem_002/sol4.py) + * [Sol5](project_euler/problem_002/sol5.py) * Problem 003 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_003/sol1.py) - * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_003/sol2.py) - * [Sol3](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_003/sol3.py) + * [Sol1](project_euler/problem_003/sol1.py) + * [Sol2](project_euler/problem_003/sol2.py) + * [Sol3](project_euler/problem_003/sol3.py) * Problem 004 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_004/sol1.py) - * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_004/sol2.py) + * [Sol1](project_euler/problem_004/sol1.py) + * [Sol2](project_euler/problem_004/sol2.py) * Problem 005 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_005/sol1.py) - * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_005/sol2.py) + * [Sol1](project_euler/problem_005/sol1.py) + * [Sol2](project_euler/problem_005/sol2.py) * Problem 006 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_006/sol1.py) - * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_006/sol2.py) - * [Sol3](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_006/sol3.py) - * [Sol4](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_006/sol4.py) + * [Sol1](project_euler/problem_006/sol1.py) + * [Sol2](project_euler/problem_006/sol2.py) + * [Sol3](project_euler/problem_006/sol3.py) + * [Sol4](project_euler/problem_006/sol4.py) * Problem 007 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_007/sol1.py) - * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_007/sol2.py) - * [Sol3](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_007/sol3.py) + * [Sol1](project_euler/problem_007/sol1.py) + * [Sol2](project_euler/problem_007/sol2.py) + * [Sol3](project_euler/problem_007/sol3.py) * Problem 008 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_008/sol1.py) - * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_008/sol2.py) - * [Sol3](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_008/sol3.py) + * [Sol1](project_euler/problem_008/sol1.py) + * [Sol2](project_euler/problem_008/sol2.py) + * [Sol3](project_euler/problem_008/sol3.py) * Problem 009 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_009/sol1.py) - * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_009/sol2.py) - * [Sol3](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_009/sol3.py) + * [Sol1](project_euler/problem_009/sol1.py) + * [Sol2](project_euler/problem_009/sol2.py) + * [Sol3](project_euler/problem_009/sol3.py) * Problem 010 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_010/sol1.py) - * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_010/sol2.py) - * [Sol3](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_010/sol3.py) + * [Sol1](project_euler/problem_010/sol1.py) + * [Sol2](project_euler/problem_010/sol2.py) + * [Sol3](project_euler/problem_010/sol3.py) * Problem 011 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_011/sol1.py) - * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_011/sol2.py) + * [Sol1](project_euler/problem_011/sol1.py) + * [Sol2](project_euler/problem_011/sol2.py) * Problem 012 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_012/sol1.py) - * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_012/sol2.py) + * [Sol1](project_euler/problem_012/sol1.py) + * [Sol2](project_euler/problem_012/sol2.py) * Problem 013 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_013/sol1.py) + * [Sol1](project_euler/problem_013/sol1.py) * Problem 014 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_014/sol1.py) - * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_014/sol2.py) + * [Sol1](project_euler/problem_014/sol1.py) + * [Sol2](project_euler/problem_014/sol2.py) * Problem 015 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_015/sol1.py) + * [Sol1](project_euler/problem_015/sol1.py) * Problem 016 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_016/sol1.py) - * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_016/sol2.py) + * [Sol1](project_euler/problem_016/sol1.py) + * [Sol2](project_euler/problem_016/sol2.py) * Problem 017 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_017/sol1.py) + * [Sol1](project_euler/problem_017/sol1.py) * Problem 018 - * [Solution](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_018/solution.py) + * [Solution](project_euler/problem_018/solution.py) * Problem 019 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_019/sol1.py) + * [Sol1](project_euler/problem_019/sol1.py) * Problem 020 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_020/sol1.py) - * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_020/sol2.py) - * [Sol3](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_020/sol3.py) - * [Sol4](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_020/sol4.py) + * [Sol1](project_euler/problem_020/sol1.py) + * [Sol2](project_euler/problem_020/sol2.py) + * [Sol3](project_euler/problem_020/sol3.py) + * [Sol4](project_euler/problem_020/sol4.py) * Problem 021 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_021/sol1.py) + * [Sol1](project_euler/problem_021/sol1.py) * Problem 022 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_022/sol1.py) - * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_022/sol2.py) + * [Sol1](project_euler/problem_022/sol1.py) + * [Sol2](project_euler/problem_022/sol2.py) * Problem 023 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_023/sol1.py) + * [Sol1](project_euler/problem_023/sol1.py) * Problem 024 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_024/sol1.py) + * [Sol1](project_euler/problem_024/sol1.py) * Problem 025 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_025/sol1.py) - * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_025/sol2.py) - * [Sol3](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_025/sol3.py) + * [Sol1](project_euler/problem_025/sol1.py) + * [Sol2](project_euler/problem_025/sol2.py) + * [Sol3](project_euler/problem_025/sol3.py) * Problem 026 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_026/sol1.py) + * [Sol1](project_euler/problem_026/sol1.py) * Problem 027 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_027/sol1.py) + * [Sol1](project_euler/problem_027/sol1.py) * Problem 028 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_028/sol1.py) + * [Sol1](project_euler/problem_028/sol1.py) * Problem 029 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_029/sol1.py) + * [Sol1](project_euler/problem_029/sol1.py) * Problem 030 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_030/sol1.py) + * [Sol1](project_euler/problem_030/sol1.py) * Problem 031 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_031/sol1.py) - * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_031/sol2.py) + * [Sol1](project_euler/problem_031/sol1.py) + * [Sol2](project_euler/problem_031/sol2.py) * Problem 032 - * [Sol32](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_032/sol32.py) + * [Sol32](project_euler/problem_032/sol32.py) * Problem 033 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_033/sol1.py) + * [Sol1](project_euler/problem_033/sol1.py) * Problem 034 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_034/sol1.py) + * [Sol1](project_euler/problem_034/sol1.py) * Problem 035 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_035/sol1.py) + * [Sol1](project_euler/problem_035/sol1.py) * Problem 036 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_036/sol1.py) + * [Sol1](project_euler/problem_036/sol1.py) * Problem 037 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_037/sol1.py) + * [Sol1](project_euler/problem_037/sol1.py) * Problem 038 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_038/sol1.py) + * [Sol1](project_euler/problem_038/sol1.py) * Problem 039 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_039/sol1.py) + * [Sol1](project_euler/problem_039/sol1.py) * Problem 040 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_040/sol1.py) + * [Sol1](project_euler/problem_040/sol1.py) * Problem 041 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_041/sol1.py) + * [Sol1](project_euler/problem_041/sol1.py) * Problem 042 - * [Solution42](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_042/solution42.py) + * [Solution42](project_euler/problem_042/solution42.py) * Problem 043 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_043/sol1.py) + * [Sol1](project_euler/problem_043/sol1.py) * Problem 044 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_044/sol1.py) + * [Sol1](project_euler/problem_044/sol1.py) * Problem 045 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_045/sol1.py) + * [Sol1](project_euler/problem_045/sol1.py) * Problem 046 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_046/sol1.py) + * [Sol1](project_euler/problem_046/sol1.py) * Problem 047 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_047/sol1.py) + * [Sol1](project_euler/problem_047/sol1.py) * Problem 048 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_048/sol1.py) + * [Sol1](project_euler/problem_048/sol1.py) * Problem 049 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_049/sol1.py) + * [Sol1](project_euler/problem_049/sol1.py) * Problem 050 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_050/sol1.py) + * [Sol1](project_euler/problem_050/sol1.py) * Problem 051 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_051/sol1.py) + * [Sol1](project_euler/problem_051/sol1.py) * Problem 052 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_052/sol1.py) + * [Sol1](project_euler/problem_052/sol1.py) * Problem 053 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_053/sol1.py) + * [Sol1](project_euler/problem_053/sol1.py) * Problem 054 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_054/sol1.py) - * [Test Poker Hand](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_054/test_poker_hand.py) + * [Sol1](project_euler/problem_054/sol1.py) + * [Test Poker Hand](project_euler/problem_054/test_poker_hand.py) * Problem 055 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_055/sol1.py) + * [Sol1](project_euler/problem_055/sol1.py) * Problem 056 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_056/sol1.py) + * [Sol1](project_euler/problem_056/sol1.py) * Problem 057 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_057/sol1.py) + * [Sol1](project_euler/problem_057/sol1.py) * Problem 058 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_058/sol1.py) + * [Sol1](project_euler/problem_058/sol1.py) * Problem 059 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_059/sol1.py) + * [Sol1](project_euler/problem_059/sol1.py) * Problem 062 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_062/sol1.py) + * [Sol1](project_euler/problem_062/sol1.py) * Problem 063 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_063/sol1.py) + * [Sol1](project_euler/problem_063/sol1.py) * Problem 064 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_064/sol1.py) + * [Sol1](project_euler/problem_064/sol1.py) * Problem 065 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_065/sol1.py) + * [Sol1](project_euler/problem_065/sol1.py) * Problem 067 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_067/sol1.py) - * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_067/sol2.py) + * [Sol1](project_euler/problem_067/sol1.py) + * [Sol2](project_euler/problem_067/sol2.py) * Problem 068 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_068/sol1.py) + * [Sol1](project_euler/problem_068/sol1.py) * Problem 069 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_069/sol1.py) + * [Sol1](project_euler/problem_069/sol1.py) * Problem 070 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_070/sol1.py) + * [Sol1](project_euler/problem_070/sol1.py) * Problem 071 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_071/sol1.py) + * [Sol1](project_euler/problem_071/sol1.py) * Problem 072 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_072/sol1.py) - * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_072/sol2.py) + * [Sol1](project_euler/problem_072/sol1.py) + * [Sol2](project_euler/problem_072/sol2.py) * Problem 074 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_074/sol1.py) - * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_074/sol2.py) + * [Sol1](project_euler/problem_074/sol1.py) + * [Sol2](project_euler/problem_074/sol2.py) * Problem 075 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_075/sol1.py) + * [Sol1](project_euler/problem_075/sol1.py) * Problem 076 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_076/sol1.py) + * [Sol1](project_euler/problem_076/sol1.py) * Problem 077 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_077/sol1.py) + * [Sol1](project_euler/problem_077/sol1.py) * Problem 078 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_078/sol1.py) + * [Sol1](project_euler/problem_078/sol1.py) * Problem 080 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_080/sol1.py) + * [Sol1](project_euler/problem_080/sol1.py) * Problem 081 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_081/sol1.py) + * [Sol1](project_euler/problem_081/sol1.py) * Problem 085 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_085/sol1.py) + * [Sol1](project_euler/problem_085/sol1.py) * Problem 086 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_086/sol1.py) + * [Sol1](project_euler/problem_086/sol1.py) * Problem 087 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_087/sol1.py) + * [Sol1](project_euler/problem_087/sol1.py) * Problem 089 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_089/sol1.py) + * [Sol1](project_euler/problem_089/sol1.py) * Problem 091 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_091/sol1.py) + * [Sol1](project_euler/problem_091/sol1.py) * Problem 092 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_092/sol1.py) + * [Sol1](project_euler/problem_092/sol1.py) * Problem 097 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_097/sol1.py) + * [Sol1](project_euler/problem_097/sol1.py) * Problem 099 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_099/sol1.py) + * [Sol1](project_euler/problem_099/sol1.py) * Problem 101 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_101/sol1.py) + * [Sol1](project_euler/problem_101/sol1.py) * Problem 102 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_102/sol1.py) + * [Sol1](project_euler/problem_102/sol1.py) * Problem 104 - * [Sol](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_104/sol.py) + * [Sol](project_euler/problem_104/sol.py) * Problem 107 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_107/sol1.py) + * [Sol1](project_euler/problem_107/sol1.py) * Problem 109 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_109/sol1.py) + * [Sol1](project_euler/problem_109/sol1.py) * Problem 112 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_112/sol1.py) + * [Sol1](project_euler/problem_112/sol1.py) * Problem 113 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_113/sol1.py) + * [Sol1](project_euler/problem_113/sol1.py) * Problem 119 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_119/sol1.py) + * [Sol1](project_euler/problem_119/sol1.py) * Problem 120 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_120/sol1.py) + * [Sol1](project_euler/problem_120/sol1.py) * Problem 121 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_121/sol1.py) + * [Sol1](project_euler/problem_121/sol1.py) * Problem 123 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_123/sol1.py) + * [Sol1](project_euler/problem_123/sol1.py) * Problem 125 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_125/sol1.py) + * [Sol1](project_euler/problem_125/sol1.py) * Problem 129 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_129/sol1.py) + * [Sol1](project_euler/problem_129/sol1.py) * Problem 135 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_135/sol1.py) + * [Sol1](project_euler/problem_135/sol1.py) * Problem 144 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_144/sol1.py) + * [Sol1](project_euler/problem_144/sol1.py) * Problem 145 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_145/sol1.py) + * [Sol1](project_euler/problem_145/sol1.py) * Problem 173 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_173/sol1.py) + * [Sol1](project_euler/problem_173/sol1.py) * Problem 174 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_174/sol1.py) + * [Sol1](project_euler/problem_174/sol1.py) * Problem 180 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_180/sol1.py) + * [Sol1](project_euler/problem_180/sol1.py) * Problem 188 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_188/sol1.py) + * [Sol1](project_euler/problem_188/sol1.py) * Problem 191 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_191/sol1.py) + * [Sol1](project_euler/problem_191/sol1.py) * Problem 203 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_203/sol1.py) + * [Sol1](project_euler/problem_203/sol1.py) * Problem 205 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_205/sol1.py) + * [Sol1](project_euler/problem_205/sol1.py) * Problem 206 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_206/sol1.py) + * [Sol1](project_euler/problem_206/sol1.py) * Problem 207 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_207/sol1.py) + * [Sol1](project_euler/problem_207/sol1.py) * Problem 234 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_234/sol1.py) + * [Sol1](project_euler/problem_234/sol1.py) * Problem 301 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_301/sol1.py) + * [Sol1](project_euler/problem_301/sol1.py) * Problem 493 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_493/sol1.py) + * [Sol1](project_euler/problem_493/sol1.py) * Problem 551 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_551/sol1.py) + * [Sol1](project_euler/problem_551/sol1.py) * Problem 686 - * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_686/sol1.py) + * [Sol1](project_euler/problem_686/sol1.py) ## Quantum - * [Deutsch Jozsa](https://github.com/TheAlgorithms/Python/blob/master/quantum/deutsch_jozsa.py) - * [Half Adder](https://github.com/TheAlgorithms/Python/blob/master/quantum/half_adder.py) - * [Not Gate](https://github.com/TheAlgorithms/Python/blob/master/quantum/not_gate.py) - * [Quantum Entanglement](https://github.com/TheAlgorithms/Python/blob/master/quantum/quantum_entanglement.py) - * [Ripple Adder Classic](https://github.com/TheAlgorithms/Python/blob/master/quantum/ripple_adder_classic.py) - * [Single Qubit Measure](https://github.com/TheAlgorithms/Python/blob/master/quantum/single_qubit_measure.py) + * [Deutsch Jozsa](quantum/deutsch_jozsa.py) + * [Half Adder](quantum/half_adder.py) + * [Not Gate](quantum/not_gate.py) + * [Quantum Entanglement](quantum/quantum_entanglement.py) + * [Ripple Adder Classic](quantum/ripple_adder_classic.py) + * [Single Qubit Measure](quantum/single_qubit_measure.py) ## Scheduling - * [First Come First Served](https://github.com/TheAlgorithms/Python/blob/master/scheduling/first_come_first_served.py) - * [Round Robin](https://github.com/TheAlgorithms/Python/blob/master/scheduling/round_robin.py) - * [Shortest Job First](https://github.com/TheAlgorithms/Python/blob/master/scheduling/shortest_job_first.py) + * [First Come First Served](scheduling/first_come_first_served.py) + * [Multi Level Feedback Queue](scheduling/multi_level_feedback_queue.py) + * [Non Preemptive Shortest Job First](scheduling/non_preemptive_shortest_job_first.py) + * [Round Robin](scheduling/round_robin.py) + * [Shortest Job First](scheduling/shortest_job_first.py) ## Searches - * [Binary Search](https://github.com/TheAlgorithms/Python/blob/master/searches/binary_search.py) - * [Binary Tree Traversal](https://github.com/TheAlgorithms/Python/blob/master/searches/binary_tree_traversal.py) - * [Double Linear Search](https://github.com/TheAlgorithms/Python/blob/master/searches/double_linear_search.py) - * [Double Linear Search Recursion](https://github.com/TheAlgorithms/Python/blob/master/searches/double_linear_search_recursion.py) - * [Fibonacci Search](https://github.com/TheAlgorithms/Python/blob/master/searches/fibonacci_search.py) - * [Hill Climbing](https://github.com/TheAlgorithms/Python/blob/master/searches/hill_climbing.py) - * [Interpolation Search](https://github.com/TheAlgorithms/Python/blob/master/searches/interpolation_search.py) - * [Jump Search](https://github.com/TheAlgorithms/Python/blob/master/searches/jump_search.py) - * [Linear Search](https://github.com/TheAlgorithms/Python/blob/master/searches/linear_search.py) - * [Quick Select](https://github.com/TheAlgorithms/Python/blob/master/searches/quick_select.py) - * [Sentinel Linear Search](https://github.com/TheAlgorithms/Python/blob/master/searches/sentinel_linear_search.py) - * [Simple Binary Search](https://github.com/TheAlgorithms/Python/blob/master/searches/simple_binary_search.py) - * [Simulated Annealing](https://github.com/TheAlgorithms/Python/blob/master/searches/simulated_annealing.py) - * [Tabu Search](https://github.com/TheAlgorithms/Python/blob/master/searches/tabu_search.py) - * [Ternary Search](https://github.com/TheAlgorithms/Python/blob/master/searches/ternary_search.py) + * [Binary Search](searches/binary_search.py) + * [Binary Tree Traversal](searches/binary_tree_traversal.py) + * [Double Linear Search](searches/double_linear_search.py) + * [Double Linear Search Recursion](searches/double_linear_search_recursion.py) + * [Fibonacci Search](searches/fibonacci_search.py) + * [Hill Climbing](searches/hill_climbing.py) + * [Interpolation Search](searches/interpolation_search.py) + * [Jump Search](searches/jump_search.py) + * [Linear Search](searches/linear_search.py) + * [Quick Select](searches/quick_select.py) + * [Sentinel Linear Search](searches/sentinel_linear_search.py) + * [Simple Binary Search](searches/simple_binary_search.py) + * [Simulated Annealing](searches/simulated_annealing.py) + * [Tabu Search](searches/tabu_search.py) + * [Ternary Search](searches/ternary_search.py) ## Sorts - * [Bead Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/bead_sort.py) - * [Bitonic Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/bitonic_sort.py) - * [Bogo Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/bogo_sort.py) - * [Bubble Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/bubble_sort.py) - * [Bucket Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/bucket_sort.py) - * [Cocktail Shaker Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/cocktail_shaker_sort.py) - * [Comb Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/comb_sort.py) - * [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) - * [Heap Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/heap_sort.py) - * [Insertion Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/insertion_sort.py) - * [Intro Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/intro_sort.py) - * [Iterative Merge Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/iterative_merge_sort.py) - * [Merge Insertion Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/merge_insertion_sort.py) - * [Merge Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/merge_sort.py) - * [Msd Radix Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/msd_radix_sort.py) - * [Natural Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/natural_sort.py) - * [Odd Even Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/odd_even_sort.py) - * [Odd Even Transposition Parallel](https://github.com/TheAlgorithms/Python/blob/master/sorts/odd_even_transposition_parallel.py) - * [Odd Even Transposition Single Threaded](https://github.com/TheAlgorithms/Python/blob/master/sorts/odd_even_transposition_single_threaded.py) - * [Pancake Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/pancake_sort.py) - * [Patience Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/patience_sort.py) - * [Pigeon Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/pigeon_sort.py) - * [Pigeonhole Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/pigeonhole_sort.py) - * [Quick Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/quick_sort.py) - * [Quick Sort 3 Partition](https://github.com/TheAlgorithms/Python/blob/master/sorts/quick_sort_3_partition.py) - * [Radix Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/radix_sort.py) - * [Random Normal Distribution Quicksort](https://github.com/TheAlgorithms/Python/blob/master/sorts/random_normal_distribution_quicksort.py) - * [Random Pivot Quick Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/random_pivot_quick_sort.py) - * [Recursive Bubble Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/recursive_bubble_sort.py) - * [Recursive Insertion Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/recursive_insertion_sort.py) - * [Recursive Mergesort Array](https://github.com/TheAlgorithms/Python/blob/master/sorts/recursive_mergesort_array.py) - * [Recursive Quick Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/recursive_quick_sort.py) - * [Selection Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/selection_sort.py) - * [Shell Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/shell_sort.py) - * [Slowsort](https://github.com/TheAlgorithms/Python/blob/master/sorts/slowsort.py) - * [Stooge Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/stooge_sort.py) - * [Strand Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/strand_sort.py) - * [Tim Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/tim_sort.py) - * [Topological Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/topological_sort.py) - * [Tree Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/tree_sort.py) - * [Unknown Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/unknown_sort.py) - * [Wiggle Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/wiggle_sort.py) + * [Bead Sort](sorts/bead_sort.py) + * [Bitonic Sort](sorts/bitonic_sort.py) + * [Bogo Sort](sorts/bogo_sort.py) + * [Bubble Sort](sorts/bubble_sort.py) + * [Bucket Sort](sorts/bucket_sort.py) + * [Cocktail Shaker Sort](sorts/cocktail_shaker_sort.py) + * [Comb Sort](sorts/comb_sort.py) + * [Counting Sort](sorts/counting_sort.py) + * [Cycle Sort](sorts/cycle_sort.py) + * [Double Sort](sorts/double_sort.py) + * [Dutch National Flag Sort](sorts/dutch_national_flag_sort.py) + * [Exchange Sort](sorts/exchange_sort.py) + * [External Sort](sorts/external_sort.py) + * [Gnome Sort](sorts/gnome_sort.py) + * [Heap Sort](sorts/heap_sort.py) + * [Insertion Sort](sorts/insertion_sort.py) + * [Intro Sort](sorts/intro_sort.py) + * [Iterative Merge Sort](sorts/iterative_merge_sort.py) + * [Merge Insertion Sort](sorts/merge_insertion_sort.py) + * [Merge Sort](sorts/merge_sort.py) + * [Msd Radix Sort](sorts/msd_radix_sort.py) + * [Natural Sort](sorts/natural_sort.py) + * [Odd Even Sort](sorts/odd_even_sort.py) + * [Odd Even Transposition Parallel](sorts/odd_even_transposition_parallel.py) + * [Odd Even Transposition Single Threaded](sorts/odd_even_transposition_single_threaded.py) + * [Pancake Sort](sorts/pancake_sort.py) + * [Patience Sort](sorts/patience_sort.py) + * [Pigeon Sort](sorts/pigeon_sort.py) + * [Pigeonhole Sort](sorts/pigeonhole_sort.py) + * [Quick Sort](sorts/quick_sort.py) + * [Quick Sort 3 Partition](sorts/quick_sort_3_partition.py) + * [Radix Sort](sorts/radix_sort.py) + * [Random Normal Distribution Quicksort](sorts/random_normal_distribution_quicksort.py) + * [Random Pivot Quick Sort](sorts/random_pivot_quick_sort.py) + * [Recursive Bubble Sort](sorts/recursive_bubble_sort.py) + * [Recursive Insertion Sort](sorts/recursive_insertion_sort.py) + * [Recursive Mergesort Array](sorts/recursive_mergesort_array.py) + * [Recursive Quick Sort](sorts/recursive_quick_sort.py) + * [Selection Sort](sorts/selection_sort.py) + * [Shell Sort](sorts/shell_sort.py) + * [Slowsort](sorts/slowsort.py) + * [Stooge Sort](sorts/stooge_sort.py) + * [Strand Sort](sorts/strand_sort.py) + * [Tim Sort](sorts/tim_sort.py) + * [Topological Sort](sorts/topological_sort.py) + * [Tree Sort](sorts/tree_sort.py) + * [Unknown Sort](sorts/unknown_sort.py) + * [Wiggle Sort](sorts/wiggle_sort.py) ## Strings - * [Aho Corasick](https://github.com/TheAlgorithms/Python/blob/master/strings/aho_corasick.py) - * [Alternative String Arrange](https://github.com/TheAlgorithms/Python/blob/master/strings/alternative_string_arrange.py) - * [Anagrams](https://github.com/TheAlgorithms/Python/blob/master/strings/anagrams.py) - * [Autocomplete Using Trie](https://github.com/TheAlgorithms/Python/blob/master/strings/autocomplete_using_trie.py) - * [Boyer Moore Search](https://github.com/TheAlgorithms/Python/blob/master/strings/boyer_moore_search.py) - * [Can String Be Rearranged As Palindrome](https://github.com/TheAlgorithms/Python/blob/master/strings/can_string_be_rearranged_as_palindrome.py) - * [Capitalize](https://github.com/TheAlgorithms/Python/blob/master/strings/capitalize.py) - * [Check Anagrams](https://github.com/TheAlgorithms/Python/blob/master/strings/check_anagrams.py) - * [Check Pangram](https://github.com/TheAlgorithms/Python/blob/master/strings/check_pangram.py) - * [Credit Card Validator](https://github.com/TheAlgorithms/Python/blob/master/strings/credit_card_validator.py) - * [Detecting English Programmatically](https://github.com/TheAlgorithms/Python/blob/master/strings/detecting_english_programmatically.py) - * [Frequency Finder](https://github.com/TheAlgorithms/Python/blob/master/strings/frequency_finder.py) - * [Indian Phone Validator](https://github.com/TheAlgorithms/Python/blob/master/strings/indian_phone_validator.py) - * [Is Contains Unique Chars](https://github.com/TheAlgorithms/Python/blob/master/strings/is_contains_unique_chars.py) - * [Is Palindrome](https://github.com/TheAlgorithms/Python/blob/master/strings/is_palindrome.py) - * [Jaro Winkler](https://github.com/TheAlgorithms/Python/blob/master/strings/jaro_winkler.py) - * [Join](https://github.com/TheAlgorithms/Python/blob/master/strings/join.py) - * [Knuth Morris Pratt](https://github.com/TheAlgorithms/Python/blob/master/strings/knuth_morris_pratt.py) - * [Levenshtein Distance](https://github.com/TheAlgorithms/Python/blob/master/strings/levenshtein_distance.py) - * [Lower](https://github.com/TheAlgorithms/Python/blob/master/strings/lower.py) - * [Manacher](https://github.com/TheAlgorithms/Python/blob/master/strings/manacher.py) - * [Min Cost String Conversion](https://github.com/TheAlgorithms/Python/blob/master/strings/min_cost_string_conversion.py) - * [Naive String Search](https://github.com/TheAlgorithms/Python/blob/master/strings/naive_string_search.py) - * [Ngram](https://github.com/TheAlgorithms/Python/blob/master/strings/ngram.py) - * [Palindrome](https://github.com/TheAlgorithms/Python/blob/master/strings/palindrome.py) - * [Prefix Function](https://github.com/TheAlgorithms/Python/blob/master/strings/prefix_function.py) - * [Rabin Karp](https://github.com/TheAlgorithms/Python/blob/master/strings/rabin_karp.py) - * [Remove Duplicate](https://github.com/TheAlgorithms/Python/blob/master/strings/remove_duplicate.py) - * [Reverse Letters](https://github.com/TheAlgorithms/Python/blob/master/strings/reverse_letters.py) - * [Reverse Long Words](https://github.com/TheAlgorithms/Python/blob/master/strings/reverse_long_words.py) - * [Reverse Words](https://github.com/TheAlgorithms/Python/blob/master/strings/reverse_words.py) - * [Split](https://github.com/TheAlgorithms/Python/blob/master/strings/split.py) - * [Upper](https://github.com/TheAlgorithms/Python/blob/master/strings/upper.py) - * [Wildcard Pattern Matching](https://github.com/TheAlgorithms/Python/blob/master/strings/wildcard_pattern_matching.py) - * [Word Occurrence](https://github.com/TheAlgorithms/Python/blob/master/strings/word_occurrence.py) - * [Word Patterns](https://github.com/TheAlgorithms/Python/blob/master/strings/word_patterns.py) - * [Z Function](https://github.com/TheAlgorithms/Python/blob/master/strings/z_function.py) + * [Aho Corasick](strings/aho_corasick.py) + * [Alternative String Arrange](strings/alternative_string_arrange.py) + * [Anagrams](strings/anagrams.py) + * [Autocomplete Using Trie](strings/autocomplete_using_trie.py) + * [Boyer Moore Search](strings/boyer_moore_search.py) + * [Can String Be Rearranged As Palindrome](strings/can_string_be_rearranged_as_palindrome.py) + * [Capitalize](strings/capitalize.py) + * [Check Anagrams](strings/check_anagrams.py) + * [Check Pangram](strings/check_pangram.py) + * [Credit Card Validator](strings/credit_card_validator.py) + * [Detecting English Programmatically](strings/detecting_english_programmatically.py) + * [Frequency Finder](strings/frequency_finder.py) + * [Indian Phone Validator](strings/indian_phone_validator.py) + * [Is Contains Unique Chars](strings/is_contains_unique_chars.py) + * [Is Palindrome](strings/is_palindrome.py) + * [Jaro Winkler](strings/jaro_winkler.py) + * [Join](strings/join.py) + * [Knuth Morris Pratt](strings/knuth_morris_pratt.py) + * [Levenshtein Distance](strings/levenshtein_distance.py) + * [Lower](strings/lower.py) + * [Manacher](strings/manacher.py) + * [Min Cost String Conversion](strings/min_cost_string_conversion.py) + * [Naive String Search](strings/naive_string_search.py) + * [Ngram](strings/ngram.py) + * [Palindrome](strings/palindrome.py) + * [Prefix Function](strings/prefix_function.py) + * [Rabin Karp](strings/rabin_karp.py) + * [Remove Duplicate](strings/remove_duplicate.py) + * [Reverse Letters](strings/reverse_letters.py) + * [Reverse Long Words](strings/reverse_long_words.py) + * [Reverse Words](strings/reverse_words.py) + * [Split](strings/split.py) + * [Upper](strings/upper.py) + * [Wildcard Pattern Matching](strings/wildcard_pattern_matching.py) + * [Word Occurrence](strings/word_occurrence.py) + * [Word Patterns](strings/word_patterns.py) + * [Z Function](strings/z_function.py) ## Web Programming - * [Co2 Emission](https://github.com/TheAlgorithms/Python/blob/master/web_programming/co2_emission.py) - * [Covid Stats Via Xpath](https://github.com/TheAlgorithms/Python/blob/master/web_programming/covid_stats_via_xpath.py) - * [Crawl Google Results](https://github.com/TheAlgorithms/Python/blob/master/web_programming/crawl_google_results.py) - * [Crawl Google Scholar Citation](https://github.com/TheAlgorithms/Python/blob/master/web_programming/crawl_google_scholar_citation.py) - * [Currency Converter](https://github.com/TheAlgorithms/Python/blob/master/web_programming/currency_converter.py) - * [Current Stock Price](https://github.com/TheAlgorithms/Python/blob/master/web_programming/current_stock_price.py) - * [Current Weather](https://github.com/TheAlgorithms/Python/blob/master/web_programming/current_weather.py) - * [Daily Horoscope](https://github.com/TheAlgorithms/Python/blob/master/web_programming/daily_horoscope.py) - * [Download Images From Google Query](https://github.com/TheAlgorithms/Python/blob/master/web_programming/download_images_from_google_query.py) - * [Emails From Url](https://github.com/TheAlgorithms/Python/blob/master/web_programming/emails_from_url.py) - * [Fetch Anime And Play](https://github.com/TheAlgorithms/Python/blob/master/web_programming/fetch_anime_and_play.py) - * [Fetch Bbc News](https://github.com/TheAlgorithms/Python/blob/master/web_programming/fetch_bbc_news.py) - * [Fetch Github Info](https://github.com/TheAlgorithms/Python/blob/master/web_programming/fetch_github_info.py) - * [Fetch Jobs](https://github.com/TheAlgorithms/Python/blob/master/web_programming/fetch_jobs.py) - * [Fetch Well Rx Price](https://github.com/TheAlgorithms/Python/blob/master/web_programming/fetch_well_rx_price.py) - * [Get Imdb Top 250 Movies Csv](https://github.com/TheAlgorithms/Python/blob/master/web_programming/get_imdb_top_250_movies_csv.py) - * [Get Imdbtop](https://github.com/TheAlgorithms/Python/blob/master/web_programming/get_imdbtop.py) - * [Get Top Hn Posts](https://github.com/TheAlgorithms/Python/blob/master/web_programming/get_top_hn_posts.py) - * [Get User Tweets](https://github.com/TheAlgorithms/Python/blob/master/web_programming/get_user_tweets.py) - * [Giphy](https://github.com/TheAlgorithms/Python/blob/master/web_programming/giphy.py) - * [Instagram Crawler](https://github.com/TheAlgorithms/Python/blob/master/web_programming/instagram_crawler.py) - * [Instagram Pic](https://github.com/TheAlgorithms/Python/blob/master/web_programming/instagram_pic.py) - * [Instagram Video](https://github.com/TheAlgorithms/Python/blob/master/web_programming/instagram_video.py) - * [Nasa Data](https://github.com/TheAlgorithms/Python/blob/master/web_programming/nasa_data.py) - * [Random Anime Character](https://github.com/TheAlgorithms/Python/blob/master/web_programming/random_anime_character.py) - * [Recaptcha Verification](https://github.com/TheAlgorithms/Python/blob/master/web_programming/recaptcha_verification.py) - * [Reddit](https://github.com/TheAlgorithms/Python/blob/master/web_programming/reddit.py) - * [Search Books By Isbn](https://github.com/TheAlgorithms/Python/blob/master/web_programming/search_books_by_isbn.py) - * [Slack Message](https://github.com/TheAlgorithms/Python/blob/master/web_programming/slack_message.py) - * [Test Fetch Github Info](https://github.com/TheAlgorithms/Python/blob/master/web_programming/test_fetch_github_info.py) - * [World Covid19 Stats](https://github.com/TheAlgorithms/Python/blob/master/web_programming/world_covid19_stats.py) + * [Co2 Emission](web_programming/co2_emission.py) + * [Covid Stats Via Xpath](web_programming/covid_stats_via_xpath.py) + * [Crawl Google Results](web_programming/crawl_google_results.py) + * [Crawl Google Scholar Citation](web_programming/crawl_google_scholar_citation.py) + * [Currency Converter](web_programming/currency_converter.py) + * [Current Stock Price](web_programming/current_stock_price.py) + * [Current Weather](web_programming/current_weather.py) + * [Daily Horoscope](web_programming/daily_horoscope.py) + * [Download Images From Google Query](web_programming/download_images_from_google_query.py) + * [Emails From Url](web_programming/emails_from_url.py) + * [Fetch Anime And Play](web_programming/fetch_anime_and_play.py) + * [Fetch Bbc News](web_programming/fetch_bbc_news.py) + * [Fetch Github Info](web_programming/fetch_github_info.py) + * [Fetch Jobs](web_programming/fetch_jobs.py) + * [Fetch Well Rx Price](web_programming/fetch_well_rx_price.py) + * [Get Imdb Top 250 Movies Csv](web_programming/get_imdb_top_250_movies_csv.py) + * [Get Imdbtop](web_programming/get_imdbtop.py) + * [Get Top Hn Posts](web_programming/get_top_hn_posts.py) + * [Get User Tweets](web_programming/get_user_tweets.py) + * [Giphy](web_programming/giphy.py) + * [Instagram Crawler](web_programming/instagram_crawler.py) + * [Instagram Pic](web_programming/instagram_pic.py) + * [Instagram Video](web_programming/instagram_video.py) + * [Nasa Data](web_programming/nasa_data.py) + * [Random Anime Character](web_programming/random_anime_character.py) + * [Recaptcha Verification](web_programming/recaptcha_verification.py) + * [Reddit](web_programming/reddit.py) + * [Search Books By Isbn](web_programming/search_books_by_isbn.py) + * [Slack Message](web_programming/slack_message.py) + * [Test Fetch Github Info](web_programming/test_fetch_github_info.py) + * [World Covid19 Stats](web_programming/world_covid19_stats.py) diff --git a/scripts/build_directory_md.py b/scripts/build_directory_md.py index 7a4bc3a4b..71577fe6d 100755 --- a/scripts/build_directory_md.py +++ b/scripts/build_directory_md.py @@ -3,8 +3,6 @@ import os from typing import Iterator -URL_BASE = "https://github.com/TheAlgorithms/Python/blob/master" - def good_file_paths(top_dir: str = ".") -> Iterator[str]: for dir_path, dir_names, filenames in os.walk(top_dir): @@ -36,7 +34,7 @@ def print_directory_md(top_dir: str = ".") -> None: if filepath != old_path: old_path = print_path(old_path, filepath) indent = (filepath.count(os.sep) + 1) if filepath else 0 - url = "/".join((URL_BASE, filepath, filename)).replace(" ", "%20") + url = "/".join((filepath, filename)).replace(" ", "%20") filename = os.path.splitext(filename.replace("_", " ").title())[0] print(f"{md_prefix(indent)} [{filename}]({url})") From 42a80cdaf689b03b326164862318039bd43bbff1 Mon Sep 17 00:00:00 2001 From: Nivid Patel <66813410+nivid26@users.noreply.github.com> Date: Wed, 22 Jun 2022 00:04:18 -0400 Subject: [PATCH 278/726] Update basic_maths.py (#6017) --- maths/basic_maths.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/maths/basic_maths.py b/maths/basic_maths.py index 58e797772..26c52c549 100644 --- a/maths/basic_maths.py +++ b/maths/basic_maths.py @@ -57,6 +57,8 @@ def number_of_divisors(n: int) -> int: temp += 1 n = int(n / i) div *= temp + if n > 1: + div *= 2 return div From a80e5aadf30817251989378e8d908ca18f733a2f Mon Sep 17 00:00:00 2001 From: yulmam <70622601+yulmam@users.noreply.github.com> Date: Wed, 22 Jun 2022 13:23:52 +0900 Subject: [PATCH 279/726] add highest_response_ratio_next.py (#6183) * add highest_response_ratio_next.py * Update highest_response_ratio_next.py * Update highest_response_ratio_next.py --- scheduling/highest_response_ratio_next.py | 118 ++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 scheduling/highest_response_ratio_next.py diff --git a/scheduling/highest_response_ratio_next.py b/scheduling/highest_response_ratio_next.py new file mode 100644 index 000000000..a5c62ddbe --- /dev/null +++ b/scheduling/highest_response_ratio_next.py @@ -0,0 +1,118 @@ +""" +Highest response ratio next (HRRN) scheduling is a non-preemptive discipline. +It was developed as modification of shortest job next or shortest job first (SJN or SJF) +to mitigate the problem of process starvation. +https://en.wikipedia.org/wiki/Highest_response_ratio_next +""" +from statistics import mean + +import numpy as np + + +def calculate_turn_around_time( + process_name: list, arrival_time: list, burst_time: list, no_of_process: int +) -> list: + """ + Calculate the turn around time of each processes + + Return: The turn around time time for each process. + >>> calculate_turn_around_time(["A", "B", "C"], [3, 5, 8], [2, 4, 6], 3) + [2, 4, 7] + >>> calculate_turn_around_time(["A", "B", "C"], [0, 2, 4], [3, 5, 7], 3) + [3, 6, 11] + """ + + current_time = 0 + # Number of processes finished + finished_process_count = 0 + # Displays the finished process. + # If it is 0, the performance is completed if it is 1, before the performance. + finished_process = [0] * no_of_process + # List to include calculation results + turn_around_time = [0] * no_of_process + + # Sort by arrival time. + burst_time = [burst_time[i] for i in np.argsort(arrival_time)] + process_name = [process_name[i] for i in np.argsort(arrival_time)] + arrival_time.sort() + + while no_of_process > finished_process_count: + + """ + If the current time is less than the arrival time of + the process that arrives first among the processes that have not been performed, + change the current time. + """ + i = 0 + while finished_process[i] == 1: + i += 1 + if current_time < arrival_time[i]: + current_time = arrival_time[i] + + response_ratio = 0 + # Index showing the location of the process being performed + loc = 0 + # Saves the current response ratio. + temp = 0 + for i in range(0, no_of_process): + if finished_process[i] == 0 and arrival_time[i] <= current_time: + temp = (burst_time[i] + (current_time - arrival_time[i])) / burst_time[ + i + ] + if response_ratio < temp: + response_ratio = temp + loc = i + + # Calculate the turn around time + turn_around_time[loc] = current_time + burst_time[loc] - arrival_time[loc] + current_time += burst_time[loc] + # Indicates that the process has been performed. + finished_process[loc] = 1 + # Increase finished_process_count by 1 + finished_process_count += 1 + + return turn_around_time + + +def calculate_waiting_time( + process_name: list, turn_around_time: list, burst_time: list, no_of_process: int +) -> list: + """ + Calculate the waiting time of each processes. + + Return: The waiting time for each process. + >>> calculate_waiting_time(["A", "B", "C"], [2, 4, 7], [2, 4, 6], 3) + [0, 0, 1] + >>> calculate_waiting_time(["A", "B", "C"], [3, 6, 11], [3, 5, 7], 3) + [0, 1, 4] + """ + + waiting_time = [0] * no_of_process + for i in range(0, no_of_process): + waiting_time[i] = turn_around_time[i] - burst_time[i] + return waiting_time + + +if __name__ == "__main__": + + no_of_process = 5 + process_name = ["A", "B", "C", "D", "E"] + arrival_time = [1, 2, 3, 4, 5] + burst_time = [1, 2, 3, 4, 5] + + turn_around_time = calculate_turn_around_time( + process_name, arrival_time, burst_time, no_of_process + ) + waiting_time = calculate_waiting_time( + process_name, turn_around_time, burst_time, no_of_process + ) + + print("Process name \tArrival time \tBurst time \tTurn around time \tWaiting time") + for i in range(0, no_of_process): + print( + f"{process_name[i]}\t\t{arrival_time[i]}\t\t{burst_time[i]}\t\t" + f"{turn_around_time[i]}\t\t\t{waiting_time[i]}" + ) + + print(f"average waiting time : {mean(waiting_time):.5f}") + print(f"average turn around time : {mean(turn_around_time):.5f}") From 04bc8f01dd81b8f4ca68e470d046fcb571b4d3d0 Mon Sep 17 00:00:00 2001 From: Margaret <62753112+meg-1@users.noreply.github.com> Date: Thu, 23 Jun 2022 19:47:29 +0300 Subject: [PATCH 280/726] Wave (#6061) * Added censor function * Added censor code * Added comments to the code * modified censor function * added decrypt function * added cypher and decypher functions, deleted censor and decrypt functions * Deleted decrypt.py * Deleted censor.py * edited the crypt and decrypt files * Update cypher_txt.py * Remove the endline in cypher.py * Removed the print at the end of decypher.py * added 4 new algorithms * added tests to the four files * added type hints for the function variables * Deleted decode message * Deleted code message * Welford average algorithm * added average welford algorithm * is_narcissistic added * added a descriptive name * added max_sectors algorithm * added find_unique * added wave algorithm * deleting average_welford [ in the wrong pr ] * deleting is_narcissistic [ is in the wrong pr ] * deleting max_sectors [ is in the wrong pr ] * deleting find_unique [ is in the wrong pr ] * deleting censor [ is in the wrong pr ] * deleting decrypt [ is in the wrong pr ] * fixed wave.py fixed indentation and followed the bots reccomendations * fixed wave.py again * fixing wave.py for the third time. * fixing wave.py * merging strings/wave.py merging the suggestion Co-authored-by: John Law Co-authored-by: John Law --- strings/wave.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 strings/wave.py diff --git a/strings/wave.py b/strings/wave.py new file mode 100644 index 000000000..69d534432 --- /dev/null +++ b/strings/wave.py @@ -0,0 +1,20 @@ +def wave(txt: str) -> list: + """ + Returns a so called 'wave' of a given string + >>> wave('cat') + ['Cat', 'cAt', 'caT'] + >>> wave('one') + ['One', 'oNe', 'onE'] + >>> wave('book') + ['Book', 'bOok', 'boOk', 'booK'] + """ + + return [ + txt[:a] + txt[a].upper() + txt[a + 1 :] + for a in range(len(txt)) + if txt[a].isalpha() + ] + + +if __name__ == "__main__": + __import__("doctest").testmod() From 4a51244e0feee90c8a80d6516628c9acb69c40b3 Mon Sep 17 00:00:00 2001 From: Erik Parmann Date: Thu, 23 Jun 2022 19:00:55 +0200 Subject: [PATCH 281/726] Remove how-to example for support vector machine (#6201) --- machine_learning/support_vector_machines.py | 58 --------------------- 1 file changed, 58 deletions(-) delete mode 100644 machine_learning/support_vector_machines.py diff --git a/machine_learning/support_vector_machines.py b/machine_learning/support_vector_machines.py deleted file mode 100644 index c5e5085d8..000000000 --- a/machine_learning/support_vector_machines.py +++ /dev/null @@ -1,58 +0,0 @@ -from sklearn import svm -from sklearn.datasets import load_iris -from sklearn.model_selection import train_test_split - - -# different functions implementing different types of SVM's -def NuSVC(train_x, train_y): - svc_NuSVC = svm.NuSVC() - svc_NuSVC.fit(train_x, train_y) - return svc_NuSVC - - -def Linearsvc(train_x, train_y): - svc_linear = svm.LinearSVC(tol=10e-2) - svc_linear.fit(train_x, train_y) - return svc_linear - - -def SVC(train_x, train_y): - # svm.SVC(C=1.0, kernel='rbf', degree=3, gamma=0.0, coef0=0.0, shrinking=True, - # probability=False,tol=0.001, cache_size=200, class_weight=None, verbose=False, - # max_iter=1000, random_state=None) - # various parameters like "kernel","gamma","C" can effectively tuned for a given - # machine learning model. - SVC = svm.SVC(gamma="auto") - SVC.fit(train_x, train_y) - return SVC - - -def test(X_new): - """ - 3 test cases to be passed - an array containing the sepal length (cm), sepal width (cm), petal length (cm), - petal width (cm) based on which the target name will be predicted - >>> test([1,2,1,4]) - 'virginica' - >>> test([5, 2, 4, 1]) - 'versicolor' - >>> test([6,3,4,1]) - 'versicolor' - """ - iris = load_iris() - # splitting the dataset to test and train - train_x, test_x, train_y, test_y = train_test_split( - iris["data"], iris["target"], random_state=4 - ) - # any of the 3 types of SVM can be used - # current_model=SVC(train_x, train_y) - # current_model=NuSVC(train_x, train_y) - current_model = Linearsvc(train_x, train_y) - prediction = current_model.predict([X_new]) - return iris["target_names"][prediction][0] - - -if __name__ == "__main__": - import doctest - - doctest.testmod() From e5d1ff2ea8c3820343c46fd08b089207f75ca03d Mon Sep 17 00:00:00 2001 From: lovetodevelop <103916828+lovetodevelop@users.noreply.github.com> Date: Sun, 3 Jul 2022 09:28:53 -0700 Subject: [PATCH 282/726] Fix tiny spelling error (#6219) --- ciphers/enigma_machine2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ciphers/enigma_machine2.py b/ciphers/enigma_machine2.py index 70f84752d..9f9dbe6f7 100644 --- a/ciphers/enigma_machine2.py +++ b/ciphers/enigma_machine2.py @@ -8,7 +8,7 @@ the famous Enigma machine from WWII. Module includes: - enigma function - showcase of function usage -- 9 randnomly generated rotors +- 9 randomly generated rotors - reflector (aka static rotor) - original alphabet From 89fc7bf0b024e4c9508db80f575efd5b5616f932 Mon Sep 17 00:00:00 2001 From: Sedat Aybars Nazlica Date: Wed, 6 Jul 2022 16:19:13 +0900 Subject: [PATCH 283/726] Add hamming distance (#6194) * Add hamming distance * Fix doctest * Refactor * Raise ValueError when string lengths are different --- strings/hamming_distance.py | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 strings/hamming_distance.py diff --git a/strings/hamming_distance.py b/strings/hamming_distance.py new file mode 100644 index 000000000..b8feaef06 --- /dev/null +++ b/strings/hamming_distance.py @@ -0,0 +1,39 @@ +def hamming_distance(string1: str, string2: str) -> int: + """Calculate the Hamming distance between two equal length strings + In information theory, the Hamming distance between two strings of equal + length is the number of positions at which the corresponding symbols are + different. https://en.wikipedia.org/wiki/Hamming_distance + + Args: + string1 (str): Sequence 1 + string2 (str): Sequence 2 + + Returns: + int: Hamming distance + + >>> hamming_distance("python", "python") + 0 + >>> hamming_distance("karolin", "kathrin") + 3 + >>> hamming_distance("00000", "11111") + 5 + >>> hamming_distance("karolin", "kath") + ValueError: String lengths must match! + """ + if len(string1) != len(string2): + raise ValueError("String lengths must match!") + + count = 0 + + for char1, char2 in zip(string1, string2): + if char1 != char2: + count += 1 + + return count + + +if __name__ == "__main__": + + import doctest + + doctest.testmod() From 9135a1f41192ebe1d835282a1465dc284359d95c Mon Sep 17 00:00:00 2001 From: John Law Date: Wed, 6 Jul 2022 16:00:05 +0800 Subject: [PATCH 284/726] Fix doctests and builds in various files (#6233) * Fix doctest in hamming distance * add line break * try to fix quantum_riper_adder * fix floating point build --- arithmetic_analysis/in_static_equilibrium.py | 7 +++++-- quantum/ripple_adder_classic.py | 4 ++-- strings/hamming_distance.py | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/arithmetic_analysis/in_static_equilibrium.py b/arithmetic_analysis/in_static_equilibrium.py index d762a376f..7aaecf174 100644 --- a/arithmetic_analysis/in_static_equilibrium.py +++ b/arithmetic_analysis/in_static_equilibrium.py @@ -19,8 +19,11 @@ def polar_force( True >>> math.isclose(force[1], 7.0710678118654755) True - >>> polar_force(10, 3.14, radian_mode=True) - [-9.999987317275396, 0.01592652916486828] + >>> force = polar_force(10, 3.14, radian_mode=True) + >>> math.isclose(force[0], -9.999987317275396) + True + >>> math.isclose(force[1], 0.01592652916486828) + True """ if radian_mode: return [magnitude * cos(angle), magnitude * sin(angle)] diff --git a/quantum/ripple_adder_classic.py b/quantum/ripple_adder_classic.py index 8539a62af..1d3724476 100644 --- a/quantum/ripple_adder_classic.py +++ b/quantum/ripple_adder_classic.py @@ -3,7 +3,7 @@ # https://en.wikipedia.org/wiki/Controlled_NOT_gate from qiskit import Aer, QuantumCircuit, execute -from qiskit.providers import BaseBackend +from qiskit.providers import Backend def store_two_classics(val1: int, val2: int) -> tuple[QuantumCircuit, str, str]: @@ -62,7 +62,7 @@ def full_adder( def ripple_adder( val1: int, val2: int, - backend: BaseBackend = Aer.get_backend("qasm_simulator"), # noqa: B008 + backend: Backend = Aer.get_backend("qasm_simulator"), # noqa: B008 ) -> int: """ Quantum Equivalent of a Ripple Adder Circuit diff --git a/strings/hamming_distance.py b/strings/hamming_distance.py index b8feaef06..5de27dc77 100644 --- a/strings/hamming_distance.py +++ b/strings/hamming_distance.py @@ -18,6 +18,8 @@ def hamming_distance(string1: str, string2: str) -> int: >>> hamming_distance("00000", "11111") 5 >>> hamming_distance("karolin", "kath") + Traceback (most recent call last): + ... ValueError: String lengths must match! """ if len(string1) != len(string2): From 0a0f4986e4fde05ebc2a24c9cc2cd6b8200b8df1 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 7 Jul 2022 05:25:25 +0200 Subject: [PATCH 285/726] Upgrade GitHub Actions (#6236) * Upgrade GitHub Actions * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .github/workflows/build.yml | 8 ++++---- .github/workflows/directory_writer.yml | 6 ++++-- .github/workflows/pre-commit.yml | 10 +++++----- .github/workflows/project_euler.yml | 12 ++++++++---- .pre-commit-config.yaml | 8 ++++---- DIRECTORY.md | 4 +++- 6 files changed, 28 insertions(+), 20 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 403ec44c8..8481b962a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,11 +9,11 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 with: - python-version: "3.10" - - uses: actions/cache@v2 + python-version: 3.x + - uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }} diff --git a/.github/workflows/directory_writer.yml b/.github/workflows/directory_writer.yml index be8154a32..331962cef 100644 --- a/.github/workflows/directory_writer.yml +++ b/.github/workflows/directory_writer.yml @@ -6,8 +6,10 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 # v1, NOT v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v1 # v1, NOT v2 or v3 + - uses: actions/setup-python@v4 + with: + python-version: 3.x - name: Write DIRECTORY.md run: | scripts/build_directory_md.py 2>&1 | tee DIRECTORY.md diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index de73c96ad..3b128bc54 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -6,17 +6,17 @@ jobs: pre-commit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/cache@v2 + - uses: actions/checkout@v3 + - uses: actions/cache@v3 with: path: | ~/.cache/pre-commit ~/.cache/pip key: ${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4 with: - python-version: "3.10" - - uses: psf/black@21.4b0 + python-version: 3.x + # - uses: psf/black@22.6.0 - name: Install pre-commit run: | python -m pip install --upgrade pip diff --git a/.github/workflows/project_euler.yml b/.github/workflows/project_euler.yml index 995295fca..460938219 100644 --- a/.github/workflows/project_euler.yml +++ b/.github/workflows/project_euler.yml @@ -14,8 +14,10 @@ jobs: project-euler: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: 3.x - name: Install pytest and pytest-cov run: | python -m pip install --upgrade pip @@ -24,8 +26,10 @@ jobs: validate-solutions: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: 3.x - name: Install pytest and requests run: | python -m pip install --upgrade pip diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 33da02fb7..90feb50ff 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.1.0 + rev: v4.3.0 hooks: - id: check-executables-have-shebangs - id: check-yaml @@ -14,7 +14,7 @@ repos: - id: requirements-txt-fixer - repo: https://github.com/psf/black - rev: 22.3.0 + rev: 22.6.0 hooks: - id: black @@ -26,7 +26,7 @@ repos: - --profile=black - repo: https://github.com/asottile/pyupgrade - rev: v2.31.0 + rev: v2.34.0 hooks: - id: pyupgrade args: @@ -42,7 +42,7 @@ repos: - --max-line-length=88 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.931 + rev: v0.961 hooks: - id: mypy args: diff --git a/DIRECTORY.md b/DIRECTORY.md index d30e275d0..2e9c03cbc 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -444,7 +444,6 @@ * [Scoring Functions](machine_learning/scoring_functions.py) * [Sequential Minimum Optimization](machine_learning/sequential_minimum_optimization.py) * [Similarity Search](machine_learning/similarity_search.py) - * [Support Vector Machines](machine_learning/support_vector_machines.py) * [Word Frequency Functions](machine_learning/word_frequency_functions.py) ## Maths @@ -910,6 +909,7 @@ ## Scheduling * [First Come First Served](scheduling/first_come_first_served.py) + * [Highest Response Ratio Next](scheduling/highest_response_ratio_next.py) * [Multi Level Feedback Queue](scheduling/multi_level_feedback_queue.py) * [Non Preemptive Shortest Job First](scheduling/non_preemptive_shortest_job_first.py) * [Round Robin](scheduling/round_robin.py) @@ -995,6 +995,7 @@ * [Credit Card Validator](strings/credit_card_validator.py) * [Detecting English Programmatically](strings/detecting_english_programmatically.py) * [Frequency Finder](strings/frequency_finder.py) + * [Hamming Distance](strings/hamming_distance.py) * [Indian Phone Validator](strings/indian_phone_validator.py) * [Is Contains Unique Chars](strings/is_contains_unique_chars.py) * [Is Palindrome](strings/is_palindrome.py) @@ -1016,6 +1017,7 @@ * [Reverse Words](strings/reverse_words.py) * [Split](strings/split.py) * [Upper](strings/upper.py) + * [Wave](strings/wave.py) * [Wildcard Pattern Matching](strings/wildcard_pattern_matching.py) * [Word Occurrence](strings/word_occurrence.py) * [Word Patterns](strings/word_patterns.py) From 2d5dd6f132a25165473471bf83765ec50c9f14d6 Mon Sep 17 00:00:00 2001 From: Vardhaman <83634399+cyai@users.noreply.github.com> Date: Thu, 7 Jul 2022 20:04:07 +0530 Subject: [PATCH 286/726] MAINT: Updated f-string method (#6230) * MAINT: Used f-string method Updated the code with f-string methods wherever required for a better and cleaner understanding of the code. * Updated files with f-string method * Update rsa_key_generator.py * Update rsa_key_generator.py * Update elgamal_key_generator.py * Update lru_cache.py I don't think this change is efficient but it might tackle the error as the error was due to using long character lines. * Update lru_cache.py * Update lru_cache.py Co-authored-by: cyai Co-authored-by: Christian Clauss --- ciphers/elgamal_key_generator.py | 12 +++++------- ciphers/rsa_cipher.py | 4 ++-- ciphers/rsa_key_generator.py | 12 +++++------- ciphers/transposition_cipher.py | 4 ++-- ciphers/transposition_cipher_encrypt_decrypt_file.py | 4 ++-- ciphers/vigenere_cipher.py | 2 +- data_structures/binary_tree/binary_search_tree.py | 2 +- hashes/chaos_machine.py | 2 +- machine_learning/gradient_boosting_regressor.py | 4 ++-- machine_learning/k_means_clust.py | 4 +--- machine_learning/linear_regression.py | 2 +- matrix/sherman_morrison.py | 2 +- neural_network/convolution_neural_network.py | 4 ++-- other/lru_cache.py | 5 +++-- other/scoring_algorithm.py | 2 +- scheduling/shortest_job_first.py | 2 +- searches/binary_tree_traversal.py | 4 ++-- strings/min_cost_string_conversion.py | 12 ++++++------ 18 files changed, 39 insertions(+), 44 deletions(-) diff --git a/ciphers/elgamal_key_generator.py b/ciphers/elgamal_key_generator.py index f557b0e0d..485b77595 100644 --- a/ciphers/elgamal_key_generator.py +++ b/ciphers/elgamal_key_generator.py @@ -38,9 +38,7 @@ def generate_key(key_size: int) -> tuple[tuple[int, int, int, int], tuple[int, i def make_key_files(name: str, keySize: int) -> None: - if os.path.exists("%s_pubkey.txt" % name) or os.path.exists( - "%s_privkey.txt" % name - ): + if os.path.exists(f"{name}_pubkey.txt") or os.path.exists(f"{name}_privkey.txt"): print("\nWARNING:") print( '"%s_pubkey.txt" or "%s_privkey.txt" already exists. \n' @@ -50,14 +48,14 @@ def make_key_files(name: str, keySize: int) -> None: sys.exit() publicKey, privateKey = generate_key(keySize) - print("\nWriting public key to file %s_pubkey.txt..." % name) - with open("%s_pubkey.txt" % name, "w") as fo: + print(f"\nWriting public key to file {name}_pubkey.txt...") + with open(f"{name}_pubkey.txt", "w") as fo: fo.write( "%d,%d,%d,%d" % (publicKey[0], publicKey[1], publicKey[2], publicKey[3]) ) - print("Writing private key to file %s_privkey.txt..." % name) - with open("%s_privkey.txt" % name, "w") as fo: + print(f"Writing private key to file {name}_privkey.txt...") + with open(f"{name}_privkey.txt", "w") as fo: fo.write("%d,%d" % (privateKey[0], privateKey[1])) diff --git a/ciphers/rsa_cipher.py b/ciphers/rsa_cipher.py index 5bb9f9916..c6bfaa0fb 100644 --- a/ciphers/rsa_cipher.py +++ b/ciphers/rsa_cipher.py @@ -129,7 +129,7 @@ def main() -> None: message = input("\nEnter message: ") pubkey_filename = "rsa_pubkey.txt" - print("Encrypting and writing to %s..." % (filename)) + print(f"Encrypting and writing to {filename}...") encryptedText = encrypt_and_write_to_file(filename, pubkey_filename, message) print("\nEncrypted text:") @@ -137,7 +137,7 @@ def main() -> None: elif mode == "decrypt": privkey_filename = "rsa_privkey.txt" - print("Reading from %s and decrypting..." % (filename)) + print(f"Reading from {filename} and decrypting...") decrypted_text = read_from_file_and_decrypt(filename, privkey_filename) print("writing decryption to rsa_decryption.txt...") with open("rsa_decryption.txt", "w") as dec: diff --git a/ciphers/rsa_key_generator.py b/ciphers/rsa_key_generator.py index 584066d89..d983c14f1 100644 --- a/ciphers/rsa_key_generator.py +++ b/ciphers/rsa_key_generator.py @@ -34,9 +34,7 @@ def generateKey(keySize: int) -> tuple[tuple[int, int], tuple[int, int]]: def makeKeyFiles(name: str, keySize: int) -> None: - if os.path.exists("%s_pubkey.txt" % (name)) or os.path.exists( - "%s_privkey.txt" % (name) - ): + if os.path.exists(f"{name}_pubkey.txt") or os.path.exists(f"{name}_privkey.txt"): print("\nWARNING:") print( '"%s_pubkey.txt" or "%s_privkey.txt" already exists. \n' @@ -46,12 +44,12 @@ def makeKeyFiles(name: str, keySize: int) -> None: sys.exit() publicKey, privateKey = generateKey(keySize) - print("\nWriting public key to file %s_pubkey.txt..." % name) - with open("%s_pubkey.txt" % name, "w") as out_file: + print(f"\nWriting public key to file {name}_pubkey.txt...") + with open(f"{name}_pubkey.txt", "w") as out_file: out_file.write(f"{keySize},{publicKey[0]},{publicKey[1]}") - print("Writing private key to file %s_privkey.txt..." % name) - with open("%s_privkey.txt" % name, "w") as out_file: + print(f"Writing private key to file {name}_privkey.txt...") + with open(f"{name}_privkey.txt", "w") as out_file: out_file.write(f"{keySize},{privateKey[0]},{privateKey[1]}") diff --git a/ciphers/transposition_cipher.py b/ciphers/transposition_cipher.py index 589bb8cb5..ed9923a6b 100644 --- a/ciphers/transposition_cipher.py +++ b/ciphers/transposition_cipher.py @@ -10,7 +10,7 @@ text. The type of transposition cipher demonstrated under is the ROUTE cipher. def main() -> None: message = input("Enter message: ") - key = int(input("Enter key [2-%s]: " % (len(message) - 1))) + key = int(input(f"Enter key [2-{len(message) - 1}]: ")) mode = input("Encryption/Decryption [e/d]: ") if mode.lower().startswith("e"): @@ -19,7 +19,7 @@ def main() -> None: text = decryptMessage(key, message) # Append pipe symbol (vertical bar) to identify spaces at the end. - print("Output:\n%s" % (text + "|")) + print(f"Output:\n{text + '|'}") def encryptMessage(key: int, message: str) -> str: diff --git a/ciphers/transposition_cipher_encrypt_decrypt_file.py b/ciphers/transposition_cipher_encrypt_decrypt_file.py index b91c73c9f..926a1b36a 100644 --- a/ciphers/transposition_cipher_encrypt_decrypt_file.py +++ b/ciphers/transposition_cipher_encrypt_decrypt_file.py @@ -12,10 +12,10 @@ def main() -> None: mode = input("Encrypt/Decrypt [e/d]: ") if not os.path.exists(inputFile): - print("File %s does not exist. Quitting..." % inputFile) + print(f"File {inputFile} does not exist. Quitting...") sys.exit() if os.path.exists(outputFile): - print("Overwrite %s? [y/n]" % outputFile) + print(f"Overwrite {outputFile}? [y/n]") response = input("> ") if not response.lower().startswith("y"): sys.exit() diff --git a/ciphers/vigenere_cipher.py b/ciphers/vigenere_cipher.py index d97a96949..2e3987708 100644 --- a/ciphers/vigenere_cipher.py +++ b/ciphers/vigenere_cipher.py @@ -13,7 +13,7 @@ def main() -> None: mode = "decrypt" translated = decryptMessage(key, message) - print("\n%sed message:" % mode.title()) + print(f"\n{mode.title()}ed message:") print(translated) diff --git a/data_structures/binary_tree/binary_search_tree.py b/data_structures/binary_tree/binary_search_tree.py index ce490fd98..b9af23dc8 100644 --- a/data_structures/binary_tree/binary_search_tree.py +++ b/data_structures/binary_tree/binary_search_tree.py @@ -15,7 +15,7 @@ class Node: if self.left is None and self.right is None: return str(self.value) - return pformat({"%s" % (self.value): (self.left, self.right)}, indent=1) + return pformat({f"{self.value}": (self.left, self.right)}, indent=1) class BinarySearchTree: diff --git a/hashes/chaos_machine.py b/hashes/chaos_machine.py index 7ad3e5540..a6d476eb7 100644 --- a/hashes/chaos_machine.py +++ b/hashes/chaos_machine.py @@ -96,7 +96,7 @@ if __name__ == "__main__": # Pulling Data (Output) while inp in ("e", "E"): - print("%s" % format(pull(), "#04x")) + print(f"{format(pull(), '#04x')}") print(buffer_space) print(params_space) inp = input("(e)exit? ").strip() diff --git a/machine_learning/gradient_boosting_regressor.py b/machine_learning/gradient_boosting_regressor.py index 0aa0e7a10..c73e30680 100644 --- a/machine_learning/gradient_boosting_regressor.py +++ b/machine_learning/gradient_boosting_regressor.py @@ -47,9 +47,9 @@ def main(): y_pred = model.predict(X_test) # The mean squared error - print("Mean squared error: %.2f" % mean_squared_error(y_test, y_pred)) + print(f"Mean squared error: {mean_squared_error(y_test, y_pred):.2f}") # Explained variance score: 1 is perfect prediction - print("Test Variance score: %.2f" % r2_score(y_test, y_pred)) + print(f"Test Variance score: {r2_score(y_test, y_pred):.2f}") # So let's run the model against the test data fig, ax = plt.subplots() diff --git a/machine_learning/k_means_clust.py b/machine_learning/k_means_clust.py index 10c9374d8..60450b7f8 100644 --- a/machine_learning/k_means_clust.py +++ b/machine_learning/k_means_clust.py @@ -164,9 +164,7 @@ def kmeans( num_changed = np.sum(prev_cluster_assignment != cluster_assignment) if verbose: print( - " {:5d} elements changed their cluster assignment.".format( - num_changed - ) + f" {num_changed:5d} elements changed their cluster assignment." ) # Record heterogeneity convergence metric diff --git a/machine_learning/linear_regression.py b/machine_learning/linear_regression.py index b0bbc7b90..85fdfb000 100644 --- a/machine_learning/linear_regression.py +++ b/machine_learning/linear_regression.py @@ -99,7 +99,7 @@ def main(): len_result = theta.shape[1] print("Resultant Feature vector : ") for i in range(0, len_result): - print("%.5f" % (theta[0, i])) + print(f"{theta[0, i]:.5f}") if __name__ == "__main__": diff --git a/matrix/sherman_morrison.py b/matrix/sherman_morrison.py index 3466b3d4a..63783c8b4 100644 --- a/matrix/sherman_morrison.py +++ b/matrix/sherman_morrison.py @@ -256,7 +256,7 @@ if __name__ == "__main__": v[0, 0], v[1, 0], v[2, 0] = 4, -2, 5 print(f"u is {u}") print(f"v is {v}") - print("uv^T is %s" % (u * v.transpose())) + print(f"uv^T is {u * v.transpose()}") # Sherman Morrison print(f"(a + uv^T)^(-1) is {ainv.ShermanMorrison(u, v)}") diff --git a/neural_network/convolution_neural_network.py b/neural_network/convolution_neural_network.py index d82148802..e3993efb4 100644 --- a/neural_network/convolution_neural_network.py +++ b/neural_network/convolution_neural_network.py @@ -71,7 +71,7 @@ class CNN: with open(save_path, "wb") as f: pickle.dump(model_dic, f) - print("Model saved: %s" % save_path) + print(f"Model saved: {save_path}") @classmethod def ReadModel(cls, model_path): @@ -303,7 +303,7 @@ class CNN: plt.show() print("------------------Training Complished---------------------") - print((" - - Training epoch: ", rp, " - - Mse: %.6f" % mse)) + print((" - - Training epoch: ", rp, f" - - Mse: {mse:.6f}")) if draw_e: draw_error() return mse diff --git a/other/lru_cache.py b/other/lru_cache.py index 98051f89d..834ea52a9 100644 --- a/other/lru_cache.py +++ b/other/lru_cache.py @@ -21,8 +21,9 @@ class DoubleLinkedListNode(Generic[T, U]): self.prev: DoubleLinkedListNode[T, U] | None = None def __repr__(self) -> str: - return "Node: key: {}, val: {}, has next: {}, has prev: {}".format( - self.key, self.val, self.next is not None, self.prev is not None + return ( + f"Node: key: {self.key}, val: {self.val}, " + f"has next: {bool(self.next)}, has prev: {bool(self.prev)}" ) diff --git a/other/scoring_algorithm.py b/other/scoring_algorithm.py index cc1744012..aecd19c55 100644 --- a/other/scoring_algorithm.py +++ b/other/scoring_algorithm.py @@ -69,7 +69,7 @@ def procentual_proximity( # weight not 0 or 1 else: - raise ValueError("Invalid weight of %f provided" % (weight)) + raise ValueError(f"Invalid weight of {weight:f} provided") score_lists.append(score) diff --git a/scheduling/shortest_job_first.py b/scheduling/shortest_job_first.py index 9372e9dbc..b3f81bfd1 100644 --- a/scheduling/shortest_job_first.py +++ b/scheduling/shortest_job_first.py @@ -111,7 +111,7 @@ def calculate_average_times( for i in range(no_of_processes): total_waiting_time = total_waiting_time + waiting_time[i] total_turn_around_time = total_turn_around_time + turn_around_time[i] - print("Average waiting time = %.5f" % (total_waiting_time / no_of_processes)) + print(f"Average waiting time = {total_waiting_time / no_of_processes:.5f}") print("Average turn around time =", total_turn_around_time / no_of_processes) diff --git a/searches/binary_tree_traversal.py b/searches/binary_tree_traversal.py index f919a2962..033db83d7 100644 --- a/searches/binary_tree_traversal.py +++ b/searches/binary_tree_traversal.py @@ -25,14 +25,14 @@ def build_tree(): q.put(tree_node) while not q.empty(): node_found = q.get() - msg = "Enter the left node of %s: " % node_found.data + msg = f"Enter the left node of {node_found.data}: " check = input(msg).strip().lower() or "n" if check == "n": return tree_node left_node = TreeNode(int(check)) node_found.left = left_node q.put(left_node) - msg = "Enter the right node of %s: " % node_found.data + msg = f"Enter the right node of {node_found.data}: " check = input(msg).strip().lower() or "n" if check == "n": return tree_node diff --git a/strings/min_cost_string_conversion.py b/strings/min_cost_string_conversion.py index 147bc6fc7..089c2532f 100644 --- a/strings/min_cost_string_conversion.py +++ b/strings/min_cost_string_conversion.py @@ -31,28 +31,28 @@ def compute_transform_tables( for i in range(1, len_source_seq + 1): costs[i][0] = i * delete_cost - ops[i][0] = "D%c" % source_seq[i - 1] + ops[i][0] = f"D{source_seq[i - 1]:c}" for i in range(1, len_destination_seq + 1): costs[0][i] = i * insert_cost - ops[0][i] = "I%c" % destination_seq[i - 1] + ops[0][i] = f"I{destination_seq[i - 1]:c}" for i in range(1, len_source_seq + 1): for j in range(1, len_destination_seq + 1): if source_seq[i - 1] == destination_seq[j - 1]: costs[i][j] = costs[i - 1][j - 1] + copy_cost - ops[i][j] = "C%c" % source_seq[i - 1] + ops[i][j] = f"C{source_seq[i - 1]:c}" else: costs[i][j] = costs[i - 1][j - 1] + replace_cost - ops[i][j] = "R%c" % source_seq[i - 1] + str(destination_seq[j - 1]) + ops[i][j] = f"R{source_seq[i - 1]:c}" + str(destination_seq[j - 1]) if costs[i - 1][j] + delete_cost < costs[i][j]: costs[i][j] = costs[i - 1][j] + delete_cost - ops[i][j] = "D%c" % source_seq[i - 1] + ops[i][j] = f"D{source_seq[i - 1]:c}" if costs[i][j - 1] + insert_cost < costs[i][j]: costs[i][j] = costs[i][j - 1] + insert_cost - ops[i][j] = "I%c" % destination_seq[j - 1] + ops[i][j] = f"I{destination_seq[j - 1]:c}" return costs, ops From b75a7c77f89e55e1f2510b2eca9b4fd1a5d21ed8 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 11 Jul 2022 10:19:52 +0200 Subject: [PATCH 287/726] pre-commit autoupdate: pyupgrade v2.34.0 -> v2.37.0 (#6245) * pre-commit autoupdate: pyupgrade v2.34.0 -> v2.37.0 * pre-commit run --all-files --- .pre-commit-config.yaml | 2 +- arithmetic_analysis/bisection.py | 2 +- arithmetic_analysis/intersection.py | 2 +- arithmetic_analysis/newton_method.py | 2 +- boolean_algebra/quine_mc_cluskey.py | 2 +- ciphers/playfair_cipher.py | 2 +- computer_vision/horn_schunck.py | 3 ++- data_structures/binary_tree/binary_search_tree_recursive.py | 2 +- data_structures/binary_tree/binary_tree_traversals.py | 3 ++- data_structures/binary_tree/non_recursive_segment_tree.py | 3 ++- data_structures/binary_tree/red_black_tree.py | 2 +- data_structures/heap/heap.py | 2 +- data_structures/heap/randomized_heap.py | 3 ++- data_structures/heap/skew_heap.py | 3 ++- data_structures/linked_list/circular_linked_list.py | 3 ++- data_structures/queue/double_ended_queue.py | 3 ++- data_structures/queue/linked_queue.py | 3 ++- divide_and_conquer/convex_hull.py | 2 +- fractals/julia_sets.py | 3 ++- graphs/prim.py | 2 +- linear_algebra/src/lib.py | 3 ++- machine_learning/linear_discriminant_analysis.py | 3 ++- maths/area_under_curve.py | 2 +- maths/euclidean_distance.py | 3 ++- maths/euler_method.py | 2 +- maths/euler_modified.py | 2 +- maths/line_length.py | 2 +- maths/monte_carlo.py | 2 +- maths/numerical_integration.py | 2 +- maths/polynomial_evaluation.py | 2 +- maths/prime_numbers.py | 2 +- other/davisb_putnamb_logemannb_loveland.py | 2 +- other/lfu_cache.py | 3 ++- other/lru_cache.py | 3 ++- project_euler/problem_010/sol2.py | 2 +- project_euler/problem_025/sol2.py | 2 +- project_euler/problem_101/sol1.py | 3 ++- project_euler/problem_107/sol1.py | 2 +- project_euler/problem_123/sol1.py | 2 +- scripts/build_directory_md.py | 2 +- web_programming/fetch_jobs.py | 2 +- 41 files changed, 56 insertions(+), 41 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 90feb50ff..7ff745997 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,7 +26,7 @@ repos: - --profile=black - repo: https://github.com/asottile/pyupgrade - rev: v2.34.0 + rev: v2.37.0 hooks: - id: pyupgrade args: diff --git a/arithmetic_analysis/bisection.py b/arithmetic_analysis/bisection.py index 1feb4a8cf..640913a7a 100644 --- a/arithmetic_analysis/bisection.py +++ b/arithmetic_analysis/bisection.py @@ -1,4 +1,4 @@ -from typing import Callable +from collections.abc import Callable def bisection(function: Callable[[float], float], a: float, b: float) -> float: diff --git a/arithmetic_analysis/intersection.py b/arithmetic_analysis/intersection.py index 9d4651144..49213dd05 100644 --- a/arithmetic_analysis/intersection.py +++ b/arithmetic_analysis/intersection.py @@ -1,5 +1,5 @@ import math -from typing import Callable +from collections.abc import Callable def intersection(function: Callable[[float], float], x0: float, x1: float) -> float: diff --git a/arithmetic_analysis/newton_method.py b/arithmetic_analysis/newton_method.py index f0cf4eaa6..c4018a0f2 100644 --- a/arithmetic_analysis/newton_method.py +++ b/arithmetic_analysis/newton_method.py @@ -1,7 +1,7 @@ """Newton's Method.""" # Newton's Method - https://en.wikipedia.org/wiki/Newton%27s_method -from typing import Callable +from collections.abc import Callable RealFunc = Callable[[float], float] # type alias for a real -> real function diff --git a/boolean_algebra/quine_mc_cluskey.py b/boolean_algebra/quine_mc_cluskey.py index fb23c8c2e..9aa9b10c8 100644 --- a/boolean_algebra/quine_mc_cluskey.py +++ b/boolean_algebra/quine_mc_cluskey.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Sequence +from collections.abc import Sequence def compare_string(string1: str, string2: str) -> str: diff --git a/ciphers/playfair_cipher.py b/ciphers/playfair_cipher.py index 7c0ee5bd5..89aedb7af 100644 --- a/ciphers/playfair_cipher.py +++ b/ciphers/playfair_cipher.py @@ -1,6 +1,6 @@ import itertools import string -from typing import Generator, Iterable +from collections.abc import Generator, Iterable def chunker(seq: Iterable[str], size: int) -> Generator[tuple[str, ...], None, None]: diff --git a/computer_vision/horn_schunck.py b/computer_vision/horn_schunck.py index 1428487d0..2a153d06d 100644 --- a/computer_vision/horn_schunck.py +++ b/computer_vision/horn_schunck.py @@ -9,9 +9,10 @@ Paper: http://image.diku.dk/imagecanon/material/HornSchunckOptical_Flow.pdf """ +from typing import SupportsIndex + import numpy as np from scipy.ndimage.filters import convolve -from typing_extensions import SupportsIndex def warp( diff --git a/data_structures/binary_tree/binary_search_tree_recursive.py b/data_structures/binary_tree/binary_search_tree_recursive.py index 4bdf4e33d..0d0ac8fd1 100644 --- a/data_structures/binary_tree/binary_search_tree_recursive.py +++ b/data_structures/binary_tree/binary_search_tree_recursive.py @@ -10,7 +10,7 @@ python binary_search_tree_recursive.py from __future__ import annotations import unittest -from typing import Iterator +from collections.abc import Iterator class Node: diff --git a/data_structures/binary_tree/binary_tree_traversals.py b/data_structures/binary_tree/binary_tree_traversals.py index 9a6239391..378598bb0 100644 --- a/data_structures/binary_tree/binary_tree_traversals.py +++ b/data_structures/binary_tree/binary_tree_traversals.py @@ -2,8 +2,9 @@ from __future__ import annotations from collections import deque +from collections.abc import Sequence from dataclasses import dataclass -from typing import Any, Sequence +from typing import Any @dataclass diff --git a/data_structures/binary_tree/non_recursive_segment_tree.py b/data_structures/binary_tree/non_recursive_segment_tree.py index b04a6e5ca..c29adefff 100644 --- a/data_structures/binary_tree/non_recursive_segment_tree.py +++ b/data_structures/binary_tree/non_recursive_segment_tree.py @@ -37,7 +37,8 @@ https://www.geeksforgeeks.org/segment-tree-efficient-implementation/ """ from __future__ import annotations -from typing import Any, Callable, Generic, TypeVar +from collections.abc import Callable +from typing import Any, Generic, TypeVar T = TypeVar("T") diff --git a/data_structures/binary_tree/red_black_tree.py b/data_structures/binary_tree/red_black_tree.py index 35517f307..a9dbd699c 100644 --- a/data_structures/binary_tree/red_black_tree.py +++ b/data_structures/binary_tree/red_black_tree.py @@ -4,7 +4,7 @@ flake8 : passed """ from __future__ import annotations -from typing import Iterator +from collections.abc import Iterator class RedBlackTree: diff --git a/data_structures/heap/heap.py b/data_structures/heap/heap.py index 550439edd..4c19747ec 100644 --- a/data_structures/heap/heap.py +++ b/data_structures/heap/heap.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Iterable +from collections.abc import Iterable class Heap: diff --git a/data_structures/heap/randomized_heap.py b/data_structures/heap/randomized_heap.py index bab4ec1b3..c0f9888f8 100644 --- a/data_structures/heap/randomized_heap.py +++ b/data_structures/heap/randomized_heap.py @@ -3,7 +3,8 @@ from __future__ import annotations import random -from typing import Any, Generic, Iterable, TypeVar +from collections.abc import Iterable +from typing import Any, Generic, TypeVar T = TypeVar("T", bound=bool) diff --git a/data_structures/heap/skew_heap.py b/data_structures/heap/skew_heap.py index 16ddc5545..490db061d 100644 --- a/data_structures/heap/skew_heap.py +++ b/data_structures/heap/skew_heap.py @@ -2,7 +2,8 @@ from __future__ import annotations -from typing import Any, Generic, Iterable, Iterator, TypeVar +from collections.abc import Iterable, Iterator +from typing import Any, Generic, TypeVar T = TypeVar("T", bound=bool) diff --git a/data_structures/linked_list/circular_linked_list.py b/data_structures/linked_list/circular_linked_list.py index 121d934c6..6fec0a125 100644 --- a/data_structures/linked_list/circular_linked_list.py +++ b/data_structures/linked_list/circular_linked_list.py @@ -1,6 +1,7 @@ from __future__ import annotations -from typing import Any, Iterator +from collections.abc import Iterator +from typing import Any class Node: diff --git a/data_structures/queue/double_ended_queue.py b/data_structures/queue/double_ended_queue.py index a4658d997..1603e50bc 100644 --- a/data_structures/queue/double_ended_queue.py +++ b/data_structures/queue/double_ended_queue.py @@ -3,8 +3,9 @@ Implementation of double ended queue. """ from __future__ import annotations +from collections.abc import Iterable from dataclasses import dataclass -from typing import Any, Iterable +from typing import Any class Deque: diff --git a/data_structures/queue/linked_queue.py b/data_structures/queue/linked_queue.py index 21970e7df..c6e9f5390 100644 --- a/data_structures/queue/linked_queue.py +++ b/data_structures/queue/linked_queue.py @@ -1,7 +1,8 @@ """ A Queue using a linked list like structure """ from __future__ import annotations -from typing import Any, Iterator +from collections.abc import Iterator +from typing import Any class Node: diff --git a/divide_and_conquer/convex_hull.py b/divide_and_conquer/convex_hull.py index 63f8dbb20..72da11639 100644 --- a/divide_and_conquer/convex_hull.py +++ b/divide_and_conquer/convex_hull.py @@ -14,7 +14,7 @@ which have not been implemented here, yet. """ from __future__ import annotations -from typing import Iterable +from collections.abc import Iterable class Point: diff --git a/fractals/julia_sets.py b/fractals/julia_sets.py index 0168a0153..f27394385 100644 --- a/fractals/julia_sets.py +++ b/fractals/julia_sets.py @@ -22,7 +22,8 @@ Remark: Some overflow runtime warnings are suppressed. This is because of the """ import warnings -from typing import Any, Callable +from collections.abc import Callable +from typing import Any import numpy from matplotlib import pyplot diff --git a/graphs/prim.py b/graphs/prim.py index 70329da7e..55d0fbfa8 100644 --- a/graphs/prim.py +++ b/graphs/prim.py @@ -7,7 +7,7 @@ import heapq as hq import math -from typing import Iterator +from collections.abc import Iterator class Vertex: diff --git a/linear_algebra/src/lib.py b/linear_algebra/src/lib.py index 2bfcea7f8..b9791c860 100644 --- a/linear_algebra/src/lib.py +++ b/linear_algebra/src/lib.py @@ -22,7 +22,8 @@ from __future__ import annotations import math import random -from typing import Collection, overload +from collections.abc import Collection +from typing import overload class Vector: diff --git a/machine_learning/linear_discriminant_analysis.py b/machine_learning/linear_discriminant_analysis.py index 18553a77a..9ef42ed19 100644 --- a/machine_learning/linear_discriminant_analysis.py +++ b/machine_learning/linear_discriminant_analysis.py @@ -42,10 +42,11 @@ Author: @EverLookNeverSee """ +from collections.abc import Callable from math import log from os import name, system from random import gauss, seed -from typing import Callable, TypeVar +from typing import TypeVar # Make a training dataset drawn from a gaussian distribution diff --git a/maths/area_under_curve.py b/maths/area_under_curve.py index 6fb3a7c98..d345398b4 100644 --- a/maths/area_under_curve.py +++ b/maths/area_under_curve.py @@ -3,7 +3,7 @@ Approximates the area under the curve using the trapezoidal rule """ from __future__ import annotations -from typing import Callable +from collections.abc import Callable def trapezoidal_area( diff --git a/maths/euclidean_distance.py b/maths/euclidean_distance.py index a20781613..22012e92c 100644 --- a/maths/euclidean_distance.py +++ b/maths/euclidean_distance.py @@ -1,6 +1,7 @@ from __future__ import annotations -from typing import Iterable, Union +from collections.abc import Iterable +from typing import Union import numpy as np diff --git a/maths/euler_method.py b/maths/euler_method.py index 155ef28d1..af7eecb2f 100644 --- a/maths/euler_method.py +++ b/maths/euler_method.py @@ -1,4 +1,4 @@ -from typing import Callable +from collections.abc import Callable import numpy as np diff --git a/maths/euler_modified.py b/maths/euler_modified.py index 7c76a0ee0..5659fa063 100644 --- a/maths/euler_modified.py +++ b/maths/euler_modified.py @@ -1,4 +1,4 @@ -from typing import Callable +from collections.abc import Callable import numpy as np diff --git a/maths/line_length.py b/maths/line_length.py index c4d986279..ad12a816b 100644 --- a/maths/line_length.py +++ b/maths/line_length.py @@ -1,7 +1,7 @@ from __future__ import annotations import math -from typing import Callable +from collections.abc import Callable def line_length( diff --git a/maths/monte_carlo.py b/maths/monte_carlo.py index efb6a01d5..c13b8d0a4 100644 --- a/maths/monte_carlo.py +++ b/maths/monte_carlo.py @@ -1,10 +1,10 @@ """ @author: MatteoRaso """ +from collections.abc import Callable from math import pi, sqrt from random import uniform from statistics import mean -from typing import Callable def pi_estimator(iterations: int): diff --git a/maths/numerical_integration.py b/maths/numerical_integration.py index cf2efce12..a2bfce5b9 100644 --- a/maths/numerical_integration.py +++ b/maths/numerical_integration.py @@ -3,7 +3,7 @@ Approximates the area under the curve using the trapezoidal rule """ from __future__ import annotations -from typing import Callable +from collections.abc import Callable def trapezoidal_area( diff --git a/maths/polynomial_evaluation.py b/maths/polynomial_evaluation.py index 4e4016e51..8ee82467e 100644 --- a/maths/polynomial_evaluation.py +++ b/maths/polynomial_evaluation.py @@ -1,4 +1,4 @@ -from typing import Sequence +from collections.abc import Sequence def evaluate_poly(poly: Sequence[float], x: float) -> float: diff --git a/maths/prime_numbers.py b/maths/prime_numbers.py index 183fbd393..7be4d3d95 100644 --- a/maths/prime_numbers.py +++ b/maths/prime_numbers.py @@ -1,5 +1,5 @@ import math -from typing import Generator +from collections.abc import Generator def slow_primes(max: int) -> Generator[int, None, None]: diff --git a/other/davisb_putnamb_logemannb_loveland.py b/other/davisb_putnamb_logemannb_loveland.py index 031f0dbed..88aefabc8 100644 --- a/other/davisb_putnamb_logemannb_loveland.py +++ b/other/davisb_putnamb_logemannb_loveland.py @@ -11,7 +11,7 @@ For more information about the algorithm: https://en.wikipedia.org/wiki/DPLL_alg from __future__ import annotations import random -from typing import Iterable +from collections.abc import Iterable class Clause: diff --git a/other/lfu_cache.py b/other/lfu_cache.py index e955973c9..072d00ab5 100644 --- a/other/lfu_cache.py +++ b/other/lfu_cache.py @@ -1,6 +1,7 @@ from __future__ import annotations -from typing import Callable, Generic, TypeVar +from collections.abc import Callable +from typing import Generic, TypeVar T = TypeVar("T") U = TypeVar("U") diff --git a/other/lru_cache.py b/other/lru_cache.py index 834ea52a9..b68ae0a8e 100644 --- a/other/lru_cache.py +++ b/other/lru_cache.py @@ -1,6 +1,7 @@ from __future__ import annotations -from typing import Callable, Generic, TypeVar +from collections.abc import Callable +from typing import Generic, TypeVar T = TypeVar("T") U = TypeVar("U") diff --git a/project_euler/problem_010/sol2.py b/project_euler/problem_010/sol2.py index 3a2f485dd..a288bb85f 100644 --- a/project_euler/problem_010/sol2.py +++ b/project_euler/problem_010/sol2.py @@ -11,8 +11,8 @@ References: - https://en.wikipedia.org/wiki/Prime_number """ import math +from collections.abc import Iterator from itertools import takewhile -from typing import Iterator def is_prime(number: int) -> bool: diff --git a/project_euler/problem_025/sol2.py b/project_euler/problem_025/sol2.py index b041afd98..6f49e89fb 100644 --- a/project_euler/problem_025/sol2.py +++ b/project_euler/problem_025/sol2.py @@ -23,7 +23,7 @@ The 12th term, F12, is the first term to contain three digits. What is the index of the first term in the Fibonacci sequence to contain 1000 digits? """ -from typing import Generator +from collections.abc import Generator def fibonacci_generator() -> Generator[int, None, None]: diff --git a/project_euler/problem_101/sol1.py b/project_euler/problem_101/sol1.py index 046788475..27438e086 100644 --- a/project_euler/problem_101/sol1.py +++ b/project_euler/problem_101/sol1.py @@ -43,7 +43,8 @@ Find the sum of FITs for the BOPs. """ from __future__ import annotations -from typing import Callable, Union +from collections.abc import Callable +from typing import Union Matrix = list[list[Union[float, int]]] diff --git a/project_euler/problem_107/sol1.py b/project_euler/problem_107/sol1.py index 6a411a114..048cf033d 100644 --- a/project_euler/problem_107/sol1.py +++ b/project_euler/problem_107/sol1.py @@ -30,7 +30,7 @@ Solution: from __future__ import annotations import os -from typing import Mapping +from collections.abc import Mapping EdgeT = tuple[int, int] diff --git a/project_euler/problem_123/sol1.py b/project_euler/problem_123/sol1.py index 919132227..f74cdd999 100644 --- a/project_euler/problem_123/sol1.py +++ b/project_euler/problem_123/sol1.py @@ -39,7 +39,7 @@ So it could be simplified as, """ from __future__ import annotations -from typing import Generator +from collections.abc import Generator def sieve() -> Generator[int, None, None]: diff --git a/scripts/build_directory_md.py b/scripts/build_directory_md.py index 71577fe6d..7572ce342 100755 --- a/scripts/build_directory_md.py +++ b/scripts/build_directory_md.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 import os -from typing import Iterator +from collections.abc import Iterator def good_file_paths(top_dir: str = ".") -> Iterator[str]: diff --git a/web_programming/fetch_jobs.py b/web_programming/fetch_jobs.py index bb2171e1f..5af90a0bb 100644 --- a/web_programming/fetch_jobs.py +++ b/web_programming/fetch_jobs.py @@ -3,7 +3,7 @@ Scraping jobs given job title and location from indeed website """ from __future__ import annotations -from typing import Generator +from collections.abc import Generator import requests from bs4 import BeautifulSoup From ba129de7f32b6acd1efd8e942aca109bacd86646 Mon Sep 17 00:00:00 2001 From: Todor Peev <46652070+Bjiornulf@users.noreply.github.com> Date: Mon, 11 Jul 2022 12:42:07 +0200 Subject: [PATCH 288/726] Fixes: 6216 | Support vector machines (#6240) * initial commit * first implementation of hard margin * remove debugging print * many commits squashed because pre-commit was buggy * more kernels and improved kernel management * remove unnecessary code + fix names + formatting + doctests * rename to fit initial naming * better naming and documentation * better naming and documentation --- machine_learning/support_vector_machines.py | 205 ++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 machine_learning/support_vector_machines.py diff --git a/machine_learning/support_vector_machines.py b/machine_learning/support_vector_machines.py new file mode 100644 index 000000000..caec10175 --- /dev/null +++ b/machine_learning/support_vector_machines.py @@ -0,0 +1,205 @@ +import numpy as np +from numpy import ndarray +from scipy.optimize import Bounds, LinearConstraint, minimize + + +def norm_squared(vector: ndarray) -> float: + """ + Return the squared second norm of vector + norm_squared(v) = sum(x * x for x in v) + + Args: + vector (ndarray): input vector + + Returns: + float: squared second norm of vector + + >>> norm_squared([1, 2]) + 5 + >>> norm_squared(np.asarray([1, 2])) + 5 + >>> norm_squared([0, 0]) + 0 + """ + return np.dot(vector, vector) + + +class SVC: + """ + Support Vector Classifier + + Args: + kernel (str): kernel to use. Default: linear + Possible choices: + - linear + regularization: constraint for soft margin (data not linearly separable) + Default: unbound + + >>> SVC(kernel="asdf") + Traceback (most recent call last): + ... + ValueError: Unknown kernel: asdf + + >>> SVC(kernel="rbf") + Traceback (most recent call last): + ... + ValueError: rbf kernel requires gamma + + >>> SVC(kernel="rbf", gamma=-1) + Traceback (most recent call last): + ... + ValueError: gamma must be > 0 + """ + + def __init__( + self, + *, + regularization: float = np.inf, + kernel: str = "linear", + gamma: float = 0, + ) -> None: + self.regularization = regularization + self.gamma = gamma + if kernel == "linear": + self.kernel = self.__linear + elif kernel == "rbf": + if self.gamma == 0: + raise ValueError("rbf kernel requires gamma") + if not (isinstance(self.gamma, float) or isinstance(self.gamma, int)): + raise ValueError("gamma must be float or int") + if not self.gamma > 0: + raise ValueError("gamma must be > 0") + self.kernel = self.__rbf + # in the future, there could be a default value like in sklearn + # sklear: def_gamma = 1/(n_features * X.var()) (wiki) + # previously it was 1/(n_features) + else: + raise ValueError(f"Unknown kernel: {kernel}") + + # kernels + def __linear(self, vector1: ndarray, vector2: ndarray) -> float: + """Linear kernel (as if no kernel used at all)""" + return np.dot(vector1, vector2) + + def __rbf(self, vector1: ndarray, vector2: ndarray) -> float: + """ + RBF: Radial Basis Function Kernel + + Note: for more information see: + https://en.wikipedia.org/wiki/Radial_basis_function_kernel + + Args: + vector1 (ndarray): first vector + vector2 (ndarray): second vector) + + Returns: + float: exp(-(gamma * norm_squared(vector1 - vector2))) + """ + return np.exp(-(self.gamma * norm_squared(vector1 - vector2))) + + def fit(self, observations: list[ndarray], classes: ndarray) -> None: + """ + Fits the SVC with a set of observations. + + Args: + observations (list[ndarray]): list of observations + classes (ndarray): classification of each observation (in {1, -1}) + """ + + self.observations = observations + self.classes = classes + + # using Wolfe's Dual to calculate w. + # Primal problem: minimize 1/2*norm_squared(w) + # constraint: yn(w . xn + b) >= 1 + # + # With l a vector + # Dual problem: maximize sum_n(ln) - + # 1/2 * sum_n(sum_m(ln*lm*yn*ym*xn . xm)) + # constraint: self.C >= ln >= 0 + # and sum_n(ln*yn) = 0 + # Then we get w using w = sum_n(ln*yn*xn) + # At the end we can get b ~= mean(yn - w . xn) + # + # Since we use kernels, we only need l_star to calculate b + # and to classify observations + + (n,) = np.shape(classes) + + def to_minimize(candidate: ndarray) -> float: + """ + Opposite of the function to maximize + + Args: + candidate (ndarray): candidate array to test + + Return: + float: Wolfe's Dual result to minimize + """ + s = 0 + (n,) = np.shape(candidate) + for i in range(n): + for j in range(n): + s += ( + candidate[i] + * candidate[j] + * classes[i] + * classes[j] + * self.kernel(observations[i], observations[j]) + ) + return 1 / 2 * s - sum(candidate) + + ly_contraint = LinearConstraint(classes, 0, 0) + l_bounds = Bounds(0, self.regularization) + + l_star = minimize( + to_minimize, np.ones(n), bounds=l_bounds, constraints=[ly_contraint] + ).x + self.optimum = l_star + + # calculating mean offset of separation plane to points + s = 0 + for i in range(n): + for j in range(n): + s += classes[i] - classes[i] * self.optimum[i] * self.kernel( + observations[i], observations[j] + ) + self.offset = s / n + + def predict(self, observation: ndarray) -> int: + """ + Get the expected class of an observation + + Args: + observation (Vector): observation + + Returns: + int {1, -1}: expected class + + >>> xs = [ + ... np.asarray([0, 1]), np.asarray([0, 2]), + ... np.asarray([1, 1]), np.asarray([1, 2]) + ... ] + >>> y = np.asarray([1, 1, -1, -1]) + >>> s = SVC() + >>> s.fit(xs, y) + >>> s.predict(np.asarray([0, 1])) + 1 + >>> s.predict(np.asarray([1, 1])) + -1 + >>> s.predict(np.asarray([2, 2])) + -1 + """ + s = sum( + self.optimum[n] + * self.classes[n] + * self.kernel(self.observations[n], observation) + for n in range(len(self.classes)) + ) + return 1 if s + self.offset >= 0 else -1 + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From dad789d9034ea6fb183bddb1a34b6b89d379e422 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 11 Jul 2022 13:11:17 +0200 Subject: [PATCH 289/726] Get rid of the Union (#6246) * Get rid of the Union * updating DIRECTORY.md * Get rid of the Union * Remove the redundant pre-commit runs. Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .github/workflows/pre-commit.yml | 6 +++++- DIRECTORY.md | 1 + project_euler/problem_101/sol1.py | 3 +-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 3b128bc54..eb5e3d4ce 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -1,6 +1,10 @@ name: pre-commit -on: [push, pull_request] +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] jobs: pre-commit: diff --git a/DIRECTORY.md b/DIRECTORY.md index 2e9c03cbc..c8f03658c 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -444,6 +444,7 @@ * [Scoring Functions](machine_learning/scoring_functions.py) * [Sequential Minimum Optimization](machine_learning/sequential_minimum_optimization.py) * [Similarity Search](machine_learning/similarity_search.py) + * [Support Vector Machines](machine_learning/support_vector_machines.py) * [Word Frequency Functions](machine_learning/word_frequency_functions.py) ## Maths diff --git a/project_euler/problem_101/sol1.py b/project_euler/problem_101/sol1.py index 27438e086..d5c503af7 100644 --- a/project_euler/problem_101/sol1.py +++ b/project_euler/problem_101/sol1.py @@ -44,9 +44,8 @@ Find the sum of FITs for the BOPs. from __future__ import annotations from collections.abc import Callable -from typing import Union -Matrix = list[list[Union[float, int]]] +Matrix = list[list[float | int]] def solve(matrix: Matrix, vector: Matrix) -> Matrix: From f7c58e4c4b66750cbb3afd9ad29e9c246b2480ab Mon Sep 17 00:00:00 2001 From: Nikos Giachoudis Date: Mon, 11 Jul 2022 10:36:57 -0400 Subject: [PATCH 290/726] Unify primality checking (#6228) * renames prime functions and occurances in comments * changes implementation of primality testing to be uniform * adds static typing as per conventions * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 1 - data_structures/hashing/double_hash.py | 4 +- .../hashing/number_theory/prime_numbers.py | 52 ++++++++++++---- maths/prime_check.py | 61 ++++++++++--------- maths/primelib.py | 22 +++---- 5 files changed, 87 insertions(+), 53 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index c8f03658c..2e9c03cbc 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -444,7 +444,6 @@ * [Scoring Functions](machine_learning/scoring_functions.py) * [Sequential Minimum Optimization](machine_learning/sequential_minimum_optimization.py) * [Similarity Search](machine_learning/similarity_search.py) - * [Support Vector Machines](machine_learning/support_vector_machines.py) * [Word Frequency Functions](machine_learning/word_frequency_functions.py) ## Maths diff --git a/data_structures/hashing/double_hash.py b/data_structures/hashing/double_hash.py index 57b1ffff4..bd1355fca 100644 --- a/data_structures/hashing/double_hash.py +++ b/data_structures/hashing/double_hash.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 from .hash_table import HashTable -from .number_theory.prime_numbers import check_prime, next_prime +from .number_theory.prime_numbers import is_prime, next_prime class DoubleHash(HashTable): @@ -15,7 +15,7 @@ class DoubleHash(HashTable): next_prime_gt = ( next_prime(value % self.size_table) - if not check_prime(value % self.size_table) + if not is_prime(value % self.size_table) else value % self.size_table ) # gt = bigger than return next_prime_gt - (data % next_prime_gt) diff --git a/data_structures/hashing/number_theory/prime_numbers.py b/data_structures/hashing/number_theory/prime_numbers.py index bf614e7d4..b88ab76ec 100644 --- a/data_structures/hashing/number_theory/prime_numbers.py +++ b/data_structures/hashing/number_theory/prime_numbers.py @@ -3,25 +3,55 @@ module to operations with prime numbers """ +import math -def check_prime(number): - """ - it's not the best solution - """ - special_non_primes = [0, 1, 2] - if number in special_non_primes[:2]: - return 2 - elif number == special_non_primes[-1]: - return 3 - return all(number % i for i in range(2, number)) +def is_prime(number: int) -> bool: + """Checks to see if a number is a prime in O(sqrt(n)). + + A number is prime if it has exactly two factors: 1 and itself. + + >>> is_prime(0) + False + >>> is_prime(1) + False + >>> is_prime(2) + True + >>> is_prime(3) + True + >>> is_prime(27) + False + >>> is_prime(87) + False + >>> is_prime(563) + True + >>> is_prime(2999) + True + >>> is_prime(67483) + False + """ + + # precondition + assert isinstance(number, int) and ( + number >= 0 + ), "'number' must been an int and positive" + + if 1 < number < 4: + # 2 and 3 are primes + return True + elif number < 2 or not number % 2: + # Negatives, 0, 1 and all even numbers are not primes + return False + + odd_numbers = range(3, int(math.sqrt(number) + 1), 2) + return not any(not number % i for i in odd_numbers) def next_prime(value, factor=1, **kwargs): value = factor * value first_value_val = value - while not check_prime(value): + while not is_prime(value): value += 1 if not ("desc" in kwargs.keys() and kwargs["desc"] is True) else -1 if value == first_value_val: diff --git a/maths/prime_check.py b/maths/prime_check.py index 92d31cfee..315492054 100644 --- a/maths/prime_check.py +++ b/maths/prime_check.py @@ -4,31 +4,36 @@ import math import unittest -def prime_check(number: int) -> bool: +def is_prime(number: int) -> bool: """Checks to see if a number is a prime in O(sqrt(n)). A number is prime if it has exactly two factors: 1 and itself. - >>> prime_check(0) + >>> is_prime(0) False - >>> prime_check(1) + >>> is_prime(1) False - >>> prime_check(2) + >>> is_prime(2) True - >>> prime_check(3) + >>> is_prime(3) True - >>> prime_check(27) + >>> is_prime(27) False - >>> prime_check(87) + >>> is_prime(87) False - >>> prime_check(563) + >>> is_prime(563) True - >>> prime_check(2999) + >>> is_prime(2999) True - >>> prime_check(67483) + >>> is_prime(67483) False """ + # precondition + assert isinstance(number, int) and ( + number >= 0 + ), "'number' must been an int and positive" + if 1 < number < 4: # 2 and 3 are primes return True @@ -42,35 +47,35 @@ def prime_check(number: int) -> bool: class Test(unittest.TestCase): def test_primes(self): - self.assertTrue(prime_check(2)) - self.assertTrue(prime_check(3)) - self.assertTrue(prime_check(5)) - self.assertTrue(prime_check(7)) - self.assertTrue(prime_check(11)) - self.assertTrue(prime_check(13)) - self.assertTrue(prime_check(17)) - self.assertTrue(prime_check(19)) - self.assertTrue(prime_check(23)) - self.assertTrue(prime_check(29)) + self.assertTrue(is_prime(2)) + self.assertTrue(is_prime(3)) + self.assertTrue(is_prime(5)) + self.assertTrue(is_prime(7)) + self.assertTrue(is_prime(11)) + self.assertTrue(is_prime(13)) + self.assertTrue(is_prime(17)) + self.assertTrue(is_prime(19)) + self.assertTrue(is_prime(23)) + self.assertTrue(is_prime(29)) def test_not_primes(self): self.assertFalse( - prime_check(-19), + is_prime(-19), "Negative numbers are excluded by definition of prime numbers.", ) self.assertFalse( - prime_check(0), + is_prime(0), "Zero doesn't have any positive factors, primes must have exactly two.", ) self.assertFalse( - prime_check(1), + is_prime(1), "One only has 1 positive factor, primes must have exactly two.", ) - self.assertFalse(prime_check(2 * 2)) - self.assertFalse(prime_check(2 * 3)) - self.assertFalse(prime_check(3 * 3)) - self.assertFalse(prime_check(3 * 5)) - self.assertFalse(prime_check(3 * 5 * 7)) + self.assertFalse(is_prime(2 * 2)) + self.assertFalse(is_prime(2 * 3)) + self.assertFalse(is_prime(3 * 3)) + self.assertFalse(is_prime(3 * 5)) + self.assertFalse(is_prime(3 * 5 * 7)) if __name__ == "__main__": diff --git a/maths/primelib.py b/maths/primelib.py index 37883d9cf..3da9c56f6 100644 --- a/maths/primelib.py +++ b/maths/primelib.py @@ -41,7 +41,7 @@ goldbach(number) // Goldbach's assumption from math import sqrt -def isPrime(number): +def is_prime(number: int) -> bool: """ input: positive integer 'number' returns true if 'number' is prime otherwise false. @@ -129,7 +129,7 @@ def getPrimeNumbers(N): # if a number is prime then appends to list 'ans' for number in range(2, N + 1): - if isPrime(number): + if is_prime(number): ans.append(number) @@ -164,11 +164,11 @@ def primeFactorization(number): ans.append(number) # if 'number' not prime then builds the prime factorization of 'number' - elif not isPrime(number): + elif not is_prime(number): while quotient != 1: - if isPrime(factor) and (quotient % factor == 0): + if is_prime(factor) and (quotient % factor == 0): ans.append(factor) quotient /= factor else: @@ -317,8 +317,8 @@ def goldbach(number): isinstance(ans, list) and (len(ans) == 2) and (ans[0] + ans[1] == number) - and isPrime(ans[0]) - and isPrime(ans[1]) + and is_prime(ans[0]) + and is_prime(ans[1]) ), "'ans' must contains two primes. And sum of elements must been eq 'number'" return ans @@ -462,11 +462,11 @@ def getPrime(n): # if ans not prime then # runs to the next prime number. - while not isPrime(ans): + while not is_prime(ans): ans += 1 # precondition - assert isinstance(ans, int) and isPrime( + assert isinstance(ans, int) and is_prime( ans ), "'ans' must been a prime number and from type int" @@ -486,7 +486,7 @@ def getPrimesBetween(pNumber1, pNumber2): # precondition assert ( - isPrime(pNumber1) and isPrime(pNumber2) and (pNumber1 < pNumber2) + is_prime(pNumber1) and is_prime(pNumber2) and (pNumber1 < pNumber2) ), "The arguments must been prime numbers and 'pNumber1' < 'pNumber2'" number = pNumber1 + 1 # jump to the next number @@ -495,7 +495,7 @@ def getPrimesBetween(pNumber1, pNumber2): # if number is not prime then # fetch the next prime number. - while not isPrime(number): + while not is_prime(number): number += 1 while number < pNumber2: @@ -505,7 +505,7 @@ def getPrimesBetween(pNumber1, pNumber2): number += 1 # fetch the next prime number. - while not isPrime(number): + while not is_prime(number): number += 1 # precondition From dcc387631d201de42dbf34216088e7faba302a41 Mon Sep 17 00:00:00 2001 From: lakshmikanth ayyadevara <52835045+Lakshmikanth2001@users.noreply.github.com> Date: Mon, 11 Jul 2022 20:59:27 +0530 Subject: [PATCH 291/726] Improve `prime_check` in math modules (#6044) * improved prime_check * updating DIRECTORY.md * included suggested changes * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- maths/prime_check.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/maths/prime_check.py b/maths/prime_check.py index 315492054..6af5a75c2 100644 --- a/maths/prime_check.py +++ b/maths/prime_check.py @@ -37,12 +37,15 @@ def is_prime(number: int) -> bool: if 1 < number < 4: # 2 and 3 are primes return True - elif number < 2 or not number % 2: - # Negatives, 0, 1 and all even numbers are not primes + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes return False - odd_numbers = range(3, int(math.sqrt(number) + 1), 2) - return not any(not number % i for i in odd_numbers) + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: + return False + return True class Test(unittest.TestCase): From 38dfcd28b5f2fb19bae130a942466d73933e072f Mon Sep 17 00:00:00 2001 From: Dhruv Manilawala Date: Thu, 14 Jul 2022 12:54:24 +0530 Subject: [PATCH 292/726] fix: test failures (#6250) 1. Incorrect function was being imported from the module 2. Testing for exception was not done correctly --- maths/miller_rabin.py | 6 +++--- maths/prime_check.py | 6 ++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/maths/miller_rabin.py b/maths/miller_rabin.py index d35e54858..b4dfed129 100644 --- a/maths/miller_rabin.py +++ b/maths/miller_rabin.py @@ -8,9 +8,9 @@ from .binary_exp_mod import bin_exp_mod # if it's not a prime, the chance of it returning true is at most 1/4**prec def is_prime_big(n, prec=1000): """ - >>> from maths.prime_check import prime_check - >>> # all(is_prime_big(i) == prime_check(i) for i in range(1000)) # 3.45s - >>> all(is_prime_big(i) == prime_check(i) for i in range(256)) + >>> from maths.prime_check import is_prime + >>> # all(is_prime_big(i) == is_prime(i) for i in range(1000)) # 3.45s + >>> all(is_prime_big(i) == is_prime(i) for i in range(256)) True """ if n < 2: diff --git a/maths/prime_check.py b/maths/prime_check.py index 6af5a75c2..80ab8bc5d 100644 --- a/maths/prime_check.py +++ b/maths/prime_check.py @@ -62,10 +62,8 @@ class Test(unittest.TestCase): self.assertTrue(is_prime(29)) def test_not_primes(self): - self.assertFalse( - is_prime(-19), - "Negative numbers are excluded by definition of prime numbers.", - ) + with self.assertRaises(AssertionError): + is_prime(-19) self.assertFalse( is_prime(0), "Zero doesn't have any positive factors, primes must have exactly two.", From e1e7922efac2b7fdfab7555baaf784edb345c222 Mon Sep 17 00:00:00 2001 From: KanakalathaVemuru <46847239+KanakalathaVemuru@users.noreply.github.com> Date: Sun, 17 Jul 2022 03:12:58 +0530 Subject: [PATCH 293/726] Add circle sort implementation (#5548) * Added circle sort implementation * Added modifications * Added modifications * Update circle_sort.py * Update circle_sort.py Co-authored-by: Christian Clauss Co-authored-by: John Law --- sorts/circle_sort.py | 87 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 sorts/circle_sort.py diff --git a/sorts/circle_sort.py b/sorts/circle_sort.py new file mode 100644 index 000000000..da3c59059 --- /dev/null +++ b/sorts/circle_sort.py @@ -0,0 +1,87 @@ +""" +This is a Python implementation of the circle sort algorithm + +For doctests run following command: +python3 -m doctest -v circle_sort.py + +For manual testing run: +python3 circle_sort.py +""" + + +def circle_sort(collection: list) -> list: + """A pure Python implementation of circle sort algorithm + + :param collection: a mutable collection of comparable items in any order + :return: the same collection in ascending order + + Examples: + >>> circle_sort([0, 5, 3, 2, 2]) + [0, 2, 2, 3, 5] + >>> circle_sort([]) + [] + >>> circle_sort([-2, 5, 0, -45]) + [-45, -2, 0, 5] + >>> collections = ([], [0, 5, 3, 2, 2], [-2, 5, 0, -45]) + >>> all(sorted(collection) == circle_sort(collection) for collection in collections) + True + """ + + if len(collection) < 2: + return collection + + def circle_sort_util(collection: list, low: int, high: int) -> bool: + """ + >>> arr = [5,4,3,2,1] + >>> circle_sort_util(lst, 0, 2) + True + >>> arr + [3, 4, 5, 2, 1] + """ + + swapped = False + + if low == high: + return swapped + + left = low + right = high + + while left < right: + if collection[left] > collection[right]: + collection[left], collection[right] = ( + collection[right], + collection[left], + ) + swapped = True + + left += 1 + right -= 1 + + if left == right: + if collection[left] > collection[right + 1]: + collection[left], collection[right + 1] = ( + collection[right + 1], + collection[left], + ) + + swapped = True + + mid = low + int((high - low) / 2) + left_swap = circle_sort_util(collection, low, mid) + right_swap = circle_sort_util(collection, mid + 1, high) + + return swapped or left_swap or right_swap + + is_not_sorted = True + + while is_not_sorted is True: + is_not_sorted = circle_sort_util(collection, 0, len(collection) - 1) + + return collection + + +if __name__ == "__main__": + user_input = input("Enter numbers separated by a comma:\n").strip() + unsorted = [int(item) for item in user_input.split(",")] + print(circle_sort(unsorted)) From b3d9281591df03768fe062cc0517ee0d4cc387f0 Mon Sep 17 00:00:00 2001 From: U <80122730+und1n3@users.noreply.github.com> Date: Sat, 16 Jul 2022 23:55:29 +0200 Subject: [PATCH 294/726] Add algorithm for creating Hamming numbers (#4992) * Added algorithm for creating Hamming numbers series in Python * Changed to f-string format. * Added modifications * Update and rename hamming.py to hamming_numbers.py * Update hamming_numbers.py * Update hamming_numbers.py * Rename maths/series/hamming_numbers.py to maths/hamming_numbers.py Co-authored-by: John Law --- maths/hamming_numbers.py | 51 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 maths/hamming_numbers.py diff --git a/maths/hamming_numbers.py b/maths/hamming_numbers.py new file mode 100644 index 000000000..4575119c8 --- /dev/null +++ b/maths/hamming_numbers.py @@ -0,0 +1,51 @@ +""" +A Hamming number is a positive integer of the form 2^i*3^j*5^k, for some +non-negative integers i, j, and k. They are often referred to as regular numbers. +More info at: https://en.wikipedia.org/wiki/Regular_number. +""" + + +def hamming(n_element: int) -> list: + """ + This function creates an ordered list of n length as requested, and afterwards + returns the last value of the list. It must be given a positive integer. + + :param n_element: The number of elements on the list + :return: The nth element of the list + + >>> hamming(5) + [1, 2, 3, 4, 5] + >>> hamming(10) + [1, 2, 3, 4, 5, 6, 8, 9, 10, 12] + >>> hamming(15) + [1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24] + """ + n_element = int(n_element) + if n_element < 1: + my_error = ValueError("a should be a positive number") + raise my_error + + hamming_list = [1] + i, j, k = (0, 0, 0) + index = 1 + while index < n_element: + while hamming_list[i] * 2 <= hamming_list[-1]: + i += 1 + while hamming_list[j] * 3 <= hamming_list[-1]: + j += 1 + while hamming_list[k] * 5 <= hamming_list[-1]: + k += 1 + hamming_list.append( + min(hamming_list[i] * 2, hamming_list[j] * 3, hamming_list[k] * 5) + ) + index += 1 + return hamming_list + + +if __name__ == "__main__": + n = input("Enter the last number (nth term) of the Hamming Number Series: ") + print("Formula of Hamming Number Series => 2^i * 3^j * 5^k") + hamming_numbers = hamming(int(n)) + print("-----------------------------------------------------") + print(f"The list with nth numbers is: {hamming_numbers}") + print("-----------------------------------------------------") From c45fb3c2948449760667fdf085cfc0467376ade8 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sat, 23 Jul 2022 04:53:46 +0300 Subject: [PATCH 295/726] perf: Project Euler problem 145 solution 1 (#6259) Improve solution (~30 times - from 900+ seconds to ~30 seconds) Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 3 ++ project_euler/problem_145/sol1.py | 90 ++++++++++++++++++++++--------- 2 files changed, 67 insertions(+), 26 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 2e9c03cbc..1ee106252 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -444,6 +444,7 @@ * [Scoring Functions](machine_learning/scoring_functions.py) * [Sequential Minimum Optimization](machine_learning/sequential_minimum_optimization.py) * [Similarity Search](machine_learning/similarity_search.py) + * [Support Vector Machines](machine_learning/support_vector_machines.py) * [Word Frequency Functions](machine_learning/word_frequency_functions.py) ## Maths @@ -500,6 +501,7 @@ * [Gaussian](maths/gaussian.py) * [Greatest Common Divisor](maths/greatest_common_divisor.py) * [Greedy Coin Change](maths/greedy_coin_change.py) + * [Hamming Numbers](maths/hamming_numbers.py) * [Hardy Ramanujanalgo](maths/hardy_ramanujanalgo.py) * [Integration By Simpson Approx](maths/integration_by_simpson_approx.py) * [Is Ip V4 Address Valid](maths/is_ip_v4_address_valid.py) @@ -938,6 +940,7 @@ * [Bogo Sort](sorts/bogo_sort.py) * [Bubble Sort](sorts/bubble_sort.py) * [Bucket Sort](sorts/bucket_sort.py) + * [Circle Sort](sorts/circle_sort.py) * [Cocktail Shaker Sort](sorts/cocktail_shaker_sort.py) * [Comb Sort](sorts/comb_sort.py) * [Counting Sort](sorts/counting_sort.py) diff --git a/project_euler/problem_145/sol1.py b/project_euler/problem_145/sol1.py index 09d8daff5..e9fc1a199 100644 --- a/project_euler/problem_145/sol1.py +++ b/project_euler/problem_145/sol1.py @@ -1,6 +1,6 @@ """ Project Euler problem 145: https://projecteuler.net/problem=145 -Author: Vineet Rao +Author: Vineet Rao, Maxim Smolskiy Problem statement: Some positive integers n have the property that the sum [ n + reverse(n) ] @@ -13,44 +13,82 @@ There are 120 reversible numbers below one-thousand. How many reversible numbers are there below one-billion (10^9)? """ +EVEN_DIGITS = [0, 2, 4, 6, 8] +ODD_DIGITS = [1, 3, 5, 7, 9] -def odd_digits(num: int) -> bool: +def reversible_numbers( + remaining_length: int, remainder: int, digits: list[int], length: int +) -> int: """ - Check if the number passed as argument has only odd digits. - >>> odd_digits(123) - False - >>> odd_digits(135797531) - True + Count the number of reversible numbers of given length. + Iterate over possible digits considering parity of current sum remainder. + >>> reversible_numbers(1, 0, [0], 1) + 0 + >>> reversible_numbers(2, 0, [0] * 2, 2) + 20 + >>> reversible_numbers(3, 0, [0] * 3, 3) + 100 """ - while num > 0: - digit = num % 10 - if digit % 2 == 0: - return False - num //= 10 - return True + if remaining_length == 0: + if digits[0] == 0 or digits[-1] == 0: + return 0 + + for i in range(length // 2 - 1, -1, -1): + remainder += digits[i] + digits[length - i - 1] + + if remainder % 2 == 0: + return 0 + + remainder //= 10 + + return 1 + + if remaining_length == 1: + if remainder % 2 == 0: + return 0 + + result = 0 + for digit in range(10): + digits[length // 2] = digit + result += reversible_numbers( + 0, (remainder + 2 * digit) // 10, digits, length + ) + return result + + result = 0 + for digit1 in range(10): + digits[(length + remaining_length) // 2 - 1] = digit1 + + if (remainder + digit1) % 2 == 0: + other_parity_digits = ODD_DIGITS + else: + other_parity_digits = EVEN_DIGITS + + for digit2 in other_parity_digits: + digits[(length - remaining_length) // 2] = digit2 + result += reversible_numbers( + remaining_length - 2, + (remainder + digit1 + digit2) // 10, + digits, + length, + ) + return result -def solution(max_num: int = 1_000_000_000) -> int: +def solution(max_power: int = 9) -> int: """ To evaluate the solution, use solution() - >>> solution(1000) + >>> solution(3) 120 - >>> solution(1_000_000) + >>> solution(6) 18720 - >>> solution(10_000_000) + >>> solution(7) 68720 """ result = 0 - # All single digit numbers reverse to themselves, so their sums are even - # Therefore at least one digit in their sum is even - # Last digit cannot be 0, else it causes leading zeros in reverse - for num in range(11, max_num): - if num % 10 == 0: - continue - num_sum = num + int(str(num)[::-1]) - num_is_reversible = odd_digits(num_sum) - result += 1 if num_is_reversible else 0 + for length in range(1, max_power + 1): + result += reversible_numbers(length, 0, [0] * length, length) return result From d53fdc29e2b47213999f566d16acd60409de6dc2 Mon Sep 17 00:00:00 2001 From: lance-pyles <36748284+lance-pyles@users.noreply.github.com> Date: Fri, 22 Jul 2022 19:26:59 -0700 Subject: [PATCH 296/726] chore: update .gitignore (#6263) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 574cdf312..baea84b8d 100644 --- a/.gitignore +++ b/.gitignore @@ -107,3 +107,4 @@ venv.bak/ .idea .try .vscode/ +.vs/ From 7d9ebee75fd9036579c2ecb282cbf4910de12b58 Mon Sep 17 00:00:00 2001 From: keshav Sharma <72795959+ksharma20@users.noreply.github.com> Date: Sun, 24 Jul 2022 21:33:10 +0530 Subject: [PATCH 297/726] chore: rename gcd to greatest_common_divisor (#6265) As described in CONTRIBUTING.md > Expand acronyms because gcd() is hard to understand but greatest_common_divisor() is not. Co-authored-by: Dhruv Manilawala --- project_euler/problem_005/sol2.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/project_euler/problem_005/sol2.py b/project_euler/problem_005/sol2.py index c88044487..1b3e5e130 100644 --- a/project_euler/problem_005/sol2.py +++ b/project_euler/problem_005/sol2.py @@ -16,28 +16,28 @@ References: """ -def gcd(x: int, y: int) -> int: +def greatest_common_divisor(x: int, y: int) -> int: """ - Euclidean GCD algorithm (Greatest Common Divisor) + Euclidean Greatest Common Divisor algorithm - >>> gcd(0, 0) + >>> greatest_common_divisor(0, 0) 0 - >>> gcd(23, 42) + >>> greatest_common_divisor(23, 42) 1 - >>> gcd(15, 33) + >>> greatest_common_divisor(15, 33) 3 - >>> gcd(12345, 67890) + >>> greatest_common_divisor(12345, 67890) 15 """ - return x if y == 0 else gcd(y, x % y) + return x if y == 0 else greatest_common_divisor(y, x % y) def lcm(x: int, y: int) -> int: """ Least Common Multiple. - Using the property that lcm(a, b) * gcd(a, b) = a*b + Using the property that lcm(a, b) * greatest_common_divisor(a, b) = a*b >>> lcm(3, 15) 15 @@ -49,7 +49,7 @@ def lcm(x: int, y: int) -> int: 192 """ - return (x * y) // gcd(x, y) + return (x * y) // greatest_common_divisor(x, y) def solution(n: int = 20) -> int: From 90959212e5b0f3cfbae95ea38100e6fee4d2475f Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Mon, 25 Jul 2022 19:41:12 +0300 Subject: [PATCH 298/726] perf: improve Project Euler problem 030 solution 1 (#6267) Improve solution (locally 3+ times - from 3+ seconds to ~1 second) Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- project_euler/problem_030/sol1.py | 32 ++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/project_euler/problem_030/sol1.py b/project_euler/problem_030/sol1.py index c9f2d7196..2c6b4e4e8 100644 --- a/project_euler/problem_030/sol1.py +++ b/project_euler/problem_030/sol1.py @@ -1,4 +1,4 @@ -""" Problem Statement (Digit Fifth Power ): https://projecteuler.net/problem=30 +""" Problem Statement (Digit Fifth Powers): https://projecteuler.net/problem=30 Surprisingly there are only three numbers that can be written as the sum of fourth powers of their digits: @@ -13,26 +13,32 @@ The sum of these numbers is 1634 + 8208 + 9474 = 19316. Find the sum of all the numbers that can be written as the sum of fifth powers of their digits. -(9^5)=59,049‬ -59049*7=4,13,343 (which is only 6 digit number ) -So, number greater than 9,99,999 are rejected -and also 59049*3=1,77,147 (which exceeds the criteria of number being 3 digit) -So, n>999 -and hence a bound between (1000,1000000) +9^5 = 59049 +59049 * 7 = 413343 (which is only 6 digit number) +So, numbers greater than 999999 are rejected +and also 59049 * 3 = 177147 (which exceeds the criteria of number being 3 digit) +So, number > 999 +and hence a number between 1000 and 1000000 """ -def digitsum(s: str) -> int: +DIGITS_FIFTH_POWER = {str(digit): digit**5 for digit in range(10)} + + +def digits_fifth_powers_sum(number: int) -> int: """ - >>> all(digitsum(str(i)) == (1 if i == 1 else 0) for i in range(100)) - True + >>> digits_fifth_powers_sum(1234) + 1300 """ - i = sum(pow(int(c), 5) for c in s) - return i if i == int(s) else 0 + return sum(DIGITS_FIFTH_POWER[digit] for digit in str(number)) def solution() -> int: - return sum(digitsum(str(i)) for i in range(1000, 1000000)) + return sum( + number + for number in range(1000, 1000000) + if number == digits_fifth_powers_sum(number) + ) if __name__ == "__main__": From 97f25d4b431ffe432a30853ed0bcc75ea5e8166f Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Tue, 26 Jul 2022 19:15:14 +0300 Subject: [PATCH 299/726] feat: add Project Euler problem 587 solution 1 (#6269) Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 2 + project_euler/problem_587/__init__.py | 0 project_euler/problem_587/sol1.py | 94 +++++++++++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 project_euler/problem_587/__init__.py create mode 100644 project_euler/problem_587/sol1.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 1ee106252..843ff77bb 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -898,6 +898,8 @@ * [Sol1](project_euler/problem_493/sol1.py) * Problem 551 * [Sol1](project_euler/problem_551/sol1.py) + * Problem 587 + * [Sol1](project_euler/problem_587/sol1.py) * Problem 686 * [Sol1](project_euler/problem_686/sol1.py) diff --git a/project_euler/problem_587/__init__.py b/project_euler/problem_587/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_587/sol1.py b/project_euler/problem_587/sol1.py new file mode 100644 index 000000000..dde5c1610 --- /dev/null +++ b/project_euler/problem_587/sol1.py @@ -0,0 +1,94 @@ +""" +Project Euler Problem 587: https://projecteuler.net/problem=587 + +A square is drawn around a circle as shown in the diagram below on the left. +We shall call the blue shaded region the L-section. +A line is drawn from the bottom left of the square to the top right +as shown in the diagram on the right. +We shall call the orange shaded region a concave triangle. + +It should be clear that the concave triangle occupies exactly half of the L-section. + +Two circles are placed next to each other horizontally, +a rectangle is drawn around both circles, and +a line is drawn from the bottom left to the top right as shown in the diagram below. + +This time the concave triangle occupies approximately 36.46% of the L-section. + +If n circles are placed next to each other horizontally, +a rectangle is drawn around the n circles, and +a line is drawn from the bottom left to the top right, +then it can be shown that the least value of n +for which the concave triangle occupies less than 10% of the L-section is n = 15. + +What is the least value of n +for which the concave triangle occupies less than 0.1% of the L-section? +""" + +from itertools import count +from math import asin, pi, sqrt + + +def circle_bottom_arc_integral(point: float) -> float: + """ + Returns integral of circle bottom arc y = 1 / 2 - sqrt(1 / 4 - (x - 1 / 2) ^ 2) + + >>> circle_bottom_arc_integral(0) + 0.39269908169872414 + + >>> circle_bottom_arc_integral(1 / 2) + 0.44634954084936207 + + >>> circle_bottom_arc_integral(1) + 0.5 + """ + + return ( + (1 - 2 * point) * sqrt(point - point**2) + 2 * point + asin(sqrt(1 - point)) + ) / 4 + + +def concave_triangle_area(circles_number: int) -> float: + """ + Returns area of concave triangle + + >>> concave_triangle_area(1) + 0.026825229575318944 + + >>> concave_triangle_area(2) + 0.01956236140083944 + """ + + intersection_y = (circles_number + 1 - sqrt(2 * circles_number)) / ( + 2 * (circles_number**2 + 1) + ) + intersection_x = circles_number * intersection_y + + triangle_area = intersection_x * intersection_y / 2 + concave_region_area = circle_bottom_arc_integral( + 1 / 2 + ) - circle_bottom_arc_integral(intersection_x) + + return triangle_area + concave_region_area + + +def solution(fraction: float = 1 / 1000) -> int: + """ + Returns least value of n + for which the concave triangle occupies less than fraction of the L-section + + >>> solution(1 / 10) + 15 + """ + + l_section_area = (1 - pi / 4) / 4 + + for n in count(1): + if concave_triangle_area(n) / l_section_area < fraction: + return n + + return -1 + + +if __name__ == "__main__": + print(f"{solution() = }") From defc205ef4459264b753429c6cbc23481347e8b7 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sat, 6 Aug 2022 17:04:24 +0300 Subject: [PATCH 300/726] perf: improve Project Euler problem 203 solution 1 (#6279) Improve solution (locally 1500+ times - from 3+ seconds to ~2 milliseconds) Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- project_euler/problem_203/sol1.py | 112 ++++++------------------------ 1 file changed, 21 insertions(+), 91 deletions(-) diff --git a/project_euler/problem_203/sol1.py b/project_euler/problem_203/sol1.py index 2ba3c96c9..dc93683da 100644 --- a/project_euler/problem_203/sol1.py +++ b/project_euler/problem_203/sol1.py @@ -29,8 +29,6 @@ References: """ from __future__ import annotations -import math - def get_pascal_triangle_unique_coefficients(depth: int) -> set[int]: """ @@ -61,76 +59,9 @@ def get_pascal_triangle_unique_coefficients(depth: int) -> set[int]: return coefficients -def get_primes_squared(max_number: int) -> list[int]: +def get_squarefrees(unique_coefficients: set[int]) -> set[int]: """ - Calculates all primes between 2 and round(sqrt(max_number)) and returns - them squared up. - - >>> get_primes_squared(2) - [] - >>> get_primes_squared(4) - [4] - >>> get_primes_squared(10) - [4, 9] - >>> get_primes_squared(100) - [4, 9, 25, 49] - """ - max_prime = math.isqrt(max_number) - non_primes = [False] * (max_prime + 1) - primes = [] - for num in range(2, max_prime + 1): - if non_primes[num]: - continue - - for num_counter in range(num**2, max_prime + 1, num): - non_primes[num_counter] = True - - primes.append(num**2) - return primes - - -def get_squared_primes_to_use( - num_to_look: int, squared_primes: list[int], previous_index: int -) -> int: - """ - Returns an int indicating the last index on which squares of primes - in primes are lower than num_to_look. - - This method supposes that squared_primes is sorted in ascending order and that - each num_to_look is provided in ascending order as well. Under these - assumptions, it needs a previous_index parameter that tells what was - the index returned by the method for the previous num_to_look. - - If all the elements in squared_primes are greater than num_to_look, then the - method returns -1. - - >>> get_squared_primes_to_use(1, [4, 9, 16, 25], 0) - -1 - >>> get_squared_primes_to_use(4, [4, 9, 16, 25], 0) - 1 - >>> get_squared_primes_to_use(16, [4, 9, 16, 25], 1) - 3 - """ - idx = max(previous_index, 0) - - while idx < len(squared_primes) and squared_primes[idx] <= num_to_look: - idx += 1 - - if idx == 0 and squared_primes[idx] > num_to_look: - return -1 - - if idx == len(squared_primes) and squared_primes[-1] > num_to_look: - return -1 - - return idx - - -def get_squarefree( - unique_coefficients: set[int], squared_primes: list[int] -) -> set[int]: - """ - Calculates the squarefree numbers inside unique_coefficients given a - list of square of primes. + Calculates the squarefree numbers inside unique_coefficients. Based on the definition of a non-squarefree number, then any non-squarefree n can be decomposed as n = p*p*r, where p is positive prime number and r @@ -140,27 +71,27 @@ def get_squarefree( squarefree as r cannot be negative. On the contrary, if any r exists such that n = p*p*r, then the number is non-squarefree. - >>> get_squarefree({1}, []) - set() - >>> get_squarefree({1, 2}, []) - set() - >>> get_squarefree({1, 2, 3, 4, 5, 6, 7, 35, 10, 15, 20, 21}, [4, 9, 25]) + >>> get_squarefrees({1}) + {1} + >>> get_squarefrees({1, 2}) + {1, 2} + >>> get_squarefrees({1, 2, 3, 4, 5, 6, 7, 35, 10, 15, 20, 21}) {1, 2, 3, 5, 6, 7, 35, 10, 15, 21} """ - if len(squared_primes) == 0: - return set() - non_squarefrees = set() - prime_squared_idx = 0 - for num in sorted(unique_coefficients): - prime_squared_idx = get_squared_primes_to_use( - num, squared_primes, prime_squared_idx - ) - if prime_squared_idx == -1: - continue - if any(num % prime == 0 for prime in squared_primes[:prime_squared_idx]): - non_squarefrees.add(num) + for number in unique_coefficients: + divisor = 2 + copy_number = number + while divisor**2 <= copy_number: + multiplicity = 0 + while copy_number % divisor == 0: + copy_number //= divisor + multiplicity += 1 + if multiplicity >= 2: + non_squarefrees.add(number) + break + divisor += 1 return unique_coefficients.difference(non_squarefrees) @@ -170,15 +101,14 @@ def solution(n: int = 51) -> int: Returns the sum of squarefrees for a given Pascal's Triangle of depth n. >>> solution(1) - 0 + 1 >>> solution(8) 105 >>> solution(9) 175 """ unique_coefficients = get_pascal_triangle_unique_coefficients(n) - primes = get_primes_squared(max(unique_coefficients)) - squarefrees = get_squarefree(unique_coefficients, primes) + squarefrees = get_squarefrees(unique_coefficients) return sum(squarefrees) From 9eac958725c8e5c62b225c77eaf83ec0ecb7e6f6 Mon Sep 17 00:00:00 2001 From: Horst JENS Date: Sat, 6 Aug 2022 17:47:56 +0200 Subject: [PATCH 301/726] typo corrected: heart -> Earth (#6275) --- physics/horizontal_projectile_motion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/physics/horizontal_projectile_motion.py b/physics/horizontal_projectile_motion.py index 0f27b0617..a747acd72 100644 --- a/physics/horizontal_projectile_motion.py +++ b/physics/horizontal_projectile_motion.py @@ -17,7 +17,7 @@ For more info: https://en.wikipedia.org/wiki/Projectile_motion from math import radians as angle_to_radians from math import sin -# Acceleration Constant on hearth (unit m/s^2) +# Acceleration Constant on Earth (unit m/s^2) g = 9.80665 From a69d880bb5e9113ccf09aeaa31a570330f856417 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sun, 7 Aug 2022 05:07:35 +0300 Subject: [PATCH 302/726] feat: add Project Euler problem 114 solution 1 (#6300) Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 2 + project_euler/problem_114/__init__.py | 0 project_euler/problem_114/sol1.py | 58 +++++++++++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 project_euler/problem_114/__init__.py create mode 100644 project_euler/problem_114/sol1.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 843ff77bb..98b87f2fe 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -854,6 +854,8 @@ * [Sol1](project_euler/problem_112/sol1.py) * Problem 113 * [Sol1](project_euler/problem_113/sol1.py) + * Problem 114 + * [Sol1](project_euler/problem_114/sol1.py) * Problem 119 * [Sol1](project_euler/problem_119/sol1.py) * Problem 120 diff --git a/project_euler/problem_114/__init__.py b/project_euler/problem_114/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_114/sol1.py b/project_euler/problem_114/sol1.py new file mode 100644 index 000000000..14d8092b2 --- /dev/null +++ b/project_euler/problem_114/sol1.py @@ -0,0 +1,58 @@ +""" +Project Euler Problem 114: https://projecteuler.net/problem=114 + +A row measuring seven units in length has red blocks with a minimum length +of three units placed on it, such that any two red blocks +(which are allowed to be different lengths) are separated by at least one grey square. +There are exactly seventeen ways of doing this. + + |g|g|g|g|g|g|g| |r,r,r|g|g|g|g| + + |g|r,r,r|g|g|g| |g|g|r,r,r|g|g| + + |g|g|g|r,r,r|g| |g|g|g|g|r,r,r| + + |r,r,r|g|r,r,r| |r,r,r,r|g|g|g| + + |g|r,r,r,r|g|g| |g|g|r,r,r,r|g| + + |g|g|g|r,r,r,r| |r,r,r,r,r|g|g| + + |g|r,r,r,r,r|g| |g|g|r,r,r,r,r| + + |r,r,r,r,r,r|g| |g|r,r,r,r,r,r| + + |r,r,r,r,r,r,r| + +How many ways can a row measuring fifty units in length be filled? + +NOTE: Although the example above does not lend itself to the possibility, +in general it is permitted to mix block sizes. For example, +on a row measuring eight units in length you could use red (3), grey (1), and red (4). +""" + + +def solution(length: int = 50) -> int: + """ + Returns the number of ways a row of the given length can be filled + + >>> solution(7) + 17 + """ + + ways_number = [1] * (length + 1) + + for row_length in range(3, length + 1): + for block_length in range(3, row_length + 1): + for block_start in range(row_length - block_length): + ways_number[row_length] += ways_number[ + row_length - block_start - block_length - 1 + ] + + ways_number[row_length] += 1 + + return ways_number[length] + + +if __name__ == "__main__": + print(f"{solution() = }") From 063a0eced918ffa58af99c9c8d2fab72ea519c59 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sun, 7 Aug 2022 14:20:45 +0300 Subject: [PATCH 303/726] feat: add Project Euler problem 115 solution 1 (#6303) Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 2 + project_euler/problem_115/__init__.py | 0 project_euler/problem_115/sol1.py | 62 +++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 project_euler/problem_115/__init__.py create mode 100644 project_euler/problem_115/sol1.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 98b87f2fe..b37bb35ec 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -856,6 +856,8 @@ * [Sol1](project_euler/problem_113/sol1.py) * Problem 114 * [Sol1](project_euler/problem_114/sol1.py) + * Problem 115 + * [Sol1](project_euler/problem_115/sol1.py) * Problem 119 * [Sol1](project_euler/problem_119/sol1.py) * Problem 120 diff --git a/project_euler/problem_115/__init__.py b/project_euler/problem_115/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_115/sol1.py b/project_euler/problem_115/sol1.py new file mode 100644 index 000000000..15a13516d --- /dev/null +++ b/project_euler/problem_115/sol1.py @@ -0,0 +1,62 @@ +""" +Project Euler Problem 115: https://projecteuler.net/problem=115 + +NOTE: This is a more difficult version of Problem 114 +(https://projecteuler.net/problem=114). + +A row measuring n units in length has red blocks +with a minimum length of m units placed on it, such that any two red blocks +(which are allowed to be different lengths) are separated by at least one black square. + +Let the fill-count function, F(m, n), +represent the number of ways that a row can be filled. + +For example, F(3, 29) = 673135 and F(3, 30) = 1089155. + +That is, for m = 3, it can be seen that n = 30 is the smallest value +for which the fill-count function first exceeds one million. + +In the same way, for m = 10, it can be verified that +F(10, 56) = 880711 and F(10, 57) = 1148904, so n = 57 is the least value +for which the fill-count function first exceeds one million. + +For m = 50, find the least value of n +for which the fill-count function first exceeds one million. +""" + +from itertools import count + + +def solution(min_block_length: int = 50) -> int: + """ + Returns for given minimum block length the least value of n + for which the fill-count function first exceeds one million + + >>> solution(3) + 30 + + >>> solution(10) + 57 + """ + + fill_count_functions = [1] * min_block_length + + for n in count(min_block_length): + fill_count_functions.append(1) + + for block_length in range(min_block_length, n + 1): + for block_start in range(n - block_length): + fill_count_functions[n] += fill_count_functions[ + n - block_start - block_length - 1 + ] + + fill_count_functions[n] += 1 + + if fill_count_functions[n] > 1_000_000: + break + + return n + + +if __name__ == "__main__": + print(f"{solution() = }") From f46ce47274e89ab52581b56fec0aefa0e844dfa7 Mon Sep 17 00:00:00 2001 From: AmirMohammad Hosseini Nasab <19665344+itsamirhn@users.noreply.github.com> Date: Fri, 12 Aug 2022 13:42:58 +0430 Subject: [PATCH 304/726] Add Max Fenwick Tree (#6298) * Add `MaxFenwickTree` * Reformat code style * Fix type hints * Fix type hints again * Complete docstring * Complete docstring * Fix typo in file name * Change MaxFenwickTree into 0-based indexing * Fix Bugs * Minor fix --- .../binary_tree/maximum_fenwick_tree.py | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 data_structures/binary_tree/maximum_fenwick_tree.py diff --git a/data_structures/binary_tree/maximum_fenwick_tree.py b/data_structures/binary_tree/maximum_fenwick_tree.py new file mode 100644 index 000000000..e90bd634d --- /dev/null +++ b/data_structures/binary_tree/maximum_fenwick_tree.py @@ -0,0 +1,102 @@ +class MaxFenwickTree: + """ + Maximum Fenwick Tree + + More info: https://cp-algorithms.com/data_structures/fenwick.html + --------- + >>> ft = MaxFenwickTree(5) + >>> ft.query(0, 5) + 0 + >>> ft.update(4, 100) + >>> ft.query(0, 5) + 100 + >>> ft.update(4, 0) + >>> ft.update(2, 20) + >>> ft.query(0, 5) + 20 + >>> ft.update(4, 10) + >>> ft.query(2, 5) + 10 + >>> ft.query(1, 5) + 20 + >>> ft.update(2, 0) + >>> ft.query(0, 5) + 10 + >>> ft = MaxFenwickTree(10000) + >>> ft.update(255, 30) + >>> ft.query(0, 10000) + 30 + """ + + def __init__(self, size: int) -> None: + """ + Create empty Maximum Fenwick Tree with specified size + + Parameters: + size: size of Array + + Returns: + None + """ + self.size = size + self.arr = [0] * size + self.tree = [0] * size + + @staticmethod + def get_next(index: int) -> int: + """ + Get next index in O(1) + """ + return index + (index & -index) + + @staticmethod + def get_prev(index: int) -> int: + """ + Get previous index in O(1) + """ + return index - (index & -index) + + def update(self, index: int, value: int) -> None: + """ + Set index to value in O(lg^2 N) + + Parameters: + index: index to update + value: value to set + + Returns: + None + """ + self.arr[index] = value + while index < self.size: + self.tree[index] = max(value, self.query(self.get_prev(index), index)) + index = self.get_next(index) + + def query(self, left: int, right: int) -> int: + """ + Answer the query of maximum range [l, r) in O(lg^2 N) + + Parameters: + left: left index of query range (inclusive) + right: right index of query range (exclusive) + + Returns: + Maximum value of range [left, right) + """ + right -= 1 # Because of right is exclusive + result = 0 + while left < right: + current_left = self.get_prev(right) + if left < current_left: + result = max(result, self.tree[right]) + right = current_left + else: + result = max(result, self.arr[right]) + right -= 1 + return result + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From f31fa4ea7e26d8721be7e966ecf92fcbd87af65f Mon Sep 17 00:00:00 2001 From: AmirMohammad Hosseini Nasab <19665344+itsamirhn@users.noreply.github.com> Date: Tue, 16 Aug 2022 22:08:33 +0430 Subject: [PATCH 305/726] Fenwick Tree (#6319) * Enhance fenwick_tree.py * Change update to add in fenwick_tree.py * Some changes * Fix bug * Add O(N) initializer to FenwickTree * Add get method to Fenwick Tree * Change tree in Fenwick Tree * Add rank query to FenwickTree * Add get_array method to FenwickTree * Add some tests * Update data_structures/binary_tree/fenwick_tree.py Co-authored-by: Christian Clauss * Update data_structures/binary_tree/fenwick_tree.py Co-authored-by: Christian Clauss * Update data_structures/binary_tree/fenwick_tree.py Co-authored-by: Christian Clauss * change `List` to `list` Co-authored-by: Christian Clauss --- data_structures/binary_tree/fenwick_tree.py | 263 ++++++++++++++++++-- 1 file changed, 241 insertions(+), 22 deletions(-) diff --git a/data_structures/binary_tree/fenwick_tree.py b/data_structures/binary_tree/fenwick_tree.py index 54f0f07ac..96020d142 100644 --- a/data_structures/binary_tree/fenwick_tree.py +++ b/data_structures/binary_tree/fenwick_tree.py @@ -1,28 +1,247 @@ +from copy import deepcopy + + class FenwickTree: - def __init__(self, SIZE): # create fenwick tree with size SIZE - self.Size = SIZE - self.ft = [0 for i in range(0, SIZE)] + """ + Fenwick Tree - def update(self, i, val): # update data (adding) in index i in O(lg N) - while i < self.Size: - self.ft[i] += val - i += i & (-i) + More info: https://en.wikipedia.org/wiki/Fenwick_tree + """ - def query(self, i): # query cumulative data from index 0 to i in O(lg N) - ret = 0 - while i > 0: - ret += self.ft[i] - i -= i & (-i) - return ret + def __init__(self, arr: list[int] = None, size: int = None) -> None: + """ + Constructor for the Fenwick tree + + Parameters: + arr (list): list of elements to initialize the tree with (optional) + size (int): size of the Fenwick tree (if arr is None) + """ + + if arr is None and size is not None: + self.size = size + self.tree = [0] * size + elif arr is not None: + self.init(arr) + else: + raise ValueError("Either arr or size must be specified") + + def init(self, arr: list[int]) -> None: + """ + Initialize the Fenwick tree with arr in O(N) + + Parameters: + arr (list): list of elements to initialize the tree with + + Returns: + None + + >>> a = [1, 2, 3, 4, 5] + >>> f1 = FenwickTree(a) + >>> f2 = FenwickTree(size=len(a)) + >>> for index, value in enumerate(a): + ... f2.add(index, value) + >>> f1.tree == f2.tree + True + """ + self.size = len(arr) + self.tree = deepcopy(arr) + for i in range(1, self.size): + j = self.next(i) + if j < self.size: + self.tree[j] += self.tree[i] + + def get_array(self) -> list[int]: + """ + Get the Normal Array of the Fenwick tree in O(N) + + Returns: + list: Normal Array of the Fenwick tree + + >>> a = [i for i in range(128)] + >>> f = FenwickTree(a) + >>> f.get_array() == a + True + """ + arr = self.tree[:] + for i in range(self.size - 1, 0, -1): + j = self.next(i) + if j < self.size: + arr[j] -= arr[i] + return arr + + @staticmethod + def next(index: int) -> int: + return index + (index & (-index)) + + @staticmethod + def prev(index: int) -> int: + return index - (index & (-index)) + + def add(self, index: int, value: int) -> None: + """ + Add a value to index in O(lg N) + + Parameters: + index (int): index to add value to + value (int): value to add to index + + Returns: + None + + >>> f = FenwickTree([1, 2, 3, 4, 5]) + >>> f.add(0, 1) + >>> f.add(1, 2) + >>> f.add(2, 3) + >>> f.add(3, 4) + >>> f.add(4, 5) + >>> f.get_array() + [2, 4, 6, 8, 10] + """ + if index == 0: + self.tree[0] += value + return + while index < self.size: + self.tree[index] += value + index = self.next(index) + + def update(self, index: int, value: int) -> None: + """ + Set the value of index in O(lg N) + + Parameters: + index (int): index to set value to + value (int): value to set in index + + Returns: + None + + >>> f = FenwickTree([5, 4, 3, 2, 1]) + >>> f.update(0, 1) + >>> f.update(1, 2) + >>> f.update(2, 3) + >>> f.update(3, 4) + >>> f.update(4, 5) + >>> f.get_array() + [1, 2, 3, 4, 5] + """ + self.add(index, value - self.get(index)) + + def prefix(self, right: int) -> int: + """ + Prefix sum of all elements in [0, right) in O(lg N) + + Parameters: + right (int): right bound of the query (exclusive) + + Returns: + int: sum of all elements in [0, right) + + >>> a = [i for i in range(128)] + >>> f = FenwickTree(a) + >>> res = True + >>> for i in range(len(a)): + ... res = res and f.prefix(i) == sum(a[:i]) + >>> res + True + """ + if right == 0: + return 0 + result = self.tree[0] + right -= 1 # make right inclusive + while right > 0: + result += self.tree[right] + right = self.prev(right) + return result + + def query(self, left: int, right: int) -> int: + """ + Query the sum of all elements in [left, right) in O(lg N) + + Parameters: + left (int): left bound of the query (inclusive) + right (int): right bound of the query (exclusive) + + Returns: + int: sum of all elements in [left, right) + + >>> a = [i for i in range(128)] + >>> f = FenwickTree(a) + >>> res = True + >>> for i in range(len(a)): + ... for j in range(i + 1, len(a)): + ... res = res and f.query(i, j) == sum(a[i:j]) + >>> res + True + """ + return self.prefix(right) - self.prefix(left) + + def get(self, index: int) -> int: + """ + Get value at index in O(lg N) + + Parameters: + index (int): index to get the value + + Returns: + int: Value of element at index + + >>> a = [i for i in range(128)] + >>> f = FenwickTree(a) + >>> res = True + >>> for i in range(len(a)): + ... res = res and f.get(i) == a[i] + >>> res + True + """ + return self.query(index, index + 1) + + def rank_query(self, value: int) -> int: + """ + Find the largest index with prefix(i) <= value in O(lg N) + NOTE: Requires that all values are non-negative! + + Parameters: + value (int): value to find the largest index of + + Returns: + -1: if value is smaller than all elements in prefix sum + int: largest index with prefix(i) <= value + + >>> f = FenwickTree([1, 2, 0, 3, 0, 5]) + >>> f.rank_query(0) + -1 + >>> f.rank_query(2) + 0 + >>> f.rank_query(1) + 0 + >>> f.rank_query(3) + 2 + >>> f.rank_query(5) + 2 + >>> f.rank_query(6) + 4 + >>> f.rank_query(11) + 5 + """ + value -= self.tree[0] + if value < 0: + return -1 + + j = 1 # Largest power of 2 <= size + while j * 2 < self.size: + j *= 2 + + i = 0 + + while j > 0: + if i + j < self.size and self.tree[i + j] <= value: + value -= self.tree[i + j] + i += j + j //= 2 + return i if __name__ == "__main__": - f = FenwickTree(100) - f.update(1, 20) - f.update(4, 4) - print(f.query(1)) - print(f.query(3)) - print(f.query(4)) - f.update(2, -5) - print(f.query(1)) - print(f.query(3)) + import doctest + + doctest.testmod() From b1818af5171ecf149b5a602572a7361c5e624f0d Mon Sep 17 00:00:00 2001 From: zhexuanl <63616187+zhexuanl@users.noreply.github.com> Date: Wed, 24 Aug 2022 12:48:54 +0800 Subject: [PATCH 306/726] Add Digital Image Processing Algorithm: Local Binary Pattern (#6294) * add algorithm local binary pattern * fix failed test for local binary pattern * updating DIRECTORY.md * fix detected precommit-error * fix precommit error * final check * Add descriptive name for parameters x and y * Update digital_image_processing/filters/local_binary_pattern.py Co-authored-by: Christian Clauss * Update digital_image_processing/filters/local_binary_pattern.py Co-authored-by: Christian Clauss * Update digital_image_processing/filters/local_binary_pattern.py Co-authored-by: Christian Clauss * Update local_binary_pattern.py * undo changes made on get_neighbors_pixel() * files formatted by black * Update digital_image_processing/filters/local_binary_pattern.py ok thanks Co-authored-by: Christian Clauss * add test for get_neighbors_pixel() function * reviewed * fix get_neighbors_pixel * Update test_digital_image_processing.py * updating DIRECTORY.md * Create code_quality.yml * Create code_quality.yml * Delete code_quality.yml * Update code_quality.yml * Delete code_quality.yml Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss --- DIRECTORY.md | 2 + .../filters/local_binary_pattern.py | 81 +++++++++++++++++++ .../test_digital_image_processing.py | 32 ++++++++ 3 files changed, 115 insertions(+) create mode 100644 digital_image_processing/filters/local_binary_pattern.py diff --git a/DIRECTORY.md b/DIRECTORY.md index b37bb35ec..a7305395a 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -152,6 +152,7 @@ * [Fenwick Tree](data_structures/binary_tree/fenwick_tree.py) * [Lazy Segment Tree](data_structures/binary_tree/lazy_segment_tree.py) * [Lowest Common Ancestor](data_structures/binary_tree/lowest_common_ancestor.py) + * [Maximum Fenwick Tree](data_structures/binary_tree/maximum_fenwick_tree.py) * [Merge Two Binary Trees](data_structures/binary_tree/merge_two_binary_trees.py) * [Non Recursive Segment Tree](data_structures/binary_tree/non_recursive_segment_tree.py) * [Number Of Possible Binary Trees](data_structures/binary_tree/number_of_possible_binary_trees.py) @@ -229,6 +230,7 @@ * [Convolve](digital_image_processing/filters/convolve.py) * [Gabor Filter](digital_image_processing/filters/gabor_filter.py) * [Gaussian Filter](digital_image_processing/filters/gaussian_filter.py) + * [Local Binary Pattern](digital_image_processing/filters/local_binary_pattern.py) * [Median Filter](digital_image_processing/filters/median_filter.py) * [Sobel Filter](digital_image_processing/filters/sobel_filter.py) * Histogram Equalization diff --git a/digital_image_processing/filters/local_binary_pattern.py b/digital_image_processing/filters/local_binary_pattern.py new file mode 100644 index 000000000..e73aa59bf --- /dev/null +++ b/digital_image_processing/filters/local_binary_pattern.py @@ -0,0 +1,81 @@ +import cv2 +import numpy as np + + +def get_neighbors_pixel( + image: np.ndarray, x_coordinate: int, y_coordinate: int, center: int +) -> int: + """ + Comparing local neighborhood pixel value with threshold value of centre pixel. + Exception is required when neighborhood value of a center pixel value is null. + i.e. values present at boundaries. + + :param image: The image we're working with + :param x_coordinate: x-coordinate of the pixel + :param y_coordinate: The y coordinate of the pixel + :param center: center pixel value + :return: The value of the pixel is being returned. + """ + + try: + return int(image[x_coordinate][y_coordinate] >= center) + except (IndexError, TypeError): + return 0 + + +def local_binary_value(image: np.ndarray, x_coordinate: int, y_coordinate: int) -> int: + """ + It takes an image, an x and y coordinate, and returns the + decimal value of the local binary patternof the pixel + at that coordinate + + :param image: the image to be processed + :param x_coordinate: x coordinate of the pixel + :param y_coordinate: the y coordinate of the pixel + :return: The decimal value of the binary value of the pixels + around the center pixel. + """ + center = image[x_coordinate][y_coordinate] + powers = [1, 2, 4, 8, 16, 32, 64, 128] + + # skip get_neighbors_pixel if center is null + if center is None: + return 0 + + # Starting from the top right, assigning value to pixels clockwise + binary_values = [ + get_neighbors_pixel(image, x_coordinate - 1, y_coordinate + 1, center), + get_neighbors_pixel(image, x_coordinate, y_coordinate + 1, center), + get_neighbors_pixel(image, x_coordinate - 1, y_coordinate, center), + get_neighbors_pixel(image, x_coordinate + 1, y_coordinate + 1, center), + get_neighbors_pixel(image, x_coordinate + 1, y_coordinate, center), + get_neighbors_pixel(image, x_coordinate + 1, y_coordinate - 1, center), + get_neighbors_pixel(image, x_coordinate, y_coordinate - 1, center), + get_neighbors_pixel(image, x_coordinate - 1, y_coordinate - 1, center), + ] + + # Converting the binary value to decimal. + return sum( + binary_value * power for binary_value, power in zip(binary_values, powers) + ) + + +if __name__ == "main": + + # Reading the image and converting it to grayscale. + image = cv2.imread( + "digital_image_processing/image_data/lena.jpg", cv2.IMREAD_GRAYSCALE + ) + + # Create a numpy array as the same height and width of read image + lbp_image = np.zeros((image.shape[0], image.shape[1])) + + # Iterating through the image and calculating the + # local binary pattern value for each pixel. + for i in range(0, image.shape[0]): + for j in range(0, image.shape[1]): + lbp_image[i][j] = local_binary_value(image, i, j) + + cv2.imshow("local binary pattern", lbp_image) + cv2.waitKey(0) + cv2.destroyAllWindows() diff --git a/digital_image_processing/test_digital_image_processing.py b/digital_image_processing/test_digital_image_processing.py index 40f2f7b83..1f42fddf2 100644 --- a/digital_image_processing/test_digital_image_processing.py +++ b/digital_image_processing/test_digital_image_processing.py @@ -1,6 +1,7 @@ """ PyTest's for Digital Image Processing """ +import numpy as np from cv2 import COLOR_BGR2GRAY, cvtColor, imread from numpy import array, uint8 from PIL import Image @@ -12,6 +13,7 @@ from digital_image_processing.dithering import burkes as bs from digital_image_processing.edge_detection import canny as canny from digital_image_processing.filters import convolve as conv from digital_image_processing.filters import gaussian_filter as gg +from digital_image_processing.filters import local_binary_pattern as lbp from digital_image_processing.filters import median_filter as med from digital_image_processing.filters import sobel_filter as sob from digital_image_processing.resize import resize as rs @@ -91,3 +93,33 @@ def test_nearest_neighbour( nn = rs.NearestNeighbour(imread(file_path, 1), 400, 200) nn.process() assert nn.output.any() + + +def test_local_binary_pattern(): + file_path: str = "digital_image_processing/image_data/lena.jpg" + + # Reading the image and converting it to grayscale. + image = imread(file_path, 0) + + # Test for get_neighbors_pixel function() return not None + x_coordinate = 0 + y_coordinate = 0 + center = image[x_coordinate][y_coordinate] + + neighbors_pixels = lbp.get_neighbors_pixel( + image, x_coordinate, y_coordinate, center + ) + + assert neighbors_pixels is not None + + # Test for local_binary_pattern function() + # Create a numpy array as the same height and width of read image + lbp_image = np.zeros((image.shape[0], image.shape[1])) + + # Iterating through the image and calculating the local binary pattern value + # for each pixel. + for i in range(0, image.shape[0]): + for j in range(0, image.shape[1]): + lbp_image[i][j] = lbp.local_binary_value(image, i, j) + + assert lbp_image.any() From cbf3c6140aafefbaef7186e0cb97d0758b1d38b2 Mon Sep 17 00:00:00 2001 From: Margaret <62753112+meg-1@users.noreply.github.com> Date: Mon, 5 Sep 2022 04:51:11 +0300 Subject: [PATCH 307/726] add the dna algorithm (#6323) * adding the dna algorithm * following bot recommendations following bot recommendations for the indentation * following bot recommendations following bot recommendations regarding indentation [ again ] * following bot recommendations following bot recommendations regarding indentation [ again. ] * following bot recommendations following bot recommendations. --- strings/dna.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 strings/dna.py diff --git a/strings/dna.py b/strings/dna.py new file mode 100644 index 000000000..46e271d68 --- /dev/null +++ b/strings/dna.py @@ -0,0 +1,26 @@ +import re + + +def dna(dna: str) -> str: + + """ + https://en.wikipedia.org/wiki/DNA + Returns the second side of a DNA strand + + >>> dna("GCTA") + 'CGAT' + >>> dna("ATGC") + 'TACG' + >>> dna("CTGA") + 'GACT' + >>> dna("GFGG") + 'Invalid Strand' + """ + + r = len(re.findall("[ATCG]", dna)) != len(dna) + val = dna.translate(dna.maketrans("ATCG", "TAGC")) + return "Invalid Strand" if r else val + + +if __name__ == "__main__": + __import__("doctest").testmod() From 4e4fe95369c15e62364f7d6a6bfc9464c1143dc6 Mon Sep 17 00:00:00 2001 From: Nikhil Kala Date: Fri, 9 Sep 2022 11:09:31 -0600 Subject: [PATCH 308/726] chore: remove the PayPal badge (#6348) --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 0298d4602..c78797960 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,6 @@ Contributions Welcome - - Donate - Discord chat From 81e30fd33c91bc37bc3baf54c42d1b192ecf41a6 Mon Sep 17 00:00:00 2001 From: C21 <31063253+C21-github@users.noreply.github.com> Date: Wed, 14 Sep 2022 13:54:55 +0530 Subject: [PATCH 309/726] Fix Max Fenwick Tree (#6328) --- .../binary_tree/maximum_fenwick_tree.py | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/data_structures/binary_tree/maximum_fenwick_tree.py b/data_structures/binary_tree/maximum_fenwick_tree.py index e90bd634d..84967a70c 100644 --- a/data_structures/binary_tree/maximum_fenwick_tree.py +++ b/data_structures/binary_tree/maximum_fenwick_tree.py @@ -16,7 +16,7 @@ class MaxFenwickTree: 20 >>> ft.update(4, 10) >>> ft.query(2, 5) - 10 + 20 >>> ft.query(1, 5) 20 >>> ft.update(2, 0) @@ -26,6 +26,14 @@ class MaxFenwickTree: >>> ft.update(255, 30) >>> ft.query(0, 10000) 30 + >>> ft = MaxFenwickTree(6) + >>> ft.update(5, 1) + >>> ft.query(5, 6) + 1 + >>> ft = MaxFenwickTree(6) + >>> ft.update(0, 1000) + >>> ft.query(0, 1) + 1000 """ def __init__(self, size: int) -> None: @@ -47,14 +55,14 @@ class MaxFenwickTree: """ Get next index in O(1) """ - return index + (index & -index) + return index | (index + 1) @staticmethod def get_prev(index: int) -> int: """ Get previous index in O(1) """ - return index - (index & -index) + return (index & (index + 1)) - 1 def update(self, index: int, value: int) -> None: """ @@ -69,7 +77,11 @@ class MaxFenwickTree: """ self.arr[index] = value while index < self.size: - self.tree[index] = max(value, self.query(self.get_prev(index), index)) + current_left_border = self.get_prev(index) + 1 + if current_left_border == index: + self.tree[index] = value + else: + self.tree[index] = max(value, current_left_border, index) index = self.get_next(index) def query(self, left: int, right: int) -> int: @@ -85,9 +97,9 @@ class MaxFenwickTree: """ right -= 1 # Because of right is exclusive result = 0 - while left < right: + while left <= right: current_left = self.get_prev(right) - if left < current_left: + if left <= current_left: result = max(result, self.tree[right]) right = current_left else: From 2104fa7aebe8d76b2b2b2c47fe7e2ee615a05df6 Mon Sep 17 00:00:00 2001 From: Nikos Giachoudis Date: Wed, 14 Sep 2022 11:40:04 +0300 Subject: [PATCH 310/726] Unify `O(sqrt(N))` `is_prime` functions under `project_euler` (#6258) * fixes #5434 * fixes broken solution * removes assert * removes assert * Apply suggestions from code review Co-authored-by: John Law * Update project_euler/problem_003/sol1.py Co-authored-by: John Law --- project_euler/problem_003/sol1.py | 30 +++++++++--------- project_euler/problem_007/sol1.py | 32 +++++++++++-------- project_euler/problem_007/sol2.py | 31 ++++++++++++++----- project_euler/problem_007/sol3.py | 31 ++++++++++++++----- project_euler/problem_010/sol1.py | 27 +++++++++++----- project_euler/problem_010/sol2.py | 23 +++++++++++--- project_euler/problem_027/sol1.py | 43 ++++++++++++++++++-------- project_euler/problem_037/sol1.py | 51 ++++++++++++++++++++++--------- project_euler/problem_041/sol1.py | 40 ++++++++++++++++++------ project_euler/problem_046/sol1.py | 49 ++++++++++++++++++++--------- project_euler/problem_049/sol1.py | 40 ++++++++++++++++-------- project_euler/problem_058/sol1.py | 51 ++++++++++++++++++++----------- 12 files changed, 313 insertions(+), 135 deletions(-) diff --git a/project_euler/problem_003/sol1.py b/project_euler/problem_003/sol1.py index 606a6945e..a7d01bb04 100644 --- a/project_euler/problem_003/sol1.py +++ b/project_euler/problem_003/sol1.py @@ -13,9 +13,11 @@ References: import math -def is_prime(num: int) -> bool: - """ - Returns boolean representing primality of given number num. +def is_prime(number: int) -> bool: + """Checks to see if a number is a prime in O(sqrt(n)). + A number is prime if it has exactly two factors: 1 and itself. + Returns boolean representing primality of given number (i.e., if the + result is true, then the number is indeed prime else it is not). >>> is_prime(2) True @@ -26,23 +28,21 @@ def is_prime(num: int) -> bool: >>> is_prime(2999) True >>> is_prime(0) - Traceback (most recent call last): - ... - ValueError: Parameter num must be greater than or equal to two. + False >>> is_prime(1) - Traceback (most recent call last): - ... - ValueError: Parameter num must be greater than or equal to two. + False """ - if num <= 1: - raise ValueError("Parameter num must be greater than or equal to two.") - if num == 2: + if 1 < number < 4: + # 2 and 3 are primes return True - elif num % 2 == 0: + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes return False - for i in range(3, int(math.sqrt(num)) + 1, 2): - if num % i == 0: + + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: return False return True diff --git a/project_euler/problem_007/sol1.py b/project_euler/problem_007/sol1.py index 78fbcb511..f52ff931f 100644 --- a/project_euler/problem_007/sol1.py +++ b/project_euler/problem_007/sol1.py @@ -15,29 +15,37 @@ References: from math import sqrt -def is_prime(num: int) -> bool: - """ - Determines whether the given number is prime or not +def is_prime(number: int) -> bool: + """Checks to see if a number is a prime in O(sqrt(n)). + A number is prime if it has exactly two factors: 1 and itself. + Returns boolean representing primality of given number (i.e., if the + result is true, then the number is indeed prime else it is not). >>> is_prime(2) True - >>> is_prime(15) + >>> is_prime(3) + True + >>> is_prime(27) False - >>> is_prime(29) + >>> is_prime(2999) True >>> is_prime(0) False + >>> is_prime(1) + False """ - if num == 2: + if 1 < number < 4: + # 2 and 3 are primes return True - elif num % 2 == 0: + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes return False - else: - sq = int(sqrt(num)) + 1 - for i in range(3, sq, 2): - if num % i == 0: - return False + + # All primes number are in format of 6k +/- 1 + for i in range(5, int(sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: + return False return True diff --git a/project_euler/problem_007/sol2.py b/project_euler/problem_007/sol2.py index 44d72e949..75d351889 100644 --- a/project_euler/problem_007/sol2.py +++ b/project_euler/problem_007/sol2.py @@ -11,22 +11,39 @@ What is the 10001st prime number? References: - https://en.wikipedia.org/wiki/Prime_number """ +import math def is_prime(number: int) -> bool: - """ - Determines whether the given number is prime or not + """Checks to see if a number is a prime in O(sqrt(n)). + A number is prime if it has exactly two factors: 1 and itself. + Returns boolean representing primality of given number (i.e., if the + result is true, then the number is indeed prime else it is not). >>> is_prime(2) True - >>> is_prime(15) - False - >>> is_prime(29) + >>> is_prime(3) True + >>> is_prime(27) + False + >>> is_prime(2999) + True + >>> is_prime(0) + False + >>> is_prime(1) + False """ - for i in range(2, int(number**0.5) + 1): - if number % i == 0: + if 1 < number < 4: + # 2 and 3 are primes + return True + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes + return False + + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: return False return True diff --git a/project_euler/problem_007/sol3.py b/project_euler/problem_007/sol3.py index daa719cef..774260db9 100644 --- a/project_euler/problem_007/sol3.py +++ b/project_euler/problem_007/sol3.py @@ -16,20 +16,37 @@ import math def is_prime(number: int) -> bool: - """ - Determines whether a given number is prime or not + """Checks to see if a number is a prime in O(sqrt(n)). + A number is prime if it has exactly two factors: 1 and itself. + Returns boolean representing primality of given number (i.e., if the + result is true, then the number is indeed prime else it is not). >>> is_prime(2) True - >>> is_prime(15) - False - >>> is_prime(29) + >>> is_prime(3) True + >>> is_prime(27) + False + >>> is_prime(2999) + True + >>> is_prime(0) + False + >>> is_prime(1) + False """ - if number % 2 == 0 and number > 2: + if 1 < number < 4: + # 2 and 3 are primes + return True + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes return False - return all(number % i for i in range(3, int(math.sqrt(number)) + 1, 2)) + + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: + return False + return True def prime_generator(): diff --git a/project_euler/problem_010/sol1.py b/project_euler/problem_010/sol1.py index e060761ee..31f2feda3 100644 --- a/project_euler/problem_010/sol1.py +++ b/project_euler/problem_010/sol1.py @@ -11,12 +11,14 @@ References: - https://en.wikipedia.org/wiki/Prime_number """ -from math import sqrt +import math -def is_prime(n: int) -> bool: - """ - Returns boolean representing primality of given number num. +def is_prime(number: int) -> bool: + """Checks to see if a number is a prime in O(sqrt(n)). + A number is prime if it has exactly two factors: 1 and itself. + Returns boolean representing primality of given number num (i.e., if the + result is true, then the number is indeed prime else it is not). >>> is_prime(2) True @@ -26,13 +28,24 @@ def is_prime(n: int) -> bool: False >>> is_prime(2999) True + >>> is_prime(0) + False + >>> is_prime(1) + False """ - if 1 < n < 4: + if 1 < number < 4: + # 2 and 3 are primes return True - elif n < 2 or not n % 2: + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes return False - return not any(not n % i for i in range(3, int(sqrt(n) + 1), 2)) + + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: + return False + return True def solution(n: int = 2000000) -> int: diff --git a/project_euler/problem_010/sol2.py b/project_euler/problem_010/sol2.py index a288bb85f..245cca1d1 100644 --- a/project_euler/problem_010/sol2.py +++ b/project_euler/problem_010/sol2.py @@ -16,8 +16,10 @@ from itertools import takewhile def is_prime(number: int) -> bool: - """ - Returns boolean representing primality of given number num. + """Checks to see if a number is a prime in O(sqrt(n)). + A number is prime if it has exactly two factors: 1 and itself. + Returns boolean representing primality of given number num (i.e., if the + result is true, then the number is indeed prime else it is not). >>> is_prime(2) True @@ -27,11 +29,24 @@ def is_prime(number: int) -> bool: False >>> is_prime(2999) True + >>> is_prime(0) + False + >>> is_prime(1) + False """ - if number % 2 == 0 and number > 2: + if 1 < number < 4: + # 2 and 3 are primes + return True + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes return False - return all(number % i for i in range(3, int(math.sqrt(number)) + 1, 2)) + + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: + return False + return True def prime_generator() -> Iterator[int]: diff --git a/project_euler/problem_027/sol1.py b/project_euler/problem_027/sol1.py index 928c0ec4f..c93e2b4fa 100644 --- a/project_euler/problem_027/sol1.py +++ b/project_euler/problem_027/sol1.py @@ -23,22 +23,39 @@ n = 0. import math -def is_prime(k: int) -> bool: - """ - Determine if a number is prime - >>> is_prime(10) - False - >>> is_prime(11) +def is_prime(number: int) -> bool: + """Checks to see if a number is a prime in O(sqrt(n)). + A number is prime if it has exactly two factors: 1 and itself. + Returns boolean representing primality of given number num (i.e., if the + result is true, then the number is indeed prime else it is not). + + >>> is_prime(2) True + >>> is_prime(3) + True + >>> is_prime(27) + False + >>> is_prime(2999) + True + >>> is_prime(0) + False + >>> is_prime(1) + False + >>> is_prime(-10) + False """ - if k < 2 or k % 2 == 0: - return False - elif k == 2: + + if 1 < number < 4: + # 2 and 3 are primes return True - else: - for x in range(3, int(math.sqrt(k) + 1), 2): - if k % x == 0: - return False + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes + return False + + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: + return False return True diff --git a/project_euler/problem_037/sol1.py b/project_euler/problem_037/sol1.py index 0411ad41b..ef7686cbc 100644 --- a/project_euler/problem_037/sol1.py +++ b/project_euler/problem_037/sol1.py @@ -1,4 +1,7 @@ """ +Truncatable primes +Problem 37: https://projecteuler.net/problem=37 + The number 3797 has an interesting property. Being prime itself, it is possible to continuously remove digits from left to right, and remain prime at each stage: 3797, 797, 97, and 7. Similarly we can work from right to left: 3797, 379, 37, and 3. @@ -11,28 +14,46 @@ NOTE: 2, 3, 5, and 7 are not considered to be truncatable primes. from __future__ import annotations -seive = [True] * 1000001 -seive[1] = False -i = 2 -while i * i <= 1000000: - if seive[i]: - for j in range(i * i, 1000001, i): - seive[j] = False - i += 1 +import math -def is_prime(n: int) -> bool: - """ - Returns True if n is prime, - False otherwise, for 1 <= n <= 1000000 - >>> is_prime(87) +def is_prime(number: int) -> bool: + """Checks to see if a number is a prime in O(sqrt(n)). + + A number is prime if it has exactly two factors: 1 and itself. + + >>> is_prime(0) False >>> is_prime(1) False - >>> is_prime(25363) + >>> is_prime(2) + True + >>> is_prime(3) + True + >>> is_prime(27) + False + >>> is_prime(87) + False + >>> is_prime(563) + True + >>> is_prime(2999) + True + >>> is_prime(67483) False """ - return seive[n] + + if 1 < number < 4: + # 2 and 3 are primes + return True + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes + return False + + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: + return False + return True def list_truncated_nums(n: int) -> list[int]: diff --git a/project_euler/problem_041/sol1.py b/project_euler/problem_041/sol1.py index 80ef2125b..2ef012068 100644 --- a/project_euler/problem_041/sol1.py +++ b/project_euler/problem_041/sol1.py @@ -12,25 +12,45 @@ pandigital prime. """ from __future__ import annotations +import math from itertools import permutations -from math import sqrt -def is_prime(n: int) -> bool: - """ - Returns True if n is prime, - False otherwise. - >>> is_prime(67483) +def is_prime(number: int) -> bool: + """Checks to see if a number is a prime in O(sqrt(n)). + + A number is prime if it has exactly two factors: 1 and itself. + + >>> is_prime(0) + False + >>> is_prime(1) + False + >>> is_prime(2) + True + >>> is_prime(3) + True + >>> is_prime(27) + False + >>> is_prime(87) False >>> is_prime(563) True - >>> is_prime(87) + >>> is_prime(2999) + True + >>> is_prime(67483) False """ - if n % 2 == 0: + + if 1 < number < 4: + # 2 and 3 are primes + return True + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes return False - for i in range(3, int(sqrt(n) + 1), 2): - if n % i == 0: + + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: return False return True diff --git a/project_euler/problem_046/sol1.py b/project_euler/problem_046/sol1.py index 550c4c7c4..07dd9bbf8 100644 --- a/project_euler/problem_046/sol1.py +++ b/project_euler/problem_046/sol1.py @@ -19,30 +19,49 @@ prime and twice a square? from __future__ import annotations -seive = [True] * 100001 -i = 2 -while i * i <= 100000: - if seive[i]: - for j in range(i * i, 100001, i): - seive[j] = False - i += 1 +import math -def is_prime(n: int) -> bool: - """ - Returns True if n is prime, - False otherwise, for 2 <= n <= 100000 +def is_prime(number: int) -> bool: + """Checks to see if a number is a prime in O(sqrt(n)). + + A number is prime if it has exactly two factors: 1 and itself. + + >>> is_prime(0) + False + >>> is_prime(1) + False + >>> is_prime(2) + True + >>> is_prime(3) + True + >>> is_prime(27) + False >>> is_prime(87) False - >>> is_prime(23) + >>> is_prime(563) True - >>> is_prime(25363) + >>> is_prime(2999) + True + >>> is_prime(67483) False """ - return seive[n] + + if 1 < number < 4: + # 2 and 3 are primes + return True + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes + return False + + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: + return False + return True -odd_composites = [num for num in range(3, len(seive), 2) if not is_prime(num)] +odd_composites = [num for num in range(3, 100001, 2) if not is_prime(num)] def compute_nums(n: int) -> list[int]: diff --git a/project_euler/problem_049/sol1.py b/project_euler/problem_049/sol1.py index dd2ef71a3..5c7560cbd 100644 --- a/project_euler/problem_049/sol1.py +++ b/project_euler/problem_049/sol1.py @@ -25,32 +25,46 @@ After that, bruteforce all passed candidates sequences using The bruteforce of this solution will be about 1 sec. """ +import math from itertools import permutations -from math import floor, sqrt def is_prime(number: int) -> bool: - """ - function to check whether the number is prime or not. - >>> is_prime(2) - True - >>> is_prime(6) + """Checks to see if a number is a prime in O(sqrt(n)). + + A number is prime if it has exactly two factors: 1 and itself. + + >>> is_prime(0) False >>> is_prime(1) False - >>> is_prime(-800) - False - >>> is_prime(104729) + >>> is_prime(2) True + >>> is_prime(3) + True + >>> is_prime(27) + False + >>> is_prime(87) + False + >>> is_prime(563) + True + >>> is_prime(2999) + True + >>> is_prime(67483) + False """ - if number < 2: + if 1 < number < 4: + # 2 and 3 are primes + return True + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes return False - for i in range(2, floor(sqrt(number)) + 1): - if number % i == 0: + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: return False - return True diff --git a/project_euler/problem_058/sol1.py b/project_euler/problem_058/sol1.py index c59b0dd71..6a991c58b 100644 --- a/project_euler/problem_058/sol1.py +++ b/project_euler/problem_058/sol1.py @@ -33,29 +33,46 @@ So we check individually each one of these before incrementing our count of current primes. """ -from math import isqrt +import math -def is_prime(number: int) -> int: - """ - Returns whether the given number is prime or not +def is_prime(number: int) -> bool: + """Checks to see if a number is a prime in O(sqrt(n)). + + A number is prime if it has exactly two factors: 1 and itself. + + >>> is_prime(0) + False >>> is_prime(1) - 0 - >>> is_prime(17) - 1 - >>> is_prime(10000) - 0 + False + >>> is_prime(2) + True + >>> is_prime(3) + True + >>> is_prime(27) + False + >>> is_prime(87) + False + >>> is_prime(563) + True + >>> is_prime(2999) + True + >>> is_prime(67483) + False """ - if number == 1: - return 0 - if number % 2 == 0 and number > 2: - return 0 + if 1 < number < 4: + # 2 and 3 are primes + return True + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes + return False - for i in range(3, isqrt(number) + 1, 2): - if number % i == 0: - return 0 - return 1 + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: + return False + return True def solution(ratio: float = 0.1) -> int: From 45d3eabeb5f22624245095abdc044422bfe5eeea Mon Sep 17 00:00:00 2001 From: Satish Mishra <36122092+ZicsX@users.noreply.github.com> Date: Wed, 14 Sep 2022 14:13:08 +0530 Subject: [PATCH 311/726] Add Optimized Shell Sort (#6225) * Add Optimized Shell Sort * Added return type * reformatted * added shrink_shell.py * ran directory generator * Rename shrink_shell.py to shrink_shell_sort.py Co-authored-by: John Law --- DIRECTORY.md | 2 +- sorts/shrink_shell_sort.py | 66 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 sorts/shrink_shell_sort.py diff --git a/DIRECTORY.md b/DIRECTORY.md index a7305395a..25eb0ef0e 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -446,7 +446,6 @@ * [Scoring Functions](machine_learning/scoring_functions.py) * [Sequential Minimum Optimization](machine_learning/sequential_minimum_optimization.py) * [Similarity Search](machine_learning/similarity_search.py) - * [Support Vector Machines](machine_learning/support_vector_machines.py) * [Word Frequency Functions](machine_learning/word_frequency_functions.py) ## Maths @@ -984,6 +983,7 @@ * [Recursive Quick Sort](sorts/recursive_quick_sort.py) * [Selection Sort](sorts/selection_sort.py) * [Shell Sort](sorts/shell_sort.py) + * [Shrink Shell](sorts/shrink_shell.py) * [Slowsort](sorts/slowsort.py) * [Stooge Sort](sorts/stooge_sort.py) * [Strand Sort](sorts/strand_sort.py) diff --git a/sorts/shrink_shell_sort.py b/sorts/shrink_shell_sort.py new file mode 100644 index 000000000..69992bfb7 --- /dev/null +++ b/sorts/shrink_shell_sort.py @@ -0,0 +1,66 @@ +""" +This function implements the shell sort algorithm +which is slightly faster than its pure implementation. + +This shell sort is implemented using a gap, which +shrinks by a certain factor each iteration. In this +implementation, the gap is initially set to the +length of the collection. The gap is then reduced by +a certain factor (1.3) each iteration. + +For each iteration, the algorithm compares elements +that are a certain number of positions apart +(determined by the gap). If the element at the higher +position is greater than the element at the lower +position, the two elements are swapped. The process +is repeated until the gap is equal to 1. + +The reason this is more efficient is that it reduces +the number of comparisons that need to be made. By +using a smaller gap, the list is sorted more quickly. +""" + + +def shell_sort(collection: list) -> list: + """Implementation of shell sort algorithm in Python + :param collection: Some mutable ordered collection with heterogeneous + comparable items inside + :return: the same collection ordered by ascending + + >>> shell_sort([3, 2, 1]) + [1, 2, 3] + >>> shell_sort([]) + [] + >>> shell_sort([1]) + [1] + """ + + # Choose an initial gap value + gap = len(collection) + + # Set the gap value to be decreased by a factor of 1.3 + # after each iteration + shrink = 1.3 + + # Continue sorting until the gap is 1 + while gap > 1: + + # Decrease the gap value + gap = int(gap / shrink) + + # Sort the elements using insertion sort + for i in range(gap, len(collection)): + temp = collection[i] + j = i + while j >= gap and collection[j - gap] > temp: + collection[j] = collection[j - gap] + j -= gap + collection[j] = temp + + return collection + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 5754bd09ffd9a13d9e9bc3083419a22ab8ff7df6 Mon Sep 17 00:00:00 2001 From: Beksultan <96925396+Vazno@users.noreply.github.com> Date: Wed, 21 Sep 2022 21:37:38 +0600 Subject: [PATCH 312/726] fix typo (#6375) --- strings/is_contains_unique_chars.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/strings/is_contains_unique_chars.py b/strings/is_contains_unique_chars.py index fdf7a02ff..d6b698e76 100644 --- a/strings/is_contains_unique_chars.py +++ b/strings/is_contains_unique_chars.py @@ -7,7 +7,7 @@ def is_contains_unique_chars(input_str: str) -> bool: False Time complexity: O(n) - Space compexity: O(1) 19320 bytes as we are having 144697 characters in unicode + Space complexity: O(1) 19320 bytes as we are having 144697 characters in unicode """ # Each bit will represent each unicode character From 91c671ebabb3449fbbaefc2c4d959566eaed48dc Mon Sep 17 00:00:00 2001 From: Yannick Brenning <90418998+ybrenning@users.noreply.github.com> Date: Sat, 24 Sep 2022 18:46:03 +0200 Subject: [PATCH 313/726] Fix minor typo and add matrix dimension check (#6367) * Fix minor typo in comment * Add matrix dimension check * Add descriptive comment --- matrix/inverse_of_matrix.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/matrix/inverse_of_matrix.py b/matrix/inverse_of_matrix.py index 9deca6c3c..e414ee254 100644 --- a/matrix/inverse_of_matrix.py +++ b/matrix/inverse_of_matrix.py @@ -27,14 +27,21 @@ def inverse_of_matrix(matrix: list[list[float]]) -> list[list[float]]: [[0.25, -0.5], [-0.3, 1.0]] """ - D = Decimal # An abbreviation to be conciseness + D = Decimal # An abbreviation for conciseness + + # Check if the provided matrix has 2 rows and 2 columns, since this implementation only works for 2x2 matrices + if len(matrix) != 2 or len(matrix[0]) != 2 or len(matrix[1]) != 2: + raise ValueError("Please provide a matrix of size 2x2.") + # Calculate the determinant of the matrix determinant = D(matrix[0][0]) * D(matrix[1][1]) - D(matrix[1][0]) * D(matrix[0][1]) if determinant == 0: raise ValueError("This matrix has no inverse.") + # Creates a copy of the matrix with swapped positions of the elements swapped_matrix = [[0.0, 0.0], [0.0, 0.0]] swapped_matrix[0][0], swapped_matrix[1][1] = matrix[1][1], matrix[0][0] swapped_matrix[1][0], swapped_matrix[0][1] = -matrix[1][0], -matrix[0][1] + # Calculate the inverse of the matrix return [[float(D(n) / determinant) or 0.0 for n in row] for row in swapped_matrix] From a0b0f414ae134aa1772d33bb930e5a960f9979e8 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sat, 24 Sep 2022 20:04:00 +0300 Subject: [PATCH 314/726] Add Project Euler problem 116 solution 1 (#6305) * Add solution * updating DIRECTORY.md * Fix pre-commit * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: John Law --- DIRECTORY.md | 6 ++- matrix/inverse_of_matrix.py | 3 +- project_euler/problem_116/__init__.py | 0 project_euler/problem_116/sol1.py | 64 +++++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 project_euler/problem_116/__init__.py create mode 100644 project_euler/problem_116/sol1.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 25eb0ef0e..1d9e6eff7 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -446,6 +446,7 @@ * [Scoring Functions](machine_learning/scoring_functions.py) * [Sequential Minimum Optimization](machine_learning/sequential_minimum_optimization.py) * [Similarity Search](machine_learning/similarity_search.py) + * [Support Vector Machines](machine_learning/support_vector_machines.py) * [Word Frequency Functions](machine_learning/word_frequency_functions.py) ## Maths @@ -859,6 +860,8 @@ * [Sol1](project_euler/problem_114/sol1.py) * Problem 115 * [Sol1](project_euler/problem_115/sol1.py) + * Problem 116 + * [Sol1](project_euler/problem_116/sol1.py) * Problem 119 * [Sol1](project_euler/problem_119/sol1.py) * Problem 120 @@ -983,7 +986,7 @@ * [Recursive Quick Sort](sorts/recursive_quick_sort.py) * [Selection Sort](sorts/selection_sort.py) * [Shell Sort](sorts/shell_sort.py) - * [Shrink Shell](sorts/shrink_shell.py) + * [Shrink Shell Sort](sorts/shrink_shell_sort.py) * [Slowsort](sorts/slowsort.py) * [Stooge Sort](sorts/stooge_sort.py) * [Strand Sort](sorts/strand_sort.py) @@ -1005,6 +1008,7 @@ * [Check Pangram](strings/check_pangram.py) * [Credit Card Validator](strings/credit_card_validator.py) * [Detecting English Programmatically](strings/detecting_english_programmatically.py) + * [Dna](strings/dna.py) * [Frequency Finder](strings/frequency_finder.py) * [Hamming Distance](strings/hamming_distance.py) * [Indian Phone Validator](strings/indian_phone_validator.py) diff --git a/matrix/inverse_of_matrix.py b/matrix/inverse_of_matrix.py index e414ee254..92780e656 100644 --- a/matrix/inverse_of_matrix.py +++ b/matrix/inverse_of_matrix.py @@ -29,7 +29,8 @@ def inverse_of_matrix(matrix: list[list[float]]) -> list[list[float]]: D = Decimal # An abbreviation for conciseness - # Check if the provided matrix has 2 rows and 2 columns, since this implementation only works for 2x2 matrices + # Check if the provided matrix has 2 rows and 2 columns + # since this implementation only works for 2x2 matrices if len(matrix) != 2 or len(matrix[0]) != 2 or len(matrix[1]) != 2: raise ValueError("Please provide a matrix of size 2x2.") diff --git a/project_euler/problem_116/__init__.py b/project_euler/problem_116/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_116/sol1.py b/project_euler/problem_116/sol1.py new file mode 100644 index 000000000..efa13ee3f --- /dev/null +++ b/project_euler/problem_116/sol1.py @@ -0,0 +1,64 @@ +""" +Project Euler Problem 116: https://projecteuler.net/problem=116 + +A row of five grey square tiles is to have a number of its tiles +replaced with coloured oblong tiles chosen +from red (length two), green (length three), or blue (length four). + +If red tiles are chosen there are exactly seven ways this can be done. + + |red,red|grey|grey|grey| |grey|red,red|grey|grey| + + |grey|grey|red,red|grey| |grey|grey|grey|red,red| + + |red,red|red,red|grey| |red,red|grey|red,red| + + |grey|red,red|red,red| + +If green tiles are chosen there are three ways. + + |green,green,green|grey|grey| |grey|green,green,green|grey| + + |grey|grey|green,green,green| + +And if blue tiles are chosen there are two ways. + + |blue,blue,blue,blue|grey| |grey|blue,blue,blue,blue| + +Assuming that colours cannot be mixed there are 7 + 3 + 2 = 12 ways +of replacing the grey tiles in a row measuring five units in length. + +How many different ways can the grey tiles in a row measuring fifty units in length +be replaced if colours cannot be mixed and at least one coloured tile must be used? + +NOTE: This is related to Problem 117 (https://projecteuler.net/problem=117). +""" + + +def solution(length: int = 50) -> int: + """ + Returns the number of different ways can the grey tiles in a row + of the given length be replaced if colours cannot be mixed + and at least one coloured tile must be used + + >>> solution(5) + 12 + """ + + different_colour_ways_number = [[0] * 3 for _ in range(length + 1)] + + for row_length in range(length + 1): + for tile_length in range(2, 5): + for tile_start in range(row_length - tile_length + 1): + different_colour_ways_number[row_length][tile_length - 2] += ( + different_colour_ways_number[row_length - tile_start - tile_length][ + tile_length - 2 + ] + + 1 + ) + + return sum(different_colour_ways_number[length]) + + +if __name__ == "__main__": + print(f"{solution() = }") From a12e6941a6c90d80d4aaee5c2c013e7da0288492 Mon Sep 17 00:00:00 2001 From: Debjit Bhowal <68442560+debjit-bw@users.noreply.github.com> Date: Sat, 1 Oct 2022 17:47:15 +0530 Subject: [PATCH 315/726] Fix docstring (#6461) * fixed wrong algo name to radix sort * added wiki url * Added "source" in docstring * Update radix_sort.py Co-authored-by: Christian Clauss --- sorts/radix_sort.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/sorts/radix_sort.py b/sorts/radix_sort.py index e433bc507..c3ff04f3d 100644 --- a/sorts/radix_sort.py +++ b/sorts/radix_sort.py @@ -1,11 +1,7 @@ """ -This is a pure Python implementation of the quick sort algorithm -For doctests run following command: -python -m doctest -v radix_sort.py -or -python3 -m doctest -v radix_sort.py -For manual testing run: -python radix_sort.py +This is a pure Python implementation of the radix sort algorithm + +Source: https://en.wikipedia.org/wiki/Radix_sort """ from __future__ import annotations From 346b0a8466732c9594eb62c4c60203d87106bf69 Mon Sep 17 00:00:00 2001 From: RAHUL S H Date: Sun, 2 Oct 2022 03:50:47 -0700 Subject: [PATCH 316/726] Added fetch_quotes.py (#6529) * Added fetch_quotes.py fetches quotes from zenquotes.io api * Update web_programming/fetch_quotes.py Co-authored-by: rohanr18 <114707091+rohanr18@users.noreply.github.com> Co-authored-by: rohanr18 <114707091+rohanr18@users.noreply.github.com> --- web_programming/fetch_quotes.py | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 web_programming/fetch_quotes.py diff --git a/web_programming/fetch_quotes.py b/web_programming/fetch_quotes.py new file mode 100644 index 000000000..4a3b002e5 --- /dev/null +++ b/web_programming/fetch_quotes.py @@ -0,0 +1,34 @@ +""" +This file fetches quotes from the " ZenQuotes API ". +It does not require any API key as it uses free tier. + +For more details and premium features visit: + https://zenquotes.io/ +""" + +import pprint + +import requests + + +def quote_of_the_day() -> list: + API_ENDPOINT_URL = "https://zenquotes.io/api/today/" + return requests.get(API_ENDPOINT_URL).json() + + +def random_quotes() -> list: + API_ENDPOINT_URL = "https://zenquotes.io/api/random/" + return requests.get(API_ENDPOINT_URL).json() + + +if __name__ == "__main__": + """ + response object has all the info with the quote + To retrieve the actual quote access the response.json() object as below + response.json() is a list of json object + response.json()[0]['q'] = actual quote. + response.json()[0]['a'] = author name. + response.json()[0]['h'] = in html format. + """ + response = random_quotes() + pprint.pprint(response) From cabd8c63825fcd1b35fdd621ba443f31d0fb880d Mon Sep 17 00:00:00 2001 From: Dhruv Manilawala Date: Sun, 2 Oct 2022 17:49:30 +0530 Subject: [PATCH 317/726] feat: basic issue forms (#6533) --- .github/ISSUE_TEMPLATE/bug_report.yaml | 54 +++++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yaml | 5 ++ .github/ISSUE_TEMPLATE/feature_request.yaml | 26 ++++++++++ 3 files changed, 85 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yaml create mode 100644 .github/ISSUE_TEMPLATE/config.yaml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yaml diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml new file mode 100644 index 000000000..6b3a5222f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -0,0 +1,54 @@ +name: Bug report +description: Create a bug report to help us address errors in the repository +labels: [bug] +body: + - type: markdown + attributes: + value: | + Before requesting please search [existing issues](https://github.com/TheAlgorithms/Python/labels/bug). + Usage questions such as "How do I...?" belong on the + [Discord](https://discord.gg/c7MnfGFGa6) and will be closed. + + - type: input + attributes: + label: "Repository commit" + description: | + The commit hash for `TheAlgorithms/Python` repository. You can get this + by running the command `git rev-parse HEAD` locally. + placeholder: "a0b0f414ae134aa1772d33bb930e5a960f9979e8" + validations: + required: true + + - type: input + attributes: + label: "Python version (python --version)" + placeholder: "Python 3.10.7" + validations: + required: true + + - type: input + attributes: + label: "Dependencies version (pip freeze)" + description: | + This is the output of the command `pip freeze --all`. Note that the + actual output might be different as compared to the placeholder text. + placeholder: | + appnope==0.1.3 + asttokens==2.0.8 + backcall==0.2.0 + ... + validations: + required: true + + - type: textarea + attributes: + label: "Expected behavior" + description: "Describe the behavior you expect. May include images or videos." + validations: + required: true + + - type: textarea + attributes: + label: "Actual behavior" + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yaml b/.github/ISSUE_TEMPLATE/config.yaml new file mode 100644 index 000000000..62019bb08 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yaml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Discord community + url: https://discord.gg/c7MnfGFGa6 + about: Have any questions or need any help? Please contact us via Discord diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml new file mode 100644 index 000000000..7d6e221e3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -0,0 +1,26 @@ +name: Feature request +description: Suggest features, propose improvements, discuss new ideas. +labels: [enhancement] +body: + - type: markdown + attributes: + value: | + Before requesting please search [existing issues](https://github.com/TheAlgorithms/Python/labels/enhancement). + Usage questions such as "How do I...?" belong on the + [Discord](https://discord.gg/c7MnfGFGa6) and will be closed. + + - type: textarea + attributes: + label: "Feature description" + description: | + This could be new algorithms, data structures or improving any existing + implementations. + validations: + required: true + + - type: checkboxes + attributes: + label: Would you like to work on this feature? + options: + - label: Yes, I want to work on this feature! + required: false From c9f1d09e1a82ec25ebd259e108b6b85046212a6e Mon Sep 17 00:00:00 2001 From: Dhruv Manilawala Date: Sun, 2 Oct 2022 18:51:53 +0530 Subject: [PATCH 318/726] fix: GitHub requires `.yml` extension (#6542) * fix: GitHub requires `.yml` extension Ref: https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#configuring-the-template-chooser * fix: remove newlines from multiline string * fix: use textarea for dependencies list input --- .../ISSUE_TEMPLATE/{bug_report.yaml => bug_report.yml} | 8 ++++---- .github/ISSUE_TEMPLATE/{config.yaml => config.yml} | 0 .../{feature_request.yaml => feature_request.yml} | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) rename .github/ISSUE_TEMPLATE/{bug_report.yaml => bug_report.yml} (95%) rename .github/ISSUE_TEMPLATE/{config.yaml => config.yml} (100%) rename .github/ISSUE_TEMPLATE/{feature_request.yaml => feature_request.yml} (95%) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yml similarity index 95% rename from .github/ISSUE_TEMPLATE/bug_report.yaml rename to .github/ISSUE_TEMPLATE/bug_report.yml index 6b3a5222f..4ccdb52ca 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -4,7 +4,7 @@ labels: [bug] body: - type: markdown attributes: - value: | + value: > Before requesting please search [existing issues](https://github.com/TheAlgorithms/Python/labels/bug). Usage questions such as "How do I...?" belong on the [Discord](https://discord.gg/c7MnfGFGa6) and will be closed. @@ -12,7 +12,7 @@ body: - type: input attributes: label: "Repository commit" - description: | + description: > The commit hash for `TheAlgorithms/Python` repository. You can get this by running the command `git rev-parse HEAD` locally. placeholder: "a0b0f414ae134aa1772d33bb930e5a960f9979e8" @@ -26,10 +26,10 @@ body: validations: required: true - - type: input + - type: textarea attributes: label: "Dependencies version (pip freeze)" - description: | + description: > This is the output of the command `pip freeze --all`. Note that the actual output might be different as compared to the placeholder text. placeholder: | diff --git a/.github/ISSUE_TEMPLATE/config.yaml b/.github/ISSUE_TEMPLATE/config.yml similarity index 100% rename from .github/ISSUE_TEMPLATE/config.yaml rename to .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yml similarity index 95% rename from .github/ISSUE_TEMPLATE/feature_request.yaml rename to .github/ISSUE_TEMPLATE/feature_request.yml index 7d6e221e3..bed3e8ab5 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yaml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -4,7 +4,7 @@ labels: [enhancement] body: - type: markdown attributes: - value: | + value: > Before requesting please search [existing issues](https://github.com/TheAlgorithms/Python/labels/enhancement). Usage questions such as "How do I...?" belong on the [Discord](https://discord.gg/c7MnfGFGa6) and will be closed. @@ -12,7 +12,7 @@ body: - type: textarea attributes: label: "Feature description" - description: | + description: > This could be new algorithms, data structures or improving any existing implementations. validations: From 072312bd0a4a2b48cc44e44a55c41ae408e8d9c1 Mon Sep 17 00:00:00 2001 From: Jay Gala <57001778+jaygala223@users.noreply.github.com> Date: Sun, 2 Oct 2022 20:19:49 +0530 Subject: [PATCH 319/726] Added code for Maximum Subarray Sum (#6536) * Added maximum subarray sum #6519 * fixes: #6519 function names changed as per naming conventions --- other/maximum_subarray.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 other/maximum_subarray.py diff --git a/other/maximum_subarray.py b/other/maximum_subarray.py new file mode 100644 index 000000000..756e00944 --- /dev/null +++ b/other/maximum_subarray.py @@ -0,0 +1,26 @@ +def max_subarray(nums: list[int]) -> int: + """ + Returns the subarray with maximum sum + >>> max_subarray([1,2,3,4,-2]) + 10 + >>> max_subarray([-2,1,-3,4,-1,2,1,-5,4]) + 6 + """ + + curr_max = ans = nums[0] + + for i in range(1, len(nums)): + if curr_max >= 0: + curr_max = curr_max + nums[i] + else: + curr_max = nums[i] + + ans = max(curr_max, ans) + + return ans + + +if __name__ == "__main__": + n = int(input("Enter number of elements : ").strip()) + array = list(map(int, input("\nEnter the numbers : ").strip().split()))[:n] + print(max_subarray(array)) From 50545d10c55859e3a3d792132ca6769f219bb130 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jerrit=20Gl=C3=A4sker?= Date: Sun, 2 Oct 2022 16:57:11 +0200 Subject: [PATCH 320/726] Run length encoding (#6492) * Removed unused commit * Added wikipedia url * Renamed parameter, changed decoding to use list comprehension --- compression/run_length_encoding.py | 48 ++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 compression/run_length_encoding.py diff --git a/compression/run_length_encoding.py b/compression/run_length_encoding.py new file mode 100644 index 000000000..691e19095 --- /dev/null +++ b/compression/run_length_encoding.py @@ -0,0 +1,48 @@ +# https://en.wikipedia.org/wiki/Run-length_encoding + + +def run_length_encode(text: str) -> list: + """ + Performs Run Length Encoding + >>> run_length_encode("AAAABBBCCDAA") + [('A', 4), ('B', 3), ('C', 2), ('D', 1), ('A', 2)] + >>> run_length_encode("A") + [('A', 1)] + >>> run_length_encode("AA") + [('A', 2)] + >>> run_length_encode("AAADDDDDDFFFCCCAAVVVV") + [('A', 3), ('D', 6), ('F', 3), ('C', 3), ('A', 2), ('V', 4)] + """ + encoded = [] + count = 1 + + for i in range(len(text)): + if i + 1 < len(text) and text[i] == text[i + 1]: + count += 1 + else: + encoded.append((text[i], count)) + count = 1 + + return encoded + + +def run_length_decode(encoded: list) -> str: + """ + Performs Run Length Decoding + >>> run_length_decode([('A', 4), ('B', 3), ('C', 2), ('D', 1), ('A', 2)]) + 'AAAABBBCCDAA' + >>> run_length_decode([('A', 1)]) + 'A' + >>> run_length_decode([('A', 2)]) + 'AA' + >>> run_length_decode([('A', 3), ('D', 6), ('F', 3), ('C', 3), ('A', 2), ('V', 4)]) + 'AAADDDDDDFFFCCCAAVVVV' + """ + return "".join(char * length for char, length in encoded) + + +if __name__ == "__main__": + from doctest import testmod + + testmod(name="run_length_encode", verbose=True) + testmod(name="run_length_decode", verbose=True) From 8b8fba34594764cbd8d834337f03d6e03b108964 Mon Sep 17 00:00:00 2001 From: Daniel Pustotin Date: Sun, 2 Oct 2022 19:35:02 +0300 Subject: [PATCH 321/726] Improve code complexity for segmented sieve (#6372) --- maths/segmented_sieve.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/maths/segmented_sieve.py b/maths/segmented_sieve.py index b15ec2480..0054b0595 100644 --- a/maths/segmented_sieve.py +++ b/maths/segmented_sieve.py @@ -15,15 +15,12 @@ def sieve(n): if temp[start] is True: in_prime.append(start) for i in range(start * start, end + 1, start): - if temp[i] is True: - temp[i] = False + temp[i] = False start += 1 prime += in_prime low = end + 1 - high = low + end - 1 - if high > n: - high = n + high = min(2 * end, n) while low <= n: temp = [True] * (high - low + 1) @@ -41,9 +38,7 @@ def sieve(n): prime.append(j + low) low = high + 1 - high = low + end - 1 - if high > n: - high = n + high = min(high + end, n) return prime From f42b2b8dff3fc9463d73072a2968594f4eda383b Mon Sep 17 00:00:00 2001 From: Saksham1970 <45041294+Saksham1970@users.noreply.github.com> Date: Sun, 2 Oct 2022 23:21:04 +0530 Subject: [PATCH 322/726] Newton raphson complex (#6545) * Newton raphson better implementation * flake8 test passed * Update arithmetic_analysis/newton_raphson_new.py Co-authored-by: Christian Clauss * added multiline suggestions Co-authored-by: Christian Clauss --- arithmetic_analysis/newton_raphson_new.py | 84 +++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 arithmetic_analysis/newton_raphson_new.py diff --git a/arithmetic_analysis/newton_raphson_new.py b/arithmetic_analysis/newton_raphson_new.py new file mode 100644 index 000000000..19ea4ce21 --- /dev/null +++ b/arithmetic_analysis/newton_raphson_new.py @@ -0,0 +1,84 @@ +# Implementing Newton Raphson method in Python +# Author: Saksham Gupta +# +# The Newton-Raphson method (also known as Newton's method) is a way to +# quickly find a good approximation for the root of a functreal-valued ion +# The method can also be extended to complex functions +# +# Newton's Method - https://en.wikipedia.org/wiki/Newton's_method + +from sympy import diff, lambdify, symbols +from sympy.functions import * # noqa: F401, F403 + + +def newton_raphson( + function: str, + starting_point: complex, + variable: str = "x", + precision: float = 10**-10, + multiplicity: int = 1, +) -> complex: + """Finds root from the 'starting_point' onwards by Newton-Raphson method + Refer to https://docs.sympy.org/latest/modules/functions/index.html + for usable mathematical functions + + >>> newton_raphson("sin(x)", 2) + 3.141592653589793 + >>> newton_raphson("x**4 -5", 0.4 + 5j) + (-7.52316384526264e-37+1.4953487812212207j) + >>> newton_raphson('log(y) - 1', 2, variable='y') + 2.7182818284590455 + >>> newton_raphson('exp(x) - 1', 10, precision=0.005) + 1.2186556186174883e-10 + >>> newton_raphson('cos(x)', 0) + Traceback (most recent call last): + ... + ZeroDivisionError: Could not find root + """ + + x = symbols(variable) + func = lambdify(x, function) + diff_function = lambdify(x, diff(function, x)) + + prev_guess = starting_point + + while True: + if diff_function(prev_guess) != 0: + next_guess = prev_guess - multiplicity * func(prev_guess) / diff_function( + prev_guess + ) + else: + raise ZeroDivisionError("Could not find root") from None + + # Precision is checked by comparing the difference of consecutive guesses + if abs(next_guess - prev_guess) < precision: + return next_guess + + prev_guess = next_guess + + +# Let's Execute +if __name__ == "__main__": + + # Find root of trigonometric function + # Find value of pi + print(f"The root of sin(x) = 0 is {newton_raphson('sin(x)', 2)}") + + # Find root of polynomial + # Find fourth Root of 5 + print(f"The root of x**4 - 5 = 0 is {newton_raphson('x**4 -5', 0.4 +5j)}") + + # Find value of e + print( + "The root of log(y) - 1 = 0 is ", + f"{newton_raphson('log(y) - 1', 2, variable='y')}", + ) + + # Exponential Roots + print( + "The root of exp(x) - 1 = 0 is", + f"{newton_raphson('exp(x) - 1', 10, precision=0.005)}", + ) + + # Find root of cos(x) + print(f"The root of cos(x) = 0 is {newton_raphson('cos(x)', 0)}") From 3d33b36e92c2edd1afd542b59d157ad4bccd4bf6 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sun, 2 Oct 2022 21:59:17 +0200 Subject: [PATCH 323/726] Fix pre-commit.ci: additional_dependencies: [types-requests] (#6559) * Fix pre-commit.ci: additional_dependencies: [types-requests==2.28.11] * updating DIRECTORY.md * Update .pre-commit-config.yaml * additional_dependencies: [types-requests] Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .pre-commit-config.yaml | 1 + DIRECTORY.md | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7ff745997..325063c3b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -49,6 +49,7 @@ repos: - --ignore-missing-imports - --install-types # See mirrors-mypy README.md - --non-interactive + additional_dependencies: [types-requests] - repo: https://github.com/codespell-project/codespell rev: v2.1.0 diff --git a/DIRECTORY.md b/DIRECTORY.md index 1d9e6eff7..64e9d5333 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -9,6 +9,7 @@ * [Newton Forward Interpolation](arithmetic_analysis/newton_forward_interpolation.py) * [Newton Method](arithmetic_analysis/newton_method.py) * [Newton Raphson](arithmetic_analysis/newton_raphson.py) + * [Newton Raphson New](arithmetic_analysis/newton_raphson_new.py) * [Secant Method](arithmetic_analysis/secant_method.py) ## Audio Filters @@ -107,6 +108,7 @@ * [Lempel Ziv](compression/lempel_ziv.py) * [Lempel Ziv Decompress](compression/lempel_ziv_decompress.py) * [Peak Signal To Noise Ratio](compression/peak_signal_to_noise_ratio.py) + * [Run Length Encoding](compression/run_length_encoding.py) ## Computer Vision * [Cnn Classification](computer_vision/cnn_classification.py) @@ -621,6 +623,7 @@ * [Linear Congruential Generator](other/linear_congruential_generator.py) * [Lru Cache](other/lru_cache.py) * [Magicdiamondpattern](other/magicdiamondpattern.py) + * [Maximum Subarray](other/maximum_subarray.py) * [Nested Brackets](other/nested_brackets.py) * [Password Generator](other/password_generator.py) * [Scoring Algorithm](other/scoring_algorithm.py) @@ -1053,6 +1056,7 @@ * [Fetch Bbc News](web_programming/fetch_bbc_news.py) * [Fetch Github Info](web_programming/fetch_github_info.py) * [Fetch Jobs](web_programming/fetch_jobs.py) + * [Fetch Quotes](web_programming/fetch_quotes.py) * [Fetch Well Rx Price](web_programming/fetch_well_rx_price.py) * [Get Imdb Top 250 Movies Csv](web_programming/get_imdb_top_250_movies_csv.py) * [Get Imdbtop](web_programming/get_imdbtop.py) From 707809b0006a76210bc3d0e4312ff5c73ff68300 Mon Sep 17 00:00:00 2001 From: AHTESHAM ZAIDI Date: Mon, 3 Oct 2022 03:25:24 +0530 Subject: [PATCH 324/726] Update astar.py (#6456) * Update astar.py Improved comments added punctuations. * Update astar.py * Update machine_learning/astar.py Co-authored-by: Caeden * Update astar.py Co-authored-by: Christian Clauss Co-authored-by: Caeden --- machine_learning/astar.py | 55 ++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/machine_learning/astar.py b/machine_learning/astar.py index ee3fcff0b..7a60ed225 100644 --- a/machine_learning/astar.py +++ b/machine_learning/astar.py @@ -1,41 +1,38 @@ """ -The A* algorithm combines features of uniform-cost search and pure -heuristic search to efficiently compute optimal solutions. -A* algorithm is a best-first search algorithm in which the cost -associated with a node is f(n) = g(n) + h(n), -where g(n) is the cost of the path from the initial state to node n and -h(n) is the heuristic estimate or the cost or a path -from node n to a goal.A* algorithm introduces a heuristic into a -regular graph-searching algorithm, -essentially planning ahead at each step so a more optimal decision -is made.A* also known as the algorithm with brains +The A* algorithm combines features of uniform-cost search and pure heuristic search to +efficiently compute optimal solutions. + +The A* algorithm is a best-first search algorithm in which the cost associated with a +node is f(n) = g(n) + h(n), where g(n) is the cost of the path from the initial state to +node n and h(n) is the heuristic estimate or the cost or a path from node n to a goal. + +The A* algorithm introduces a heuristic into a regular graph-searching algorithm, +essentially planning ahead at each step so a more optimal decision is made. For this +reason, A* is known as an algorithm with brains. + +https://en.wikipedia.org/wiki/A*_search_algorithm """ import numpy as np class Cell: """ - Class cell represents a cell in the world which have the property - position : The position of the represented by tupleof x and y - coordinates initially set to (0,0) - parent : This contains the parent cell object which we visited - before arrinving this cell - g,h,f : The parameters for constructing the heuristic function - which can be any function. for simplicity used line - distance + Class cell represents a cell in the world which have the properties: + position: represented by tuple of x and y coordinates initially set to (0,0). + parent: Contains the parent cell object visited before we arrived at this cell. + g, h, f: Parameters used when calling our heuristic function. """ def __init__(self): self.position = (0, 0) self.parent = None - self.g = 0 self.h = 0 self.f = 0 """ - overrides equals method because otherwise cell assign will give - wrong results + Overrides equals method because otherwise cell assign will give + wrong results. """ def __eq__(self, cell): @@ -48,8 +45,8 @@ class Cell: class Gridworld: """ Gridworld class represents the external world here a grid M*M - matrix - world_size: create a numpy array with the given world_size default is 5 + matrix. + world_size: create a numpy array with the given world_size default is 5. """ def __init__(self, world_size=(5, 5)): @@ -90,10 +87,10 @@ class Gridworld: def astar(world, start, goal): """ - Implementation of a start algorithm - world : Object of the world object - start : Object of the cell as start position - stop : Object of the cell as goal position + Implementation of a start algorithm. + world : Object of the world object. + start : Object of the cell as start position. + stop : Object of the cell as goal position. >>> p = Gridworld() >>> start = Cell() @@ -137,14 +134,14 @@ def astar(world, start, goal): if __name__ == "__main__": world = Gridworld() - # stat position and Goal + # Start position and goal start = Cell() start.position = (0, 0) goal = Cell() goal.position = (4, 4) print(f"path from {start.position} to {goal.position}") s = astar(world, start, goal) - # Just for visual reasons + # Just for visual reasons. for i in s: world.w[i] = 1 print(world.w) From e9862adafce9eb682cabcf8ac502893e0272ae65 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 3 Oct 2022 03:27:14 +0200 Subject: [PATCH 325/726] chore: remove pre-commit GHA (#6565) [`pre-commit.ci` is working](https://results.pre-commit.ci/repo/github/63476337) so let's remove our redundant and less powerful GitHub Action. --- .github/workflows/pre-commit.yml | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 .github/workflows/pre-commit.yml diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml deleted file mode 100644 index eb5e3d4ce..000000000 --- a/.github/workflows/pre-commit.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: pre-commit - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - pre-commit: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/cache@v3 - with: - path: | - ~/.cache/pre-commit - ~/.cache/pip - key: ${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} - - uses: actions/setup-python@v4 - with: - python-version: 3.x - # - uses: psf/black@22.6.0 - - name: Install pre-commit - run: | - python -m pip install --upgrade pip - python -m pip install --upgrade pre-commit - - run: pre-commit run --verbose --all-files --show-diff-on-failure From 756bb268eb22199534fc8d6478cf0e006f02b56b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 3 Oct 2022 22:00:45 +0200 Subject: [PATCH 326/726] [pre-commit.ci] pre-commit autoupdate (#6629) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/psf/black: 22.6.0 → 22.8.0](https://github.com/psf/black/compare/22.6.0...22.8.0) - [github.com/asottile/pyupgrade: v2.37.0 → v2.38.2](https://github.com/asottile/pyupgrade/compare/v2.37.0...v2.38.2) - https://gitlab.com/pycqa/flake8 → https://github.com/PyCQA/flake8 - [github.com/PyCQA/flake8: 3.9.2 → 5.0.4](https://github.com/PyCQA/flake8/compare/3.9.2...5.0.4) - [github.com/pre-commit/mirrors-mypy: v0.961 → v0.981](https://github.com/pre-commit/mirrors-mypy/compare/v0.961...v0.981) - [github.com/codespell-project/codespell: v2.1.0 → v2.2.1](https://github.com/codespell-project/codespell/compare/v2.1.0...v2.2.1) * Fix a long line * Update sol1.py * Update sol1.py * lambda_ * Update multi_level_feedback_queue.py * Update double_ended_queue.py * Update sequential_minimum_optimization.py * Update .pre-commit-config.yaml Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .pre-commit-config.yaml | 14 +++++++------- data_structures/queue/double_ended_queue.py | 2 +- linear_algebra/src/power_iteration.py | 12 ++++++------ .../sequential_minimum_optimization.py | 2 +- project_euler/problem_045/sol1.py | 2 +- project_euler/problem_113/sol1.py | 2 +- scheduling/multi_level_feedback_queue.py | 2 +- .../download_images_from_google_query.py | 3 ++- 8 files changed, 20 insertions(+), 19 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 325063c3b..a2fcf12c9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: requirements-txt-fixer - repo: https://github.com/psf/black - rev: 22.6.0 + rev: 22.8.0 hooks: - id: black @@ -26,14 +26,14 @@ repos: - --profile=black - repo: https://github.com/asottile/pyupgrade - rev: v2.37.0 + rev: v2.38.2 hooks: - id: pyupgrade args: - --py310-plus - - repo: https://gitlab.com/pycqa/flake8 - rev: 3.9.2 + - repo: https://github.com/PyCQA/flake8 + rev: 5.0.4 hooks: - id: flake8 args: @@ -42,7 +42,7 @@ repos: - --max-line-length=88 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.961 + rev: v0.981 hooks: - id: mypy args: @@ -52,11 +52,11 @@ repos: additional_dependencies: [types-requests] - repo: https://github.com/codespell-project/codespell - rev: v2.1.0 + rev: v2.2.1 hooks: - id: codespell args: - - --ignore-words-list=ans,crate,fo,followings,hist,iff,mater,secant,som,sur,tim + - --ignore-words-list=ans,crate,damon,fo,followings,hist,iff,mater,secant,som,sur,tim,zar - --skip="./.*,./strings/dictionary.txt,./strings/words.txt,./project_euler/problem_022/p022_names.txt" exclude: | (?x)^( diff --git a/data_structures/queue/double_ended_queue.py b/data_structures/queue/double_ended_queue.py index 1603e50bc..f38874788 100644 --- a/data_structures/queue/double_ended_queue.py +++ b/data_structures/queue/double_ended_queue.py @@ -377,7 +377,7 @@ class Deque: me = self._front oth = other._front - # if the length of the deques are not the same, they are not equal + # if the length of the dequeues are not the same, they are not equal if len(self) != len(other): return False diff --git a/linear_algebra/src/power_iteration.py b/linear_algebra/src/power_iteration.py index 4c6525b6e..4b866331b 100644 --- a/linear_algebra/src/power_iteration.py +++ b/linear_algebra/src/power_iteration.py @@ -52,7 +52,7 @@ def power_iteration( # or when we have small changes from one iteration to next. convergence = False - lamda_previous = 0 + lambda_previous = 0 iterations = 0 error = 1e12 @@ -64,21 +64,21 @@ def power_iteration( # Find rayleigh quotient # (faster than usual b/c we know vector is normalized already) vectorH = vector.conj().T if is_complex else vector.T - lamda = np.dot(vectorH, np.dot(input_matrix, vector)) + lambda_ = np.dot(vectorH, np.dot(input_matrix, vector)) # Check convergence. - error = np.abs(lamda - lamda_previous) / lamda + error = np.abs(lambda_ - lambda_previous) / lambda_ iterations += 1 if error <= error_tol or iterations >= max_iterations: convergence = True - lamda_previous = lamda + lambda_previous = lambda_ if is_complex: - lamda = np.real(lamda) + lambda_ = np.real(lambda_) - return lamda, vector + return lambda_, vector def test_power_iteration() -> None: diff --git a/machine_learning/sequential_minimum_optimization.py b/machine_learning/sequential_minimum_optimization.py index c217a370a..cc7868d0f 100644 --- a/machine_learning/sequential_minimum_optimization.py +++ b/machine_learning/sequential_minimum_optimization.py @@ -145,7 +145,7 @@ class SmoSVM: if self._is_unbound(i2): self._error[i2] = 0 - # Predict test samles + # Predict test samples def predict(self, test_samples, classify=True): if test_samples.shape[1] > self.samples.shape[1]: diff --git a/project_euler/problem_045/sol1.py b/project_euler/problem_045/sol1.py index cdf5c14cf..d921b2802 100644 --- a/project_euler/problem_045/sol1.py +++ b/project_euler/problem_045/sol1.py @@ -8,7 +8,7 @@ Hexagonal H(n) = n * (2 * n − 1) 1, 6, 15, 28, 45, ... It can be verified that T(285) = P(165) = H(143) = 40755. Find the next triangle number that is also pentagonal and hexagonal. -All trinagle numbers are hexagonal numbers. +All triangle numbers are hexagonal numbers. T(2n-1) = n * (2 * n - 1) = H(n) So we shall check only for hexagonal numbers which are also pentagonal. """ diff --git a/project_euler/problem_113/sol1.py b/project_euler/problem_113/sol1.py index 951d9b49c..2077c0fa6 100644 --- a/project_euler/problem_113/sol1.py +++ b/project_euler/problem_113/sol1.py @@ -62,7 +62,7 @@ def non_bouncy_upto(n: int) -> int: def solution(num_digits: int = 100) -> int: """ - Caclulate the number of non-bouncy numbers less than a googol. + Calculate the number of non-bouncy numbers less than a googol. >>> solution(6) 12951 >>> solution(10) diff --git a/scheduling/multi_level_feedback_queue.py b/scheduling/multi_level_feedback_queue.py index 95ca827e0..b54cc8719 100644 --- a/scheduling/multi_level_feedback_queue.py +++ b/scheduling/multi_level_feedback_queue.py @@ -307,6 +307,6 @@ if __name__ == "__main__": ) # print sequence of finished processes print( - f"sequnece of finished processes:\ + f"sequence of finished processes:\ {mlfq.calculate_sequence_of_finish_queue()}" ) diff --git a/web_programming/download_images_from_google_query.py b/web_programming/download_images_from_google_query.py index b11a7f883..9c0c21dc8 100644 --- a/web_programming/download_images_from_google_query.py +++ b/web_programming/download_images_from_google_query.py @@ -14,7 +14,8 @@ headers = { def download_images_from_google_query(query: str = "dhaka", max_images: int = 5) -> int: - """Searches google using the provided query term and downloads the images in a folder. + """ + Searches google using the provided query term and downloads the images in a folder. Args: query : The image search term to be provided by the user. Defaults to From fa49e27d22d57db01994e94d2d5391b8d52c79ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9rome=20Eertmans?= Date: Tue, 4 Oct 2022 12:25:23 +0200 Subject: [PATCH 327/726] fix: remove non-existing user from CODEOWNERS (#6648) Removes user @mateuszz0000 that does not exist, or seems to have been renamed to @L3str4nge --- .github/CODEOWNERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 260b9704e..fdce879f8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -31,7 +31,7 @@ # /data_structures/ @cclauss # TODO: Uncomment this line after Hacktoberfest -/digital_image_processing/ @mateuszz0000 +# /digital_image_processing/ # /divide_and_conquer/ @@ -79,7 +79,7 @@ # /searches/ -/sorts/ @mateuszz0000 +# /sorts/ # /strings/ @cclauss # TODO: Uncomment this line after Hacktoberfest From a84fb58271b1d42da300ccad54ee8391a518a5bb Mon Sep 17 00:00:00 2001 From: Tarun Jain <66197713+lucifertrj@users.noreply.github.com> Date: Tue, 4 Oct 2022 22:10:53 +0530 Subject: [PATCH 328/726] Discord Server invite (#6663) --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c9525aa40..b5a07af10 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -176,7 +176,7 @@ We want your work to be readable by others; therefore, we encourage you to note - Most importantly, - __Be consistent in the use of these guidelines when submitting.__ - - __Join__ [Gitter](https://gitter.im/TheAlgorithms) __now!__ + - __Join__ us on [Discord](https://discord.com/invite/c7MnfGFGa6) and [Gitter](https://gitter.im/TheAlgorithms) __now!__ - Happy coding! Writer [@poyea](https://github.com/poyea), Jun 2019. From 46842e8c5b5fc78ced0f38206560deb2b8160a54 Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj <114707091+rohanr18@users.noreply.github.com> Date: Tue, 4 Oct 2022 23:35:56 +0530 Subject: [PATCH 329/726] Add missing type hints in `matrix` directory (#6612) * Update count_islands_in_matrix.py * Update matrix_class.py * Update matrix_operation.py * Update nth_fibonacci_using_matrix_exponentiation.py * Update searching_in_sorted_matrix.py * Update count_islands_in_matrix.py * Update matrix_class.py * Update matrix_operation.py * Update rotate_matrix.py * Update sherman_morrison.py * Update spiral_print.py * Update count_islands_in_matrix.py * formatting * formatting * Update matrix_class.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- matrix/count_islands_in_matrix.py | 7 +- matrix/matrix_class.py | 80 ++++++++++--------- matrix/matrix_operation.py | 34 ++++---- ...h_fibonacci_using_matrix_exponentiation.py | 10 +-- matrix/rotate_matrix.py | 16 ++-- matrix/searching_in_sorted_matrix.py | 4 +- matrix/sherman_morrison.py | 46 +++++------ matrix/spiral_print.py | 64 +++++++++------ 8 files changed, 142 insertions(+), 119 deletions(-) diff --git a/matrix/count_islands_in_matrix.py b/matrix/count_islands_in_matrix.py index ad9c67fb8..00f9e1436 100644 --- a/matrix/count_islands_in_matrix.py +++ b/matrix/count_islands_in_matrix.py @@ -4,12 +4,12 @@ class matrix: # Public class to implement a graph - def __init__(self, row: int, col: int, graph: list): + def __init__(self, row: int, col: int, graph: list[list[bool]]) -> None: self.ROW = row self.COL = col self.graph = graph - def is_safe(self, i, j, visited) -> bool: + def is_safe(self, i: int, j: int, visited: list[list[bool]]) -> bool: return ( 0 <= i < self.ROW and 0 <= j < self.COL @@ -17,7 +17,8 @@ class matrix: # Public class to implement a graph and self.graph[i][j] ) - def diffs(self, i, j, visited): # Checking all 8 elements surrounding nth element + def diffs(self, i: int, j: int, visited: list[list[bool]]) -> None: + # Checking all 8 elements surrounding nth element rowNbr = [-1, -1, -1, 0, 0, 1, 1, 1] # Coordinate order colNbr = [-1, 0, 1, -1, 1, -1, 0, 1] visited[i][j] = True # Make those cells visited diff --git a/matrix/matrix_class.py b/matrix/matrix_class.py index 57a2fc45f..305cad0a5 100644 --- a/matrix/matrix_class.py +++ b/matrix/matrix_class.py @@ -1,5 +1,7 @@ # An OOP approach to representing and manipulating matrices +from __future__ import annotations + class Matrix: """ @@ -54,7 +56,9 @@ class Matrix: [6. -12. 6.] [-3. 6. -3.]] >>> print(matrix.inverse()) - None + Traceback (most recent call last): + ... + TypeError: Only matrices with a non-zero determinant have an inverse Determinant is an int, float, or Nonetype >>> matrix.determinant() @@ -101,10 +105,9 @@ class Matrix: [198. 243. 288. 304.] [306. 378. 450. 472.] [414. 513. 612. 640.]] - """ - def __init__(self, rows): + def __init__(self, rows: list[list[int]]): error = TypeError( "Matrices must be formed from a list of zero or more lists containing at " "least one and the same number of values, each of which must be of type " @@ -125,42 +128,43 @@ class Matrix: self.rows = [] # MATRIX INFORMATION - def columns(self): + def columns(self) -> list[list[int]]: return [[row[i] for row in self.rows] for i in range(len(self.rows[0]))] @property - def num_rows(self): + def num_rows(self) -> int: return len(self.rows) @property - def num_columns(self): + def num_columns(self) -> int: return len(self.rows[0]) @property - def order(self): + def order(self) -> tuple[int, int]: return (self.num_rows, self.num_columns) @property - def is_square(self): + def is_square(self) -> bool: return self.order[0] == self.order[1] - def identity(self): + def identity(self) -> Matrix: values = [ [0 if column_num != row_num else 1 for column_num in range(self.num_rows)] for row_num in range(self.num_rows) ] return Matrix(values) - def determinant(self): + def determinant(self) -> int: if not self.is_square: - return None + return 0 if self.order == (0, 0): return 1 if self.order == (1, 1): - return self.rows[0][0] + return int(self.rows[0][0]) if self.order == (2, 2): - return (self.rows[0][0] * self.rows[1][1]) - ( - self.rows[0][1] * self.rows[1][0] + return int( + (self.rows[0][0] * self.rows[1][1]) + - (self.rows[0][1] * self.rows[1][0]) ) else: return sum( @@ -168,10 +172,10 @@ class Matrix: for column in range(self.num_columns) ) - def is_invertable(self): + def is_invertable(self) -> bool: return bool(self.determinant()) - def get_minor(self, row, column): + def get_minor(self, row: int, column: int) -> int: values = [ [ self.rows[other_row][other_column] @@ -183,12 +187,12 @@ class Matrix: ] return Matrix(values).determinant() - def get_cofactor(self, row, column): + def get_cofactor(self, row: int, column: int) -> int: if (row + column) % 2 == 0: return self.get_minor(row, column) return -1 * self.get_minor(row, column) - def minors(self): + def minors(self) -> Matrix: return Matrix( [ [self.get_minor(row, column) for column in range(self.num_columns)] @@ -196,7 +200,7 @@ class Matrix: ] ) - def cofactors(self): + def cofactors(self) -> Matrix: return Matrix( [ [ @@ -209,25 +213,27 @@ class Matrix: ] ) - def adjugate(self): + def adjugate(self) -> Matrix: values = [ [self.cofactors().rows[column][row] for column in range(self.num_columns)] for row in range(self.num_rows) ] return Matrix(values) - def inverse(self): + def inverse(self) -> Matrix: determinant = self.determinant() - return None if not determinant else self.adjugate() * (1 / determinant) + if not determinant: + raise TypeError("Only matrices with a non-zero determinant have an inverse") + return self.adjugate() * (1 / determinant) - def __repr__(self): + def __repr__(self) -> str: return str(self.rows) - def __str__(self): + def __str__(self) -> str: if self.num_rows == 0: return "[]" if self.num_rows == 1: - return "[[" + ". ".join(self.rows[0]) + "]]" + return "[[" + ". ".join(str(self.rows[0])) + "]]" return ( "[" + "\n ".join( @@ -240,7 +246,7 @@ class Matrix: ) # MATRIX MANIPULATION - def add_row(self, row, position=None): + def add_row(self, row: list[int], position: int | None = None) -> None: type_error = TypeError("Row must be a list containing all ints and/or floats") if not isinstance(row, list): raise type_error @@ -256,7 +262,7 @@ class Matrix: else: self.rows = self.rows[0:position] + [row] + self.rows[position:] - def add_column(self, column, position=None): + def add_column(self, column: list[int], position: int | None = None) -> None: type_error = TypeError( "Column must be a list containing all ints and/or floats" ) @@ -278,18 +284,18 @@ class Matrix: ] # MATRIX OPERATIONS - def __eq__(self, other): + def __eq__(self, other: object) -> bool: if not isinstance(other, Matrix): raise TypeError("A Matrix can only be compared with another Matrix") return self.rows == other.rows - def __ne__(self, other): + def __ne__(self, other: object) -> bool: return not self == other - def __neg__(self): + def __neg__(self) -> Matrix: return self * -1 - def __add__(self, other): + def __add__(self, other: Matrix) -> Matrix: if self.order != other.order: raise ValueError("Addition requires matrices of the same order") return Matrix( @@ -299,7 +305,7 @@ class Matrix: ] ) - def __sub__(self, other): + def __sub__(self, other: Matrix) -> Matrix: if self.order != other.order: raise ValueError("Subtraction requires matrices of the same order") return Matrix( @@ -309,9 +315,11 @@ class Matrix: ] ) - def __mul__(self, other): + def __mul__(self, other: Matrix | int | float) -> Matrix: if isinstance(other, (int, float)): - return Matrix([[element * other for element in row] for row in self.rows]) + return Matrix( + [[int(element * other) for element in row] for row in self.rows] + ) elif isinstance(other, Matrix): if self.num_columns != other.num_rows: raise ValueError( @@ -329,7 +337,7 @@ class Matrix: "A Matrix can only be multiplied by an int, float, or another matrix" ) - def __pow__(self, other): + def __pow__(self, other: int) -> Matrix: if not isinstance(other, int): raise TypeError("A Matrix can only be raised to the power of an int") if not self.is_square: @@ -348,7 +356,7 @@ class Matrix: return result @classmethod - def dot_product(cls, row, column): + def dot_product(cls, row: list[int], column: list[int]) -> int: return sum(row[i] * column[i] for i in range(len(row))) diff --git a/matrix/matrix_operation.py b/matrix/matrix_operation.py index 8e5d0f583..576094902 100644 --- a/matrix/matrix_operation.py +++ b/matrix/matrix_operation.py @@ -4,8 +4,10 @@ Functions for 2D matrix operations from __future__ import annotations +from typing import Any -def add(*matrix_s: list[list]) -> list[list]: + +def add(*matrix_s: list[list[int]]) -> list[list[int]]: """ >>> add([[1,2],[3,4]],[[2,3],[4,5]]) [[3, 5], [7, 9]] @@ -25,7 +27,7 @@ def add(*matrix_s: list[list]) -> list[list]: raise TypeError("Expected a matrix, got int/list instead") -def subtract(matrix_a: list[list], matrix_b: list[list]) -> list[list]: +def subtract(matrix_a: list[list[int]], matrix_b: list[list[int]]) -> list[list[int]]: """ >>> subtract([[1,2],[3,4]],[[2,3],[4,5]]) [[-1, -1], [-1, -1]] @@ -45,7 +47,7 @@ def subtract(matrix_a: list[list], matrix_b: list[list]) -> list[list]: raise TypeError("Expected a matrix, got int/list instead") -def scalar_multiply(matrix: list[list], n: int | float) -> list[list]: +def scalar_multiply(matrix: list[list[int]], n: int | float) -> list[list[float]]: """ >>> scalar_multiply([[1,2],[3,4]],5) [[5, 10], [15, 20]] @@ -55,7 +57,7 @@ def scalar_multiply(matrix: list[list], n: int | float) -> list[list]: return [[x * n for x in row] for row in matrix] -def multiply(matrix_a: list[list], matrix_b: list[list]) -> list[list]: +def multiply(matrix_a: list[list[int]], matrix_b: list[list[int]]) -> list[list[int]]: """ >>> multiply([[1,2],[3,4]],[[5,5],[7,5]]) [[19, 15], [43, 35]] @@ -77,7 +79,7 @@ def multiply(matrix_a: list[list], matrix_b: list[list]) -> list[list]: ] -def identity(n: int) -> list[list]: +def identity(n: int) -> list[list[int]]: """ :param n: dimension for nxn matrix :type n: int @@ -89,7 +91,9 @@ def identity(n: int) -> list[list]: return [[int(row == column) for column in range(n)] for row in range(n)] -def transpose(matrix: list[list], return_map: bool = True) -> list[list] | map[list]: +def transpose( + matrix: list[list[int]], return_map: bool = True +) -> list[list[int]] | map[list[int]]: """ >>> transpose([[1,2],[3,4]]) # doctest: +ELLIPSIS list[list] | map[l raise TypeError("Expected a matrix, got int/list instead") -def minor(matrix: list[list], row: int, column: int) -> list[list]: +def minor(matrix: list[list[int]], row: int, column: int) -> list[list[int]]: """ >>> minor([[1, 2], [3, 4]], 1, 1) [[1]] @@ -117,7 +121,7 @@ def minor(matrix: list[list], row: int, column: int) -> list[list]: return [row[:column] + row[column + 1 :] for row in minor] -def determinant(matrix: list[list]) -> int: +def determinant(matrix: list[list[int]]) -> Any: """ >>> determinant([[1, 2], [3, 4]]) -2 @@ -133,7 +137,7 @@ def determinant(matrix: list[list]) -> int: ) -def inverse(matrix: list[list]) -> list[list] | None: +def inverse(matrix: list[list[int]]) -> list[list[float]] | None: """ >>> inverse([[1, 2], [3, 4]]) [[-2.0, 1.0], [1.5, -0.5]] @@ -157,27 +161,27 @@ def inverse(matrix: list[list]) -> list[list] | None: return scalar_multiply(adjugate, 1 / det) -def _check_not_integer(matrix: list[list]) -> bool: +def _check_not_integer(matrix: list[list[int]]) -> bool: return not isinstance(matrix, int) and not isinstance(matrix[0], int) -def _shape(matrix: list[list]) -> tuple[int, int]: +def _shape(matrix: list[list[int]]) -> tuple[int, int]: return len(matrix), len(matrix[0]) def _verify_matrix_sizes( - matrix_a: list[list], matrix_b: list[list] -) -> tuple[tuple, tuple]: + matrix_a: list[list[int]], matrix_b: list[list[int]] +) -> tuple[tuple[int, int], tuple[int, int]]: shape = _shape(matrix_a) + _shape(matrix_b) if shape[0] != shape[3] or shape[1] != shape[2]: raise ValueError( - "operands could not be broadcast together with shape " + f"operands could not be broadcast together with shape " f"({shape[0], shape[1]}), ({shape[2], shape[3]})" ) return (shape[0], shape[2]), (shape[1], shape[3]) -def main(): +def main() -> None: matrix_a = [[12, 10], [3, 9]] matrix_b = [[3, 4], [7, 4]] matrix_c = [[11, 12, 13, 14], [21, 22, 23, 24], [31, 32, 33, 34], [41, 42, 43, 44]] diff --git a/matrix/nth_fibonacci_using_matrix_exponentiation.py b/matrix/nth_fibonacci_using_matrix_exponentiation.py index 341a02e1a..7c964d884 100644 --- a/matrix/nth_fibonacci_using_matrix_exponentiation.py +++ b/matrix/nth_fibonacci_using_matrix_exponentiation.py @@ -16,7 +16,7 @@ We can decrease the n times multiplication by following the divide and conquer a """ -def multiply(matrix_a, matrix_b): +def multiply(matrix_a: list[list[int]], matrix_b: list[list[int]]) -> list[list[int]]: matrix_c = [] n = len(matrix_a) for i in range(n): @@ -30,11 +30,11 @@ def multiply(matrix_a, matrix_b): return matrix_c -def identity(n): +def identity(n: int) -> list[list[int]]: return [[int(row == column) for column in range(n)] for row in range(n)] -def nth_fibonacci_matrix(n): +def nth_fibonacci_matrix(n: int) -> int: """ >>> nth_fibonacci_matrix(100) 354224848179261915075 @@ -54,7 +54,7 @@ def nth_fibonacci_matrix(n): return res_matrix[0][0] -def nth_fibonacci_bruteforce(n): +def nth_fibonacci_bruteforce(n: int) -> int: """ >>> nth_fibonacci_bruteforce(100) 354224848179261915075 @@ -70,7 +70,7 @@ def nth_fibonacci_bruteforce(n): return fib1 -def main(): +def main() -> None: for ordinal in "0th 1st 2nd 3rd 10th 100th 1000th".split(): n = int("".join(c for c in ordinal if c in "0123456789")) # 1000th --> 1000 print( diff --git a/matrix/rotate_matrix.py b/matrix/rotate_matrix.py index f638597ae..c16cdb9a8 100644 --- a/matrix/rotate_matrix.py +++ b/matrix/rotate_matrix.py @@ -8,7 +8,7 @@ https://stackoverflow.com/questions/42519/how-do-you-rotate-a-two-dimensional-ar from __future__ import annotations -def make_matrix(row_size: int = 4) -> list[list]: +def make_matrix(row_size: int = 4) -> list[list[int]]: """ >>> make_matrix() [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]] @@ -25,7 +25,7 @@ def make_matrix(row_size: int = 4) -> list[list]: return [[1 + x + y * row_size for x in range(row_size)] for y in range(row_size)] -def rotate_90(matrix: list[list]) -> list[list]: +def rotate_90(matrix: list[list[int]]) -> list[list[int]]: """ >>> rotate_90(make_matrix()) [[4, 8, 12, 16], [3, 7, 11, 15], [2, 6, 10, 14], [1, 5, 9, 13]] @@ -37,7 +37,7 @@ def rotate_90(matrix: list[list]) -> list[list]: # OR.. transpose(reverse_column(matrix)) -def rotate_180(matrix: list[list]) -> list[list]: +def rotate_180(matrix: list[list[int]]) -> list[list[int]]: """ >>> rotate_180(make_matrix()) [[16, 15, 14, 13], [12, 11, 10, 9], [8, 7, 6, 5], [4, 3, 2, 1]] @@ -49,7 +49,7 @@ def rotate_180(matrix: list[list]) -> list[list]: # OR.. reverse_column(reverse_row(matrix)) -def rotate_270(matrix: list[list]) -> list[list]: +def rotate_270(matrix: list[list[int]]) -> list[list[int]]: """ >>> rotate_270(make_matrix()) [[13, 9, 5, 1], [14, 10, 6, 2], [15, 11, 7, 3], [16, 12, 8, 4]] @@ -61,22 +61,22 @@ def rotate_270(matrix: list[list]) -> list[list]: # OR.. transpose(reverse_row(matrix)) -def transpose(matrix: list[list]) -> list[list]: +def transpose(matrix: list[list[int]]) -> list[list[int]]: matrix[:] = [list(x) for x in zip(*matrix)] return matrix -def reverse_row(matrix: list[list]) -> list[list]: +def reverse_row(matrix: list[list[int]]) -> list[list[int]]: matrix[:] = matrix[::-1] return matrix -def reverse_column(matrix: list[list]) -> list[list]: +def reverse_column(matrix: list[list[int]]) -> list[list[int]]: matrix[:] = [x[::-1] for x in matrix] return matrix -def print_matrix(matrix: list[list]) -> None: +def print_matrix(matrix: list[list[int]]) -> None: for i in matrix: print(*i) diff --git a/matrix/searching_in_sorted_matrix.py b/matrix/searching_in_sorted_matrix.py index ae8136149..ddca3b1ce 100644 --- a/matrix/searching_in_sorted_matrix.py +++ b/matrix/searching_in_sorted_matrix.py @@ -2,7 +2,7 @@ from __future__ import annotations def search_in_a_sorted_matrix( - mat: list[list], m: int, n: int, key: int | float + mat: list[list[int]], m: int, n: int, key: int | float ) -> None: """ >>> search_in_a_sorted_matrix( @@ -30,7 +30,7 @@ def search_in_a_sorted_matrix( print(f"Key {key} not found") -def main(): +def main() -> None: mat = [[2, 5, 7], [4, 8, 13], [9, 11, 15], [12, 17, 20]] x = int(input("Enter the element to be searched:")) print(mat) diff --git a/matrix/sherman_morrison.py b/matrix/sherman_morrison.py index 63783c8b4..a0c93f115 100644 --- a/matrix/sherman_morrison.py +++ b/matrix/sherman_morrison.py @@ -1,14 +1,18 @@ +from __future__ import annotations + +from typing import Any + + class Matrix: """ Matrix structure. """ - def __init__(self, row: int, column: int, default_value: float = 0): + def __init__(self, row: int, column: int, default_value: float = 0) -> None: """ Initialize matrix with given size and default value. - Example: >>> a = Matrix(2, 3, 1) >>> a @@ -20,7 +24,7 @@ class Matrix: self.row, self.column = row, column self.array = [[default_value for c in range(column)] for r in range(row)] - def __str__(self): + def __str__(self) -> str: """ Return string representation of this matrix. @@ -37,7 +41,7 @@ class Matrix: string_format_identifier = "%%%ds" % (max_element_length,) # Make string and return - def single_line(row_vector): + def single_line(row_vector: list[float]) -> str: nonlocal string_format_identifier line = "[" line += ", ".join(string_format_identifier % (obj,) for obj in row_vector) @@ -47,14 +51,13 @@ class Matrix: s += "\n".join(single_line(row_vector) for row_vector in self.array) return s - def __repr__(self): + def __repr__(self) -> str: return str(self) - def validateIndices(self, loc: tuple): + def validateIndices(self, loc: tuple[int, int]) -> bool: """ Check if given indices are valid to pick element from matrix. - Example: >>> a = Matrix(2, 6, 0) >>> a.validateIndices((2, 7)) @@ -69,11 +72,10 @@ class Matrix: else: return True - def __getitem__(self, loc: tuple): + def __getitem__(self, loc: tuple[int, int]) -> Any: """ Return array[row][column] where loc = (row, column). - Example: >>> a = Matrix(3, 2, 7) >>> a[1, 0] @@ -82,11 +84,10 @@ class Matrix: assert self.validateIndices(loc) return self.array[loc[0]][loc[1]] - def __setitem__(self, loc: tuple, value: float): + def __setitem__(self, loc: tuple[int, int], value: float) -> None: """ Set array[row][column] = value where loc = (row, column). - Example: >>> a = Matrix(2, 3, 1) >>> a[1, 2] = 51 @@ -98,11 +99,10 @@ class Matrix: assert self.validateIndices(loc) self.array[loc[0]][loc[1]] = value - def __add__(self, another): + def __add__(self, another: Matrix) -> Matrix: """ Return self + another. - Example: >>> a = Matrix(2, 1, -4) >>> b = Matrix(2, 1, 3) @@ -123,11 +123,10 @@ class Matrix: result[r, c] = self[r, c] + another[r, c] return result - def __neg__(self): + def __neg__(self) -> Matrix: """ Return -self. - Example: >>> a = Matrix(2, 2, 3) >>> a[0, 1] = a[1, 0] = -2 @@ -143,14 +142,13 @@ class Matrix: result[r, c] = -self[r, c] return result - def __sub__(self, another): + def __sub__(self, another: Matrix) -> Matrix: return self + (-another) - def __mul__(self, another): + def __mul__(self, another: int | float | Matrix) -> Matrix: """ Return self * another. - Example: >>> a = Matrix(2, 3, 1) >>> a[0,2] = a[1,2] = 3 @@ -177,11 +175,10 @@ class Matrix: else: raise TypeError(f"Unsupported type given for another ({type(another)})") - def transpose(self): + def transpose(self) -> Matrix: """ Return self^T. - Example: >>> a = Matrix(2, 3) >>> for r in range(2): @@ -201,7 +198,7 @@ class Matrix: result[c, r] = self[r, c] return result - def ShermanMorrison(self, u, v): + def ShermanMorrison(self, u: Matrix, v: Matrix) -> Any: """ Apply Sherman-Morrison formula in O(n^2). @@ -211,7 +208,6 @@ class Matrix: impossible to calculate. Warning: This method doesn't check if self is invertible. Make sure self is invertible before execute this method. - Example: >>> ainv = Matrix(3, 3, 0) >>> for i in range(3): ainv[i,i] = 1 @@ -243,7 +239,7 @@ class Matrix: # Testing if __name__ == "__main__": - def test1(): + def test1() -> None: # a^(-1) ainv = Matrix(3, 3, 0) for i in range(3): @@ -256,11 +252,11 @@ if __name__ == "__main__": v[0, 0], v[1, 0], v[2, 0] = 4, -2, 5 print(f"u is {u}") print(f"v is {v}") - print(f"uv^T is {u * v.transpose()}") + print("uv^T is %s" % (u * v.transpose())) # Sherman Morrison print(f"(a + uv^T)^(-1) is {ainv.ShermanMorrison(u, v)}") - def test2(): + def test2() -> None: import doctest doctest.testmod() diff --git a/matrix/spiral_print.py b/matrix/spiral_print.py index 6f699c1ab..2441f05d1 100644 --- a/matrix/spiral_print.py +++ b/matrix/spiral_print.py @@ -1,19 +1,17 @@ """ This program print the matrix in spiral form. This problem has been solved through recursive way. - Matrix must satisfy below conditions i) matrix should be only one or two dimensional ii) number of column of all rows should be equal """ -from collections.abc import Iterable - -def check_matrix(matrix): +def check_matrix(matrix: list[list[int]]) -> bool: # must be - if matrix and isinstance(matrix, Iterable): - if isinstance(matrix[0], Iterable): + matrix = list(list(row) for row in matrix) + if matrix and isinstance(matrix, list): + if isinstance(matrix[0], list): prev_len = 0 for row in matrix: if prev_len == 0: @@ -29,32 +27,48 @@ def check_matrix(matrix): return result -def spiralPrint(a): +def spiral_print_clockwise(a: list[list[int]]) -> None: + """ + >>> spiral_print_clockwise([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]) + 1 + 2 + 3 + 4 + 8 + 12 + 11 + 10 + 9 + 5 + 6 + 7 + """ if check_matrix(a) and len(a) > 0: - matRow = len(a) - if isinstance(a[0], Iterable): - matCol = len(a[0]) + a = list(list(row) for row in a) + mat_row = len(a) + if isinstance(a[0], list): + mat_col = len(a[0]) else: for dat in a: - print(dat), + print(dat) return # horizotal printing increasing - for i in range(0, matCol): - print(a[0][i]), + for i in range(0, mat_col): + print(a[0][i]) # vertical printing down - for i in range(1, matRow): - print(a[i][matCol - 1]), + for i in range(1, mat_row): + print(a[i][mat_col - 1]) # horizotal printing decreasing - if matRow > 1: - for i in range(matCol - 2, -1, -1): - print(a[matRow - 1][i]), + if mat_row > 1: + for i in range(mat_col - 2, -1, -1): + print(a[mat_row - 1][i]) # vertical printing up - for i in range(matRow - 2, 0, -1): - print(a[i][0]), - remainMat = [row[1 : matCol - 1] for row in a[1 : matRow - 1]] - if len(remainMat) > 0: - spiralPrint(remainMat) + for i in range(mat_row - 2, 0, -1): + print(a[i][0]) + remain_mat = [row[1 : mat_col - 1] for row in a[1 : mat_row - 1]] + if len(remain_mat) > 0: + spiral_print_clockwise(remain_mat) else: return else: @@ -64,5 +78,5 @@ def spiralPrint(a): # driver code if __name__ == "__main__": - a = ([1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]) - spiralPrint(a) + a = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]] + spiral_print_clockwise(a) From 087a3a8d537ceb179d0a47eda66f47d103c4b1b9 Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj <114707091+rohanr18@users.noreply.github.com> Date: Wed, 5 Oct 2022 01:22:49 +0530 Subject: [PATCH 330/726] lorenz -> lorentz (#6670) --- ...four_vector.py => lorentz_transformation_four_vector.py} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename physics/{lorenz_transformation_four_vector.py => lorentz_transformation_four_vector.py} (96%) diff --git a/physics/lorenz_transformation_four_vector.py b/physics/lorentz_transformation_four_vector.py similarity index 96% rename from physics/lorenz_transformation_four_vector.py rename to physics/lorentz_transformation_four_vector.py index 6c0d5f9d1..bda852c25 100644 --- a/physics/lorenz_transformation_four_vector.py +++ b/physics/lorentz_transformation_four_vector.py @@ -1,13 +1,13 @@ """ -Lorenz transformation describes the transition from a reference frame P +Lorentz transformation describes the transition from a reference frame P to another reference frame P', each of which is moving in a direction with -respect to the other. The Lorenz transformation implemented in this code +respect to the other. The Lorentz transformation implemented in this code is the relativistic version using a four vector described by Minkowsky Space: x0 = ct, x1 = x, x2 = y, and x3 = z NOTE: Please note that x0 is c (speed of light) times t (time). -So, the Lorenz transformation using a four vector is defined as: +So, the Lorentz transformation using a four vector is defined as: |ct'| | γ -γβ 0 0| |ct| |x' | = |-γβ γ 0 0| *|x | From 8cce0d463a0f65c22769fe4f0750acbeed2e0d60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9rome=20Eertmans?= Date: Wed, 5 Oct 2022 12:32:07 +0200 Subject: [PATCH 331/726] refactor: pivot is randomly chosen (#6643) As described in #6095, this reduces the chances to observe a O(n^2) complexity. Here, `collection.pop(pivot_index)` is avoided for performance reasons. Fixes: #6095 --- sorts/quick_sort.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/sorts/quick_sort.py b/sorts/quick_sort.py index b099c7886..70cd19d7a 100644 --- a/sorts/quick_sort.py +++ b/sorts/quick_sort.py @@ -9,6 +9,8 @@ python3 quick_sort.py """ from __future__ import annotations +from random import randrange + def quick_sort(collection: list) -> list: """A pure Python implementation of quick sort algorithm @@ -26,11 +28,17 @@ def quick_sort(collection: list) -> list: """ if len(collection) < 2: return collection - pivot = collection.pop() # Use the last element as the first pivot + pivot_index = randrange(len(collection)) # Use random element as pivot + pivot = collection[pivot_index] greater: list[int] = [] # All elements greater than pivot lesser: list[int] = [] # All elements less than or equal to pivot - for element in collection: + + for element in collection[:pivot_index]: (greater if element > pivot else lesser).append(element) + + for element in collection[pivot_index + 1 :]: + (greater if element > pivot else lesser).append(element) + return quick_sort(lesser) + [pivot] + quick_sort(greater) From 660d2bb66c8ca03e2225090b5c638ffb0fd14a60 Mon Sep 17 00:00:00 2001 From: Paul <56065602+ZeroDayOwl@users.noreply.github.com> Date: Thu, 6 Oct 2022 23:19:34 +0600 Subject: [PATCH 332/726] Add algorithm for Newton's Law of Gravitation (#6626) * Add algorithm for Newton's Law of Gravitation * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update physics/newtons_law_of_gravitation.py Co-authored-by: Christian Clauss * One and only one argument must be 0 * Update newtons_law_of_gravitation.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- physics/newtons_law_of_gravitation.py | 100 ++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 physics/newtons_law_of_gravitation.py diff --git a/physics/newtons_law_of_gravitation.py b/physics/newtons_law_of_gravitation.py new file mode 100644 index 000000000..0bb27bb24 --- /dev/null +++ b/physics/newtons_law_of_gravitation.py @@ -0,0 +1,100 @@ +""" +Title : Finding the value of either Gravitational Force, one of the masses or distance +provided that the other three parameters are given. + +Description : Newton's Law of Universal Gravitation explains the presence of force of +attraction between bodies having a definite mass situated at a distance. It is usually +stated as that, every particle attracts every other particle in the universe with a +force that is directly proportional to the product of their masses and inversely +proportional to the square of the distance between their centers. The publication of the +theory has become known as the "first great unification", as it marked the unification +of the previously described phenomena of gravity on Earth with known astronomical +behaviors. + +The equation for the universal gravitation is as follows: +F = (G * mass_1 * mass_2) / (distance)^2 + +Source : +- https://en.wikipedia.org/wiki/Newton%27s_law_of_universal_gravitation +- Newton (1687) "Philosophiæ Naturalis Principia Mathematica" +""" + +from __future__ import annotations + +# Define the Gravitational Constant G and the function +GRAVITATIONAL_CONSTANT = 6.6743e-11 # unit of G : m^3 * kg^-1 * s^-2 + + +def gravitational_law( + force: float, mass_1: float, mass_2: float, distance: float +) -> dict[str, float]: + + """ + Input Parameters + ---------------- + force : magnitude in Newtons + + mass_1 : mass in Kilograms + + mass_2 : mass in Kilograms + + distance : distance in Meters + + Returns + ------- + result : dict name, value pair of the parameter having Zero as it's value + + Returns the value of one of the parameters specified as 0, provided the values of + other parameters are given. + >>> gravitational_law(force=0, mass_1=5, mass_2=10, distance=20) + {'force': 8.342875e-12} + + >>> gravitational_law(force=7367.382, mass_1=0, mass_2=74, distance=3048) + {'mass_1': 1.385816317292268e+19} + + >>> gravitational_law(force=36337.283, mass_1=0, mass_2=0, distance=35584) + Traceback (most recent call last): + ... + ValueError: One and only one argument must be 0 + + >>> gravitational_law(force=36337.283, mass_1=-674, mass_2=0, distance=35584) + Traceback (most recent call last): + ... + ValueError: Mass can not be negative + + >>> gravitational_law(force=-847938e12, mass_1=674, mass_2=0, distance=9374) + Traceback (most recent call last): + ... + ValueError: Gravitational force can not be negative + """ + + product_of_mass = mass_1 * mass_2 + + if (force, mass_1, mass_2, distance).count(0) != 1: + raise ValueError("One and only one argument must be 0") + if force < 0: + raise ValueError("Gravitational force can not be negative") + if distance < 0: + raise ValueError("Distance can not be negative") + if mass_1 < 0 or mass_2 < 0: + raise ValueError("Mass can not be negative") + if force == 0: + force = GRAVITATIONAL_CONSTANT * product_of_mass / (distance**2) + return {"force": force} + elif mass_1 == 0: + mass_1 = (force) * (distance**2) / (GRAVITATIONAL_CONSTANT * mass_2) + return {"mass_1": mass_1} + elif mass_2 == 0: + mass_2 = (force) * (distance**2) / (GRAVITATIONAL_CONSTANT * mass_1) + return {"mass_2": mass_2} + elif distance == 0: + distance = (GRAVITATIONAL_CONSTANT * product_of_mass / (force)) ** 0.5 + return {"distance": distance} + raise ValueError("One and only one argument must be 0") + + +# Run doctest +if __name__ == "__main__": + import doctest + + doctest.testmod() From 5894554d41116af83152b1ea59fbf78303d87966 Mon Sep 17 00:00:00 2001 From: Jordan Rinder Date: Sat, 8 Oct 2022 18:28:17 -0400 Subject: [PATCH 333/726] Add Catalan number to maths (#6845) * Add Catalan number to maths * updating DIRECTORY.md * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- DIRECTORY.md | 4 +++- maths/catalan_number.py | 51 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 maths/catalan_number.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 64e9d5333..668da4761 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -475,6 +475,7 @@ * [Binomial Coefficient](maths/binomial_coefficient.py) * [Binomial Distribution](maths/binomial_distribution.py) * [Bisection](maths/bisection.py) + * [Catalan Number](maths/catalan_number.py) * [Ceil](maths/ceil.py) * [Check Polygon](maths/check_polygon.py) * [Chudnovsky Algorithm](maths/chudnovsky_algorithm.py) @@ -632,8 +633,9 @@ ## Physics * [Horizontal Projectile Motion](physics/horizontal_projectile_motion.py) - * [Lorenz Transformation Four Vector](physics/lorenz_transformation_four_vector.py) + * [Lorentz Transformation Four Vector](physics/lorentz_transformation_four_vector.py) * [N Body Simulation](physics/n_body_simulation.py) + * [Newtons Law Of Gravitation](physics/newtons_law_of_gravitation.py) * [Newtons Second Law Of Motion](physics/newtons_second_law_of_motion.py) ## Project Euler diff --git a/maths/catalan_number.py b/maths/catalan_number.py new file mode 100644 index 000000000..4a1280a45 --- /dev/null +++ b/maths/catalan_number.py @@ -0,0 +1,51 @@ +""" + +Calculate the nth Catalan number + +Source: + https://en.wikipedia.org/wiki/Catalan_number + +""" + + +def catalan(number: int) -> int: + """ + :param number: nth catalan number to calculate + :return: the nth catalan number + Note: A catalan number is only defined for positive integers + + >>> catalan(5) + 14 + >>> catalan(0) + Traceback (most recent call last): + ... + ValueError: Input value of [number=0] must be > 0 + >>> catalan(-1) + Traceback (most recent call last): + ... + ValueError: Input value of [number=-1] must be > 0 + >>> catalan(5.0) + Traceback (most recent call last): + ... + TypeError: Input value of [number=5.0] must be an integer + """ + + if not isinstance(number, int): + raise TypeError(f"Input value of [number={number}] must be an integer") + + if number < 1: + raise ValueError(f"Input value of [number={number}] must be > 0") + + current_number = 1 + + for i in range(1, number): + current_number *= 4 * i - 2 + current_number //= i + 1 + + return current_number + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 51dba4d743cd2c8d407eea3e9cd4e7b2f69ee34d Mon Sep 17 00:00:00 2001 From: Lakshay Roopchandani <75477853+lakshayroop5@users.noreply.github.com> Date: Sun, 9 Oct 2022 18:23:44 +0530 Subject: [PATCH 334/726] Job sequencing with deadlines (#6854) * completed optimised code for job sequencing with deadline problem * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * completed optimised code for job sequencing with deadline problem * completed optimized code for job sequencing with deadline problem * completed optimised code for job sequencing with deadline problem * completed optimised code for job sequencing with deadline problem * completed optimised code for job sequencing with deadline problem * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * completed optimized code for the issue "Job Scheduling with deadlines" * completed optimized code for the issue "Job Scheduling with deadlines" * completed optimized code for the issue "Job Scheduling with deadlines" * Update greedy_methods/job_sequencing_with_deadline.py Co-authored-by: Christian Clauss * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Updated reviews * Updated reviews * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update and rename greedy_methods/job_sequencing_with_deadline.py to scheduling/job_sequencing_with_deadline.py Co-authored-by: lakshayroop5 <87693528+lavenroop5@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- scheduling/job_sequencing_with_deadline.py | 48 ++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 scheduling/job_sequencing_with_deadline.py diff --git a/scheduling/job_sequencing_with_deadline.py b/scheduling/job_sequencing_with_deadline.py new file mode 100644 index 000000000..7b23c0b35 --- /dev/null +++ b/scheduling/job_sequencing_with_deadline.py @@ -0,0 +1,48 @@ +def job_sequencing_with_deadlines(num_jobs: int, jobs: list) -> list: + """ + Function to find the maximum profit by doing jobs in a given time frame + + Args: + num_jobs [int]: Number of jobs + jobs [list]: A list of tuples of (job_id, deadline, profit) + + Returns: + max_profit [int]: Maximum profit that can be earned by doing jobs + in a given time frame + + Examples: + >>> job_sequencing_with_deadlines(4, + ... [(1, 4, 20), (2, 1, 10), (3, 1, 40), (4, 1, 30)]) + [2, 60] + >>> job_sequencing_with_deadlines(5, + ... [(1, 2, 100), (2, 1, 19), (3, 2, 27), (4, 1, 25), (5, 1, 15)]) + [2, 127] + """ + + # Sort the jobs in descending order of profit + jobs = sorted(jobs, key=lambda value: value[2], reverse=True) + + # Create a list of size equal to the maximum deadline + # and initialize it with -1 + max_deadline = max(jobs, key=lambda value: value[1])[1] + time_slots = [-1] * max_deadline + + # Finding the maximum profit and the count of jobs + count = 0 + max_profit = 0 + for job in jobs: + # Find a free time slot for this job + # (Note that we start from the last possible slot) + for i in range(job[1] - 1, -1, -1): + if time_slots[i] == -1: + time_slots[i] = job[0] + count += 1 + max_profit += job[2] + break + return [count, max_profit] + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 0a3433eaed6c8369f6c45b3abf70ee33a3a74910 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 10 Oct 2022 22:04:33 +0200 Subject: [PATCH 335/726] [pre-commit.ci] pre-commit autoupdate (#6940) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/psf/black: 22.8.0 → 22.10.0](https://github.com/psf/black/compare/22.8.0...22.10.0) - [github.com/asottile/pyupgrade: v2.38.2 → v3.0.0](https://github.com/asottile/pyupgrade/compare/v2.38.2...v3.0.0) - [github.com/pre-commit/mirrors-mypy: v0.981 → v0.982](https://github.com/pre-commit/mirrors-mypy/compare/v0.981...v0.982) * updating DIRECTORY.md Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- DIRECTORY.md | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a2fcf12c9..0abe647b0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: requirements-txt-fixer - repo: https://github.com/psf/black - rev: 22.8.0 + rev: 22.10.0 hooks: - id: black @@ -26,7 +26,7 @@ repos: - --profile=black - repo: https://github.com/asottile/pyupgrade - rev: v2.38.2 + rev: v3.0.0 hooks: - id: pyupgrade args: @@ -42,7 +42,7 @@ repos: - --max-line-length=88 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.981 + rev: v0.982 hooks: - id: mypy args: diff --git a/DIRECTORY.md b/DIRECTORY.md index 668da4761..9ef72c403 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -927,6 +927,7 @@ ## Scheduling * [First Come First Served](scheduling/first_come_first_served.py) * [Highest Response Ratio Next](scheduling/highest_response_ratio_next.py) + * [Job Sequencing With Deadline](scheduling/job_sequencing_with_deadline.py) * [Multi Level Feedback Queue](scheduling/multi_level_feedback_queue.py) * [Non Preemptive Shortest Job First](scheduling/non_preemptive_shortest_job_first.py) * [Round Robin](scheduling/round_robin.py) From f0d1a42deb146bebcdf7b1b2ec788c815ede452a Mon Sep 17 00:00:00 2001 From: Shubhajit Roy <81477286+shubhajitroy123@users.noreply.github.com> Date: Wed, 12 Oct 2022 12:52:23 +0530 Subject: [PATCH 336/726] Python program for Carmicheal Number (#6864) * Add files via upload Python program to determine whether a number is Carmichael Number or not. * Rename Carmichael Number.py to carmichael number.py * Rename carmichael number.py to carmichael_number.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update carmichael_number.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Create carmichael_number.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update maths/carmichael_number.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- maths/carmichael_number.py | 47 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 maths/carmichael_number.py diff --git a/maths/carmichael_number.py b/maths/carmichael_number.py new file mode 100644 index 000000000..09a4fedfb --- /dev/null +++ b/maths/carmichael_number.py @@ -0,0 +1,47 @@ +""" +== Carmichael Numbers == +A number n is said to be a Carmichael number if it +satisfies the following modular arithmetic condition: + + power(b, n-1) MOD n = 1, + for all b ranging from 1 to n such that b and + n are relatively prime, i.e, gcd(b, n) = 1 + +Examples of Carmichael Numbers: 561, 1105, ... +https://en.wikipedia.org/wiki/Carmichael_number +""" + + +def gcd(a: int, b: int) -> int: + if a < b: + return gcd(b, a) + if a % b == 0: + return b + return gcd(b, a % b) + + +def power(x: int, y: int, mod: int) -> int: + if y == 0: + return 1 + temp = power(x, y // 2, mod) % mod + temp = (temp * temp) % mod + if y % 2 == 1: + temp = (temp * x) % mod + return temp + + +def isCarmichaelNumber(n: int) -> bool: + b = 2 + while b < n: + if gcd(b, n) == 1 and power(b, n - 1, n) != 1: + return False + b += 1 + return True + + +if __name__ == "__main__": + number = int(input("Enter number: ").strip()) + if isCarmichaelNumber(number): + print(f"{number} is a Carmichael Number.") + else: + print(f"{number} is not a Carmichael Number.") From a04a6365dee01bebf382809a5638b6fd0d0a51e6 Mon Sep 17 00:00:00 2001 From: Martmists Date: Wed, 12 Oct 2022 15:19:00 +0200 Subject: [PATCH 337/726] Add Equal Loudness Filter (#7019) * Add Equal Loudness Filter Signed-off-by: Martmists * NoneType return on __init__ Signed-off-by: Martmists * Add data to JSON as requested by @CenTdemeern1 in a not very polite manner Signed-off-by: Martmists * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * 'modernize' Signed-off-by: Martmists * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update audio_filters/equal_loudness_filter.py Co-authored-by: Christian Clauss * Update equal_loudness_filter.py * Update equal_loudness_filter.py * Finally!! * Arrgghh Signed-off-by: Martmists Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- audio_filters/equal_loudness_filter.py | 61 +++++++++++++++++++++ audio_filters/loudness_curve.json | 76 ++++++++++++++++++++++++++ requirements.txt | 1 + 3 files changed, 138 insertions(+) create mode 100644 audio_filters/equal_loudness_filter.py create mode 100644 audio_filters/loudness_curve.json diff --git a/audio_filters/equal_loudness_filter.py b/audio_filters/equal_loudness_filter.py new file mode 100644 index 000000000..b9a3c50e1 --- /dev/null +++ b/audio_filters/equal_loudness_filter.py @@ -0,0 +1,61 @@ +from json import loads +from pathlib import Path + +import numpy as np +from yulewalker import yulewalk + +from audio_filters.butterworth_filter import make_highpass +from audio_filters.iir_filter import IIRFilter + +data = loads((Path(__file__).resolve().parent / "loudness_curve.json").read_text()) + + +class EqualLoudnessFilter: + r""" + An equal-loudness filter which compensates for the human ear's non-linear response + to sound. + This filter corrects this by cascading a yulewalk filter and a butterworth filter. + + Designed for use with samplerate of 44.1kHz and above. If you're using a lower + samplerate, use with caution. + + Code based on matlab implementation at https://bit.ly/3eqh2HU + (url shortened for flake8) + + Target curve: https://i.imgur.com/3g2VfaM.png + Yulewalk response: https://i.imgur.com/J9LnJ4C.png + Butterworth and overall response: https://i.imgur.com/3g2VfaM.png + + Images and original matlab implementation by David Robinson, 2001 + """ + + def __init__(self, samplerate: int = 44100) -> None: + self.yulewalk_filter = IIRFilter(10) + self.butterworth_filter = make_highpass(150, samplerate) + + # pad the data to nyquist + curve_freqs = np.array(data["frequencies"] + [max(20000.0, samplerate / 2)]) + curve_gains = np.array(data["gains"] + [140]) + + # Convert to angular frequency + freqs_normalized = curve_freqs / samplerate * 2 + # Invert the curve and normalize to 0dB + gains_normalized = np.power(10, (np.min(curve_gains) - curve_gains) / 20) + + # Scipy's `yulewalk` function is a stub, so we're using the + # `yulewalker` library instead. + # This function computes the coefficients using a least-squares + # fit to the specified curve. + ya, yb = yulewalk(10, freqs_normalized, gains_normalized) + self.yulewalk_filter.set_coefficients(ya, yb) + + def process(self, sample: float) -> float: + """ + Process a single sample through both filters + + >>> filt = EqualLoudnessFilter() + >>> filt.process(0.0) + 0.0 + """ + tmp = self.yulewalk_filter.process(sample) + return self.butterworth_filter.process(tmp) diff --git a/audio_filters/loudness_curve.json b/audio_filters/loudness_curve.json new file mode 100644 index 000000000..fc066a081 --- /dev/null +++ b/audio_filters/loudness_curve.json @@ -0,0 +1,76 @@ +{ + "_comment": "The following is a representative average of the Equal Loudness Contours as measured by Robinson and Dadson, 1956", + "_doi": "10.1088/0508-3443/7/5/302", + "frequencies": [ + 0, + 20, + 30, + 40, + 50, + 60, + 70, + 80, + 90, + 100, + 200, + 300, + 400, + 500, + 600, + 700, + 800, + 900, + 1000, + 1500, + 2000, + 2500, + 3000, + 3700, + 4000, + 5000, + 6000, + 7000, + 8000, + 9000, + 10000, + 12000, + 15000, + 20000 + ], + "gains": [ + 120, + 113, + 103, + 97, + 93, + 91, + 89, + 87, + 86, + 85, + 78, + 76, + 76, + 76, + 76, + 77, + 78, + 79.5, + 80, + 79, + 77, + 74, + 71.5, + 70, + 70.5, + 74, + 79, + 84, + 86, + 86, + 85, + 95, + 110, + 125 + ] +} diff --git a/requirements.txt b/requirements.txt index 294494acf..0fbc1cc4b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,3 +17,4 @@ tensorflow texttable tweepy xgboost +yulewalker From d15bf7d492bc778682f80392bfd559074c4adbec Mon Sep 17 00:00:00 2001 From: Saksham Chawla <51916697+saksham-chawla@users.noreply.github.com> Date: Wed, 12 Oct 2022 22:05:31 +0530 Subject: [PATCH 338/726] Add typing to data_structures/heap/heap_generic.py (#7044) * Update heap_generic.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update heap_generic.py * Update heap_generic.py * Update heap_generic.py * Update heap_generic.py * Update heap_generic.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- data_structures/heap/heap_generic.py | 35 +++++++++++++++------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/data_structures/heap/heap_generic.py b/data_structures/heap/heap_generic.py index 553cb9451..e7831cd45 100644 --- a/data_structures/heap/heap_generic.py +++ b/data_structures/heap/heap_generic.py @@ -1,35 +1,38 @@ +from collections.abc import Callable + + class Heap: """ A generic Heap class, can be used as min or max by passing the key function accordingly. """ - def __init__(self, key=None): + def __init__(self, key: Callable | None = None) -> None: # Stores actual heap items. - self.arr = list() + self.arr: list = list() # Stores indexes of each item for supporting updates and deletion. - self.pos_map = {} + self.pos_map: dict = {} # Stores current size of heap. self.size = 0 # Stores function used to evaluate the score of an item on which basis ordering # will be done. self.key = key or (lambda x: x) - def _parent(self, i): + def _parent(self, i: int) -> int | None: """Returns parent index of given index if exists else None""" return int((i - 1) / 2) if i > 0 else None - def _left(self, i): + def _left(self, i: int) -> int | None: """Returns left-child-index of given index if exists else None""" left = int(2 * i + 1) return left if 0 < left < self.size else None - def _right(self, i): + def _right(self, i: int) -> int | None: """Returns right-child-index of given index if exists else None""" right = int(2 * i + 2) return right if 0 < right < self.size else None - def _swap(self, i, j): + def _swap(self, i: int, j: int) -> None: """Performs changes required for swapping two elements in the heap""" # First update the indexes of the items in index map. self.pos_map[self.arr[i][0]], self.pos_map[self.arr[j][0]] = ( @@ -39,11 +42,11 @@ class Heap: # Then swap the items in the list. self.arr[i], self.arr[j] = self.arr[j], self.arr[i] - def _cmp(self, i, j): + def _cmp(self, i: int, j: int) -> bool: """Compares the two items using default comparison""" return self.arr[i][1] < self.arr[j][1] - def _get_valid_parent(self, i): + def _get_valid_parent(self, i: int) -> int: """ Returns index of valid parent as per desired ordering among given index and both it's children @@ -59,21 +62,21 @@ class Heap: return valid_parent - def _heapify_up(self, index): + def _heapify_up(self, index: int) -> None: """Fixes the heap in upward direction of given index""" parent = self._parent(index) while parent is not None and not self._cmp(index, parent): self._swap(index, parent) index, parent = parent, self._parent(parent) - def _heapify_down(self, index): + def _heapify_down(self, index: int) -> None: """Fixes the heap in downward direction of given index""" valid_parent = self._get_valid_parent(index) while valid_parent != index: self._swap(index, valid_parent) index, valid_parent = valid_parent, self._get_valid_parent(valid_parent) - def update_item(self, item, item_value): + def update_item(self, item: int, item_value: int) -> None: """Updates given item value in heap if present""" if item not in self.pos_map: return @@ -84,7 +87,7 @@ class Heap: self._heapify_up(index) self._heapify_down(index) - def delete_item(self, item): + def delete_item(self, item: int) -> None: """Deletes given item from heap if present""" if item not in self.pos_map: return @@ -99,7 +102,7 @@ class Heap: self._heapify_up(index) self._heapify_down(index) - def insert_item(self, item, item_value): + def insert_item(self, item: int, item_value: int) -> None: """Inserts given item with given value in heap""" arr_len = len(self.arr) if arr_len == self.size: @@ -110,11 +113,11 @@ class Heap: self.size += 1 self._heapify_up(self.size - 1) - def get_top(self): + def get_top(self) -> tuple | None: """Returns top item tuple (Calculated value, item) from heap if present""" return self.arr[0] if self.size else None - def extract_top(self): + def extract_top(self) -> tuple | None: """ Return top item tuple (Calculated value, item) from heap and removes it as well if present From aeb933bff55734f33268848fb1fcb6a0395297cb Mon Sep 17 00:00:00 2001 From: Saksham Chawla <51916697+saksham-chawla@users.noreply.github.com> Date: Wed, 12 Oct 2022 22:07:00 +0530 Subject: [PATCH 339/726] Add typing to data_structures/hashing/hash_table.py (#7040) * Update hash_table.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update hash_table.py * Update hash_table.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- data_structures/hashing/hash_table.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/data_structures/hashing/hash_table.py b/data_structures/hashing/hash_table.py index f4422de53..1cd71cc4b 100644 --- a/data_structures/hashing/hash_table.py +++ b/data_structures/hashing/hash_table.py @@ -7,13 +7,18 @@ class HashTable: Basic Hash Table example with open addressing and linear probing """ - def __init__(self, size_table, charge_factor=None, lim_charge=None): + def __init__( + self, + size_table: int, + charge_factor: int | None = None, + lim_charge: float | None = None, + ) -> None: self.size_table = size_table self.values = [None] * self.size_table self.lim_charge = 0.75 if lim_charge is None else lim_charge self.charge_factor = 1 if charge_factor is None else charge_factor - self.__aux_list = [] - self._keys = {} + self.__aux_list: list = [] + self._keys: dict = {} def keys(self): return self._keys From e272b9d6a494036aaa7f71c53d01017a34117bc9 Mon Sep 17 00:00:00 2001 From: Saksham Chawla <51916697+saksham-chawla@users.noreply.github.com> Date: Wed, 12 Oct 2022 22:14:08 +0530 Subject: [PATCH 340/726] Add typing to data_structures/queue/queue_on_pseudo_stack.py (#7037) * Add typing hacktoberfest * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- data_structures/queue/queue_on_pseudo_stack.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/data_structures/queue/queue_on_pseudo_stack.py b/data_structures/queue/queue_on_pseudo_stack.py index 7fa2fb256..9a0c16f61 100644 --- a/data_structures/queue/queue_on_pseudo_stack.py +++ b/data_structures/queue/queue_on_pseudo_stack.py @@ -1,4 +1,5 @@ """Queue represented by a pseudo stack (represented by a list with pop and append)""" +from typing import Any class Queue: @@ -14,7 +15,7 @@ class Queue: @param item item to enqueue""" - def put(self, item): + def put(self, item: Any) -> None: self.stack.append(item) self.length = self.length + 1 @@ -23,7 +24,7 @@ class Queue: @return dequeued item that was dequeued""" - def get(self): + def get(self) -> Any: self.rotate(1) dequeued = self.stack[self.length - 1] self.stack = self.stack[:-1] @@ -35,7 +36,7 @@ class Queue: @param rotation number of times to rotate queue""" - def rotate(self, rotation): + def rotate(self, rotation: int) -> None: for i in range(rotation): temp = self.stack[0] self.stack = self.stack[1:] @@ -45,7 +46,7 @@ class Queue: """Reports item at the front of self @return item at front of self.stack""" - def front(self): + def front(self) -> Any: front = self.get() self.put(front) self.rotate(self.length - 1) @@ -53,5 +54,5 @@ class Queue: """Returns the length of this.stack""" - def size(self): + def size(self) -> int: return self.length From f676055bc6e4f3540c97745ffc19bf62955c9077 Mon Sep 17 00:00:00 2001 From: Saksham Chawla <51916697+saksham-chawla@users.noreply.github.com> Date: Wed, 12 Oct 2022 22:19:49 +0530 Subject: [PATCH 341/726] Add typing to maths/segmented_sieve.py (#7054) --- maths/segmented_sieve.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths/segmented_sieve.py b/maths/segmented_sieve.py index 0054b0595..35ed9702b 100644 --- a/maths/segmented_sieve.py +++ b/maths/segmented_sieve.py @@ -3,7 +3,7 @@ import math -def sieve(n): +def sieve(n: int) -> list[int]: """Segmented Sieve.""" in_prime = [] start = 2 From 922887c38609650dc8eb8eaa9153605eabc45ecd Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj <114707091+rohanr18@users.noreply.github.com> Date: Thu, 13 Oct 2022 00:04:01 +0530 Subject: [PATCH 342/726] Add volume of hollow circular cylinder, Exceptions (#6441) * Add volume of hollow circular cylinder, Exceptions * Update volume.py * floats, zeroes tests added * Update volume.py * f-strings --- maths/volume.py | 255 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 223 insertions(+), 32 deletions(-) diff --git a/maths/volume.py b/maths/volume.py index acaed65f4..97c06d7e1 100644 --- a/maths/volume.py +++ b/maths/volume.py @@ -1,6 +1,5 @@ """ Find Volumes of Various Shapes. - Wikipedia reference: https://en.wikipedia.org/wiki/Volume """ from __future__ import annotations @@ -11,12 +10,21 @@ from math import pi, pow def vol_cube(side_length: int | float) -> float: """ Calculate the Volume of a Cube. - >>> vol_cube(1) 1.0 >>> vol_cube(3) 27.0 + >>> vol_cube(0) + 0.0 + >>> vol_cube(1.6) + 4.096000000000001 + >>> vol_cube(-1) + Traceback (most recent call last): + ... + ValueError: vol_cube() only accepts non-negative values """ + if side_length < 0: + raise ValueError("vol_cube() only accepts non-negative values") return pow(side_length, 3) @@ -24,10 +32,23 @@ def vol_spherical_cap(height: float, radius: float) -> float: """ Calculate the Volume of the spherical cap. :return 1/3 pi * height ^ 2 * (3 * radius - height) - >>> vol_spherical_cap(1, 2) 5.235987755982988 + >>> vol_spherical_cap(1.6, 2.6) + 16.621119532592402 + >>> vol_spherical_cap(0, 0) + 0.0 + >>> vol_spherical_cap(-1, 2) + Traceback (most recent call last): + ... + ValueError: vol_spherical_cap() only accepts non-negative values + >>> vol_spherical_cap(1, -2) + Traceback (most recent call last): + ... + ValueError: vol_spherical_cap() only accepts non-negative values """ + if height < 0 or radius < 0: + raise ValueError("vol_spherical_cap() only accepts non-negative values") return 1 / 3 * pi * pow(height, 2) * (3 * radius - height) @@ -36,7 +57,6 @@ def vol_spheres_intersect( ) -> float: """ Calculate the volume of the intersection of two spheres. - The intersection is composed by two spherical caps and therefore its volume is the sum of the volumes of the spherical caps. First, it calculates the heights (h1, h2) of the spherical caps, then the two volumes and it returns the sum. @@ -49,10 +69,27 @@ def vol_spheres_intersect( / (2 * centers_distance) if centers_distance is 0 then it returns the volume of the smallers sphere :return vol_spherical_cap(h1, radius_2) + vol_spherical_cap(h2, radius_1) - >>> vol_spheres_intersect(2, 2, 1) 21.205750411731103 + >>> vol_spheres_intersect(2.6, 2.6, 1.6) + 40.71504079052372 + >>> vol_spheres_intersect(0, 0, 0) + 0.0 + >>> vol_spheres_intersect(-2, 2, 1) + Traceback (most recent call last): + ... + ValueError: vol_spheres_intersect() only accepts non-negative values + >>> vol_spheres_intersect(2, -2, 1) + Traceback (most recent call last): + ... + ValueError: vol_spheres_intersect() only accepts non-negative values + >>> vol_spheres_intersect(2, 2, -1) + Traceback (most recent call last): + ... + ValueError: vol_spheres_intersect() only accepts non-negative values """ + if radius_1 < 0 or radius_2 < 0 or centers_distance < 0: + raise ValueError("vol_spheres_intersect() only accepts non-negative values") if centers_distance == 0: return vol_sphere(min(radius_1, radius_2)) @@ -74,40 +111,81 @@ def vol_cuboid(width: float, height: float, length: float) -> float: """ Calculate the Volume of a Cuboid. :return multiple of width, length and height - >>> vol_cuboid(1, 1, 1) 1.0 >>> vol_cuboid(1, 2, 3) 6.0 + >>> vol_cuboid(1.6, 2.6, 3.6) + 14.976 + >>> vol_cuboid(0, 0, 0) + 0.0 + >>> vol_cuboid(-1, 2, 3) + Traceback (most recent call last): + ... + ValueError: vol_cuboid() only accepts non-negative values + >>> vol_cuboid(1, -2, 3) + Traceback (most recent call last): + ... + ValueError: vol_cuboid() only accepts non-negative values + >>> vol_cuboid(1, 2, -3) + Traceback (most recent call last): + ... + ValueError: vol_cuboid() only accepts non-negative values """ + if width < 0 or height < 0 or length < 0: + raise ValueError("vol_cuboid() only accepts non-negative values") return float(width * height * length) def vol_cone(area_of_base: float, height: float) -> float: """ Calculate the Volume of a Cone. - Wikipedia reference: https://en.wikipedia.org/wiki/Cone :return (1/3) * area_of_base * height - >>> vol_cone(10, 3) 10.0 >>> vol_cone(1, 1) 0.3333333333333333 + >>> vol_cone(1.6, 1.6) + 0.8533333333333335 + >>> vol_cone(0, 0) + 0.0 + >>> vol_cone(-1, 1) + Traceback (most recent call last): + ... + ValueError: vol_cone() only accepts non-negative values + >>> vol_cone(1, -1) + Traceback (most recent call last): + ... + ValueError: vol_cone() only accepts non-negative values """ + if height < 0 or area_of_base < 0: + raise ValueError("vol_cone() only accepts non-negative values") return area_of_base * height / 3.0 def vol_right_circ_cone(radius: float, height: float) -> float: """ Calculate the Volume of a Right Circular Cone. - Wikipedia reference: https://en.wikipedia.org/wiki/Cone :return (1/3) * pi * radius^2 * height - >>> vol_right_circ_cone(2, 3) 12.566370614359172 + >>> vol_right_circ_cone(0, 0) + 0.0 + >>> vol_right_circ_cone(1.6, 1.6) + 4.289321169701265 + >>> vol_right_circ_cone(-1, 1) + Traceback (most recent call last): + ... + ValueError: vol_right_circ_cone() only accepts non-negative values + >>> vol_right_circ_cone(1, -1) + Traceback (most recent call last): + ... + ValueError: vol_right_circ_cone() only accepts non-negative values """ + if height < 0 or radius < 0: + raise ValueError("vol_right_circ_cone() only accepts non-negative values") return pi * pow(radius, 2) * height / 3.0 @@ -116,12 +194,25 @@ def vol_prism(area_of_base: float, height: float) -> float: Calculate the Volume of a Prism. Wikipedia reference: https://en.wikipedia.org/wiki/Prism_(geometry) :return V = Bh - >>> vol_prism(10, 2) 20.0 >>> vol_prism(11, 1) 11.0 + >>> vol_prism(1.6, 1.6) + 2.5600000000000005 + >>> vol_prism(0, 0) + 0.0 + >>> vol_prism(-1, 1) + Traceback (most recent call last): + ... + ValueError: vol_prism() only accepts non-negative values + >>> vol_prism(1, -1) + Traceback (most recent call last): + ... + ValueError: vol_prism() only accepts non-negative values """ + if height < 0 or area_of_base < 0: + raise ValueError("vol_prism() only accepts non-negative values") return float(area_of_base * height) @@ -130,12 +221,25 @@ def vol_pyramid(area_of_base: float, height: float) -> float: Calculate the Volume of a Pyramid. Wikipedia reference: https://en.wikipedia.org/wiki/Pyramid_(geometry) :return (1/3) * Bh - >>> vol_pyramid(10, 3) 10.0 >>> vol_pyramid(1.5, 3) 1.5 + >>> vol_pyramid(1.6, 1.6) + 0.8533333333333335 + >>> vol_pyramid(0, 0) + 0.0 + >>> vol_pyramid(-1, 1) + Traceback (most recent call last): + ... + ValueError: vol_pyramid() only accepts non-negative values + >>> vol_pyramid(1, -1) + Traceback (most recent call last): + ... + ValueError: vol_pyramid() only accepts non-negative values """ + if height < 0 or area_of_base < 0: + raise ValueError("vol_pyramid() only accepts non-negative values") return area_of_base * height / 3.0 @@ -144,27 +248,44 @@ def vol_sphere(radius: float) -> float: Calculate the Volume of a Sphere. Wikipedia reference: https://en.wikipedia.org/wiki/Sphere :return (4/3) * pi * r^3 - >>> vol_sphere(5) 523.5987755982989 >>> vol_sphere(1) 4.1887902047863905 + >>> vol_sphere(1.6) + 17.15728467880506 + >>> vol_sphere(0) + 0.0 + >>> vol_sphere(-1) + Traceback (most recent call last): + ... + ValueError: vol_sphere() only accepts non-negative values """ + if radius < 0: + raise ValueError("vol_sphere() only accepts non-negative values") return 4 / 3 * pi * pow(radius, 3) -def vol_hemisphere(radius: float): +def vol_hemisphere(radius: float) -> float: """Calculate the volume of a hemisphere Wikipedia reference: https://en.wikipedia.org/wiki/Hemisphere Other references: https://www.cuemath.com/geometry/hemisphere :return 2/3 * pi * radius^3 - >>> vol_hemisphere(1) 2.0943951023931953 - >>> vol_hemisphere(7) 718.3775201208659 + >>> vol_hemisphere(1.6) + 8.57864233940253 + >>> vol_hemisphere(0) + 0.0 + >>> vol_hemisphere(-1) + Traceback (most recent call last): + ... + ValueError: vol_hemisphere() only accepts non-negative values """ + if radius < 0: + raise ValueError("vol_hemisphere() only accepts non-negative values") return 2 / 3 * pi * pow(radius, 3) @@ -172,26 +293,93 @@ def vol_circular_cylinder(radius: float, height: float) -> float: """Calculate the Volume of a Circular Cylinder. Wikipedia reference: https://en.wikipedia.org/wiki/Cylinder :return pi * radius^2 * height - >>> vol_circular_cylinder(1, 1) 3.141592653589793 >>> vol_circular_cylinder(4, 3) 150.79644737231007 + >>> vol_circular_cylinder(1.6, 1.6) + 12.867963509103795 + >>> vol_circular_cylinder(0, 0) + 0.0 + >>> vol_circular_cylinder(-1, 1) + Traceback (most recent call last): + ... + ValueError: vol_circular_cylinder() only accepts non-negative values + >>> vol_circular_cylinder(1, -1) + Traceback (most recent call last): + ... + ValueError: vol_circular_cylinder() only accepts non-negative values """ + if height < 0 or radius < 0: + raise ValueError("vol_circular_cylinder() only accepts non-negative values") return pi * pow(radius, 2) * height -def vol_conical_frustum(height: float, radius_1: float, radius_2: float): +def vol_hollow_circular_cylinder( + inner_radius: float, outer_radius: float, height: float +) -> float: + """Calculate the Volume of a Hollow Circular Cylinder. + >>> vol_hollow_circular_cylinder(1, 2, 3) + 28.274333882308138 + >>> vol_hollow_circular_cylinder(1.6, 2.6, 3.6) + 47.50088092227767 + >>> vol_hollow_circular_cylinder(-1, 2, 3) + Traceback (most recent call last): + ... + ValueError: vol_hollow_circular_cylinder() only accepts non-negative values + >>> vol_hollow_circular_cylinder(1, -2, 3) + Traceback (most recent call last): + ... + ValueError: vol_hollow_circular_cylinder() only accepts non-negative values + >>> vol_hollow_circular_cylinder(1, 2, -3) + Traceback (most recent call last): + ... + ValueError: vol_hollow_circular_cylinder() only accepts non-negative values + >>> vol_hollow_circular_cylinder(2, 1, 3) + Traceback (most recent call last): + ... + ValueError: outer_radius must be greater than inner_radius + >>> vol_hollow_circular_cylinder(0, 0, 0) + Traceback (most recent call last): + ... + ValueError: outer_radius must be greater than inner_radius + """ + if inner_radius < 0 or outer_radius < 0 or height < 0: + raise ValueError( + "vol_hollow_circular_cylinder() only accepts non-negative values" + ) + if outer_radius <= inner_radius: + raise ValueError("outer_radius must be greater than inner_radius") + return pi * (pow(outer_radius, 2) - pow(inner_radius, 2)) * height + + +def vol_conical_frustum(height: float, radius_1: float, radius_2: float) -> float: """Calculate the Volume of a Conical Frustum. Wikipedia reference: https://en.wikipedia.org/wiki/Frustum :return 1/3 * pi * height * (radius_1^2 + radius_top^2 + radius_1 * radius_2) - >>> vol_conical_frustum(45, 7, 28) 48490.482608158454 - >>> vol_conical_frustum(1, 1, 2) 7.330382858376184 + >>> vol_conical_frustum(1.6, 2.6, 3.6) + 48.7240076620753 + >>> vol_conical_frustum(0, 0, 0) + 0.0 + >>> vol_conical_frustum(-2, 2, 1) + Traceback (most recent call last): + ... + ValueError: vol_conical_frustum() only accepts non-negative values + >>> vol_conical_frustum(2, -2, 1) + Traceback (most recent call last): + ... + ValueError: vol_conical_frustum() only accepts non-negative values + >>> vol_conical_frustum(2, 2, -1) + Traceback (most recent call last): + ... + ValueError: vol_conical_frustum() only accepts non-negative values """ + if radius_1 < 0 or radius_2 < 0 or height < 0: + raise ValueError("vol_conical_frustum() only accepts non-negative values") return ( 1 / 3 @@ -204,18 +392,21 @@ def vol_conical_frustum(height: float, radius_1: float, radius_2: float): def main(): """Print the Results of Various Volume Calculations.""" print("Volumes:") - print("Cube: " + str(vol_cube(2))) # = 8 - print("Cuboid: " + str(vol_cuboid(2, 2, 2))) # = 8 - print("Cone: " + str(vol_cone(2, 2))) # ~= 1.33 - print("Right Circular Cone: " + str(vol_right_circ_cone(2, 2))) # ~= 8.38 - print("Prism: " + str(vol_prism(2, 2))) # = 4 - print("Pyramid: " + str(vol_pyramid(2, 2))) # ~= 1.33 - print("Sphere: " + str(vol_sphere(2))) # ~= 33.5 - print("Hemisphere: " + str(vol_hemisphere(2))) # ~= 16.75 - print("Circular Cylinder: " + str(vol_circular_cylinder(2, 2))) # ~= 25.1 - print("Conical Frustum: " + str(vol_conical_frustum(2, 2, 4))) # ~= 58.6 - print("Spherical cap: " + str(vol_spherical_cap(1, 2))) # ~= 5.24 - print("Spheres intersetion: " + str(vol_spheres_intersect(2, 2, 1))) # ~= 21.21 + print(f"Cube: {vol_cube(2) = }") # = 8 + print(f"Cuboid: {vol_cuboid(2, 2, 2) = }") # = 8 + print(f"Cone: {vol_cone(2, 2) = }") # ~= 1.33 + print(f"Right Circular Cone: {vol_right_circ_cone(2, 2) = }") # ~= 8.38 + print(f"Prism: {vol_prism(2, 2) = }") # = 4 + print(f"Pyramid: {vol_pyramid(2, 2) = }") # ~= 1.33 + print(f"Sphere: {vol_sphere(2) = }") # ~= 33.5 + print(f"Hemisphere: {vol_hemisphere(2) = }") # ~= 16.75 + print(f"Circular Cylinder: {vol_circular_cylinder(2, 2) = }") # ~= 25.1 + print( + f"Hollow Circular Cylinder: {vol_hollow_circular_cylinder(1, 2, 3) = }" + ) # ~= 28.3 + print(f"Conical Frustum: {vol_conical_frustum(2, 2, 4) = }") # ~= 58.6 + print(f"Spherical cap: {vol_spherical_cap(1, 2) = }") # ~= 5.24 + print(f"Spheres intersetion: {vol_spheres_intersect(2, 2, 1) = }") # ~= 21.21 if __name__ == "__main__": From 2423760e1d28b4c6860ef63f83b1e6b4b83c1522 Mon Sep 17 00:00:00 2001 From: Saksham Chawla <51916697+saksham-chawla@users.noreply.github.com> Date: Thu, 13 Oct 2022 00:11:01 +0530 Subject: [PATCH 343/726] Add typing to maths/abs.py (#7060) --- maths/abs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths/abs.py b/maths/abs.py index 68c99a1d5..dfea52dfb 100644 --- a/maths/abs.py +++ b/maths/abs.py @@ -1,7 +1,7 @@ """Absolute Value.""" -def abs_val(num): +def abs_val(num: float) -> float: """ Find the absolute value of a number. From 74494d433f8d050d37642f912f616451f40d65e6 Mon Sep 17 00:00:00 2001 From: Saksham Chawla <51916697+saksham-chawla@users.noreply.github.com> Date: Thu, 13 Oct 2022 00:11:52 +0530 Subject: [PATCH 344/726] Add typing to maths/ceil.py (#7057) --- maths/ceil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths/ceil.py b/maths/ceil.py index 97578265c..909e02b3f 100644 --- a/maths/ceil.py +++ b/maths/ceil.py @@ -3,7 +3,7 @@ https://en.wikipedia.org/wiki/Floor_and_ceiling_functions """ -def ceil(x) -> int: +def ceil(x: float) -> int: """ Return the ceiling of x as an Integral. From 32ff33648e0d1f93398db34fd271aa6606abc3a4 Mon Sep 17 00:00:00 2001 From: Saksham Chawla <51916697+saksham-chawla@users.noreply.github.com> Date: Thu, 13 Oct 2022 00:12:30 +0530 Subject: [PATCH 345/726] Add typing to maths/floor.py (#7056) --- maths/floor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths/floor.py b/maths/floor.py index 482250f5e..8bbcb21aa 100644 --- a/maths/floor.py +++ b/maths/floor.py @@ -3,7 +3,7 @@ https://en.wikipedia.org/wiki/Floor_and_ceiling_functions """ -def floor(x) -> int: +def floor(x: float) -> int: """ Return the floor of x as an Integral. :param x: the number From 467ade28a04ed3e77b6c89542fd99f390139b5bd Mon Sep 17 00:00:00 2001 From: Rohan R Bharadwaj <114707091+rohanr18@users.noreply.github.com> Date: Thu, 13 Oct 2022 00:18:49 +0530 Subject: [PATCH 346/726] Add surface area of cuboid, conical frustum (#6442) * Add surface area of cuboid, conical frustum * add tests for floats, zeroes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/area.py | 131 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 116 insertions(+), 15 deletions(-) diff --git a/maths/area.py b/maths/area.py index b1b139cf4..abbf7aa85 100644 --- a/maths/area.py +++ b/maths/area.py @@ -7,9 +7,12 @@ from math import pi, sqrt def surface_area_cube(side_length: float) -> float: """ Calculate the Surface Area of a Cube. - >>> surface_area_cube(1) 6 + >>> surface_area_cube(1.6) + 15.360000000000003 + >>> surface_area_cube(0) + 0 >>> surface_area_cube(3) 54 >>> surface_area_cube(-1) @@ -22,16 +25,46 @@ def surface_area_cube(side_length: float) -> float: return 6 * side_length**2 +def surface_area_cuboid(length: float, breadth: float, height: float) -> float: + """ + Calculate the Surface Area of a Cuboid. + >>> surface_area_cuboid(1, 2, 3) + 22 + >>> surface_area_cuboid(0, 0, 0) + 0 + >>> surface_area_cuboid(1.6, 2.6, 3.6) + 38.56 + >>> surface_area_cuboid(-1, 2, 3) + Traceback (most recent call last): + ... + ValueError: surface_area_cuboid() only accepts non-negative values + >>> surface_area_cuboid(1, -2, 3) + Traceback (most recent call last): + ... + ValueError: surface_area_cuboid() only accepts non-negative values + >>> surface_area_cuboid(1, 2, -3) + Traceback (most recent call last): + ... + ValueError: surface_area_cuboid() only accepts non-negative values + """ + if length < 0 or breadth < 0 or height < 0: + raise ValueError("surface_area_cuboid() only accepts non-negative values") + return 2 * ((length * breadth) + (breadth * height) + (length * height)) + + def surface_area_sphere(radius: float) -> float: """ Calculate the Surface Area of a Sphere. Wikipedia reference: https://en.wikipedia.org/wiki/Sphere Formula: 4 * pi * r^2 - >>> surface_area_sphere(5) 314.1592653589793 >>> surface_area_sphere(1) 12.566370614359172 + >>> surface_area_sphere(1.6) + 32.169908772759484 + >>> surface_area_sphere(0) + 0.0 >>> surface_area_sphere(-1) Traceback (most recent call last): ... @@ -46,7 +79,6 @@ def surface_area_hemisphere(radius: float) -> float: """ Calculate the Surface Area of a Hemisphere. Formula: 3 * pi * r^2 - >>> surface_area_hemisphere(5) 235.61944901923448 >>> surface_area_hemisphere(1) @@ -70,11 +102,14 @@ def surface_area_cone(radius: float, height: float) -> float: Calculate the Surface Area of a Cone. Wikipedia reference: https://en.wikipedia.org/wiki/Cone Formula: pi * r * (r + (h ** 2 + r ** 2) ** 0.5) - >>> surface_area_cone(10, 24) 1130.9733552923256 >>> surface_area_cone(6, 8) 301.59289474462014 + >>> surface_area_cone(1.6, 2.6) + 23.387862992395807 + >>> surface_area_cone(0, 0) + 0.0 >>> surface_area_cone(-1, -2) Traceback (most recent call last): ... @@ -93,14 +128,51 @@ def surface_area_cone(radius: float, height: float) -> float: return pi * radius * (radius + (height**2 + radius**2) ** 0.5) +def surface_area_conical_frustum( + radius_1: float, radius_2: float, height: float +) -> float: + """ + Calculate the Surface Area of a Conical Frustum. + >>> surface_area_conical_frustum(1, 2, 3) + 45.511728065337266 + >>> surface_area_conical_frustum(4, 5, 6) + 300.7913575056268 + >>> surface_area_conical_frustum(0, 0, 0) + 0.0 + >>> surface_area_conical_frustum(1.6, 2.6, 3.6) + 78.57907060751548 + >>> surface_area_conical_frustum(-1, 2, 3) + Traceback (most recent call last): + ... + ValueError: surface_area_conical_frustum() only accepts non-negative values + >>> surface_area_conical_frustum(1, -2, 3) + Traceback (most recent call last): + ... + ValueError: surface_area_conical_frustum() only accepts non-negative values + >>> surface_area_conical_frustum(1, 2, -3) + Traceback (most recent call last): + ... + ValueError: surface_area_conical_frustum() only accepts non-negative values + """ + if radius_1 < 0 or radius_2 < 0 or height < 0: + raise ValueError( + "surface_area_conical_frustum() only accepts non-negative values" + ) + slant_height = (height**2 + (radius_1 - radius_2) ** 2) ** 0.5 + return pi * ((slant_height * (radius_1 + radius_2)) + radius_1**2 + radius_2**2) + + def surface_area_cylinder(radius: float, height: float) -> float: """ Calculate the Surface Area of a Cylinder. Wikipedia reference: https://en.wikipedia.org/wiki/Cylinder Formula: 2 * pi * r * (h + r) - >>> surface_area_cylinder(7, 10) 747.6990515543707 + >>> surface_area_cylinder(1.6, 2.6) + 42.22300526424682 + >>> surface_area_cylinder(0, 0) + 0.0 >>> surface_area_cylinder(6, 8) 527.7875658030853 >>> surface_area_cylinder(-1, -2) @@ -124,9 +196,12 @@ def surface_area_cylinder(radius: float, height: float) -> float: def area_rectangle(length: float, width: float) -> float: """ Calculate the area of a rectangle. - >>> area_rectangle(10, 20) 200 + >>> area_rectangle(1.6, 2.6) + 4.16 + >>> area_rectangle(0, 0) + 0 >>> area_rectangle(-1, -2) Traceback (most recent call last): ... @@ -148,9 +223,12 @@ def area_rectangle(length: float, width: float) -> float: def area_square(side_length: float) -> float: """ Calculate the area of a square. - >>> area_square(10) 100 + >>> area_square(0) + 0 + >>> area_square(1.6) + 2.5600000000000005 >>> area_square(-1) Traceback (most recent call last): ... @@ -164,9 +242,12 @@ def area_square(side_length: float) -> float: def area_triangle(base: float, height: float) -> float: """ Calculate the area of a triangle given the base and height. - >>> area_triangle(10, 10) 50.0 + >>> area_triangle(1.6, 2.6) + 2.08 + >>> area_triangle(0, 0) + 0.0 >>> area_triangle(-1, -2) Traceback (most recent call last): ... @@ -188,13 +269,15 @@ def area_triangle(base: float, height: float) -> float: def area_triangle_three_sides(side1: float, side2: float, side3: float) -> float: """ Calculate area of triangle when the length of 3 sides are known. - This function uses Heron's formula: https://en.wikipedia.org/wiki/Heron%27s_formula - >>> area_triangle_three_sides(5, 12, 13) 30.0 >>> area_triangle_three_sides(10, 11, 12) 51.521233486786784 + >>> area_triangle_three_sides(0, 0, 0) + 0.0 + >>> area_triangle_three_sides(1.6, 2.6, 3.6) + 1.8703742940919619 >>> area_triangle_three_sides(-1, -2, -1) Traceback (most recent call last): ... @@ -233,9 +316,12 @@ def area_triangle_three_sides(side1: float, side2: float, side3: float) -> float def area_parallelogram(base: float, height: float) -> float: """ Calculate the area of a parallelogram. - >>> area_parallelogram(10, 20) 200 + >>> area_parallelogram(1.6, 2.6) + 4.16 + >>> area_parallelogram(0, 0) + 0 >>> area_parallelogram(-1, -2) Traceback (most recent call last): ... @@ -257,9 +343,12 @@ def area_parallelogram(base: float, height: float) -> float: def area_trapezium(base1: float, base2: float, height: float) -> float: """ Calculate the area of a trapezium. - >>> area_trapezium(10, 20, 30) 450.0 + >>> area_trapezium(1.6, 2.6, 3.6) + 7.5600000000000005 + >>> area_trapezium(0, 0, 0) + 0.0 >>> area_trapezium(-1, -2, -3) Traceback (most recent call last): ... @@ -297,9 +386,12 @@ def area_trapezium(base1: float, base2: float, height: float) -> float: def area_circle(radius: float) -> float: """ Calculate the area of a circle. - >>> area_circle(20) 1256.6370614359173 + >>> area_circle(1.6) + 8.042477193189871 + >>> area_circle(0) + 0.0 >>> area_circle(-1) Traceback (most recent call last): ... @@ -313,11 +405,14 @@ def area_circle(radius: float) -> float: def area_ellipse(radius_x: float, radius_y: float) -> float: """ Calculate the area of a ellipse. - >>> area_ellipse(10, 10) 314.1592653589793 >>> area_ellipse(10, 20) 628.3185307179587 + >>> area_ellipse(0, 0) + 0.0 + >>> area_ellipse(1.6, 2.6) + 13.06902543893354 >>> area_ellipse(-10, 20) Traceback (most recent call last): ... @@ -339,9 +434,12 @@ def area_ellipse(radius_x: float, radius_y: float) -> float: def area_rhombus(diagonal_1: float, diagonal_2: float) -> float: """ Calculate the area of a rhombus. - >>> area_rhombus(10, 20) 100.0 + >>> area_rhombus(1.6, 2.6) + 2.08 + >>> area_rhombus(0, 0) + 0.0 >>> area_rhombus(-1, -2) Traceback (most recent call last): ... @@ -374,9 +472,12 @@ if __name__ == "__main__": print(f"Rhombus: {area_rhombus(10, 20) = }") print(f"Trapezium: {area_trapezium(10, 20, 30) = }") print(f"Circle: {area_circle(20) = }") + print(f"Ellipse: {area_ellipse(10, 20) = }") print("\nSurface Areas of various geometric shapes: \n") print(f"Cube: {surface_area_cube(20) = }") + print(f"Cuboid: {surface_area_cuboid(10, 20, 30) = }") print(f"Sphere: {surface_area_sphere(20) = }") print(f"Hemisphere: {surface_area_hemisphere(20) = }") print(f"Cone: {surface_area_cone(10, 20) = }") + print(f"Conical Frustum: {surface_area_conical_frustum(10, 20, 30) = }") print(f"Cylinder: {surface_area_cylinder(10, 20) = }") From c0c230255ffe79946bd959ecb559696353ac33f2 Mon Sep 17 00:00:00 2001 From: Eeman Majumder <54275491+Eeman1113@users.noreply.github.com> Date: Thu, 13 Oct 2022 01:13:52 +0530 Subject: [PATCH 347/726] added self organising maps algorithm in the machine learning section. (#6877) * added self organising maps algo * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update machine_learning/Self_Organising_Maps.py * Update and rename Self_Organising_Maps.py to self_organizing_map.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update self_organizing_map.py * Update self_organizing_map.py * Update self_organizing_map.py * Update self_organizing_map.py Co-authored-by: Eeman Majumder Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- machine_learning/self_organizing_map.py | 73 +++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 machine_learning/self_organizing_map.py diff --git a/machine_learning/self_organizing_map.py b/machine_learning/self_organizing_map.py new file mode 100644 index 000000000..bd3d388f9 --- /dev/null +++ b/machine_learning/self_organizing_map.py @@ -0,0 +1,73 @@ +""" +https://en.wikipedia.org/wiki/Self-organizing_map +""" +import math + + +class SelfOrganizingMap: + def get_winner(self, weights: list[list[float]], sample: list[int]) -> int: + """ + Compute the winning vector by Euclidean distance + + >>> SelfOrganizingMap().get_winner([[1, 2, 3], [4, 5, 6]], [1, 2, 3]) + 1 + """ + d0 = 0.0 + d1 = 0.0 + for i in range(len(sample)): + d0 += math.pow((sample[i] - weights[0][i]), 2) + d1 += math.pow((sample[i] - weights[1][i]), 2) + return 0 if d0 > d1 else 1 + return 0 + + def update( + self, weights: list[list[int | float]], sample: list[int], j: int, alpha: float + ) -> list[list[int | float]]: + """ + Update the winning vector. + + >>> SelfOrganizingMap().update([[1, 2, 3], [4, 5, 6]], [1, 2, 3], 1, 0.1) + [[1, 2, 3], [3.7, 4.7, 6]] + """ + for i in range(len(weights)): + weights[j][i] += alpha * (sample[i] - weights[j][i]) + return weights + + +# Driver code +def main() -> None: + # Training Examples ( m, n ) + training_samples = [[1, 1, 0, 0], [0, 0, 0, 1], [1, 0, 0, 0], [0, 0, 1, 1]] + + # weight initialization ( n, C ) + weights = [[0.2, 0.6, 0.5, 0.9], [0.8, 0.4, 0.7, 0.3]] + + # training + self_organizing_map = SelfOrganizingMap() + epochs = 3 + alpha = 0.5 + + for i in range(epochs): + for j in range(len(training_samples)): + + # training sample + sample = training_samples[j] + + # Compute the winning vector + winner = self_organizing_map.get_winner(weights, sample) + + # Update the winning vector + weights = self_organizing_map.update(weights, sample, winner, alpha) + + # classify test sample + sample = [0, 0, 0, 1] + winner = self_organizing_map.get_winner(weights, sample) + + # results + print(f"Clusters that the test sample belongs to : {winner}") + print(f"Weights that have been trained : {weights}") + + +# running the main() function +if __name__ == "__main__": + main() From bae08adc86c44268faaa0fe05ea0f2f91567ac9a Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 12 Oct 2022 21:56:07 +0200 Subject: [PATCH 348/726] README.md: Lose LGTM badge because we don't use it (#7063) * README.md: Lose LGTM badge because we don't use it * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 2 ++ README.md | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 9ef72c403..25272af4a 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -14,6 +14,7 @@ ## Audio Filters * [Butterworth Filter](audio_filters/butterworth_filter.py) + * [Equal Loudness Filter](audio_filters/equal_loudness_filter.py) * [Iir Filter](audio_filters/iir_filter.py) * [Show Response](audio_filters/show_response.py) @@ -475,6 +476,7 @@ * [Binomial Coefficient](maths/binomial_coefficient.py) * [Binomial Distribution](maths/binomial_distribution.py) * [Bisection](maths/bisection.py) + * [Carmichael Number](maths/carmichael_number.py) * [Catalan Number](maths/catalan_number.py) * [Ceil](maths/ceil.py) * [Check Polygon](maths/check_polygon.py) diff --git a/README.md b/README.md index c78797960..c499c14e1 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,6 @@ GitHub Workflow Status - - LGTM - pre-commit From e2cd982b1154814debe2960498ccbb29d4829bf7 Mon Sep 17 00:00:00 2001 From: VARISH GAUTAM <48176176+Variiiest@users.noreply.github.com> Date: Thu, 13 Oct 2022 02:12:02 +0530 Subject: [PATCH 349/726] Weird numbers (#6871) * Create weird_number.py In number theory, a weird number is a natural number that is abundant but not semiperfect * check * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * resolved * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * removed * Update weird_number.py * Update weird_number.py * Update weird_number.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- maths/weird_number.py | 100 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 maths/weird_number.py diff --git a/maths/weird_number.py b/maths/weird_number.py new file mode 100644 index 000000000..2834a9fee --- /dev/null +++ b/maths/weird_number.py @@ -0,0 +1,100 @@ +""" +https://en.wikipedia.org/wiki/Weird_number + +Fun fact: The set of weird numbers has positive asymptotic density. +""" +from math import sqrt + + +def factors(number: int) -> list[int]: + """ + >>> factors(12) + [1, 2, 3, 4, 6] + >>> factors(1) + [1] + >>> factors(100) + [1, 2, 4, 5, 10, 20, 25, 50] + + # >>> factors(-12) + # [1, 2, 3, 4, 6] + """ + + values = [1] + for i in range(2, int(sqrt(number)) + 1, 1): + if number % i == 0: + values.append(i) + if int(number // i) != i: + values.append(int(number // i)) + return sorted(values) + + +def abundant(n: int) -> bool: + """ + >>> abundant(0) + True + >>> abundant(1) + False + >>> abundant(12) + True + >>> abundant(13) + False + >>> abundant(20) + True + + # >>> abundant(-12) + # True + """ + return sum(factors(n)) > n + + +def semi_perfect(number: int) -> bool: + """ + >>> semi_perfect(0) + True + >>> semi_perfect(1) + True + >>> semi_perfect(12) + True + >>> semi_perfect(13) + False + + # >>> semi_perfect(-12) + # True + """ + values = factors(number) + r = len(values) + subset = [[0 for i in range(number + 1)] for j in range(r + 1)] + for i in range(r + 1): + subset[i][0] = True + + for i in range(1, number + 1): + subset[0][i] = False + + for i in range(1, r + 1): + for j in range(1, number + 1): + if j < values[i - 1]: + subset[i][j] = subset[i - 1][j] + else: + subset[i][j] = subset[i - 1][j] or subset[i - 1][j - values[i - 1]] + + return subset[r][number] != 0 + + +def weird(number: int) -> bool: + """ + >>> weird(0) + False + >>> weird(70) + True + >>> weird(77) + False + """ + return abundant(number) and not semi_perfect(number) + + +if __name__ == "__main__": + import doctest + + doctest.testmod(verbose=True) + for number in (69, 70, 71): + print(f"{number} is {'' if weird(number) else 'not '}weird.") From 07e991d55330bf1363ba53858a98cf6fd8d45026 Mon Sep 17 00:00:00 2001 From: Caeden Date: Wed, 12 Oct 2022 23:54:20 +0100 Subject: [PATCH 350/726] Add pep8-naming to pre-commit hooks and fixes incorrect naming conventions (#7062) * ci(pre-commit): Add pep8-naming to `pre-commit` hooks (#7038) * refactor: Fix naming conventions (#7038) * Update arithmetic_analysis/lu_decomposition.py Co-authored-by: Christian Clauss * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * refactor(lu_decomposition): Replace `NDArray` with `ArrayLike` (#7038) * chore: Fix naming conventions in doctests (#7038) * fix: Temporarily disable project euler problem 104 (#7069) * chore: Fix naming conventions in doctests (#7038) Co-authored-by: Christian Clauss Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 1 + arithmetic_analysis/lu_decomposition.py | 6 +- backtracking/n_queens.py | 4 +- ciphers/affine_cipher.py | 52 ++--- ciphers/bifid.py | 2 +- ciphers/brute_force_caesar_cipher.py | 2 +- ciphers/elgamal_key_generator.py | 10 +- ciphers/hill_cipher.py | 4 +- ciphers/polybius.py | 2 +- ciphers/rabin_miller.py | 14 +- ciphers/rsa_cipher.py | 14 +- ciphers/rsa_factorization.py | 10 +- ciphers/rsa_key_generator.py | 28 +-- ciphers/simple_substitution_cipher.py | 48 ++--- ciphers/trafid_cipher.py | 56 +++--- ciphers/transposition_cipher.py | 36 ++-- ...ansposition_cipher_encrypt_decrypt_file.py | 32 +-- ciphers/vigenere_cipher.py | 30 +-- compression/lempel_ziv_decompress.py | 6 +- compression/peak_signal_to_noise_ratio.py | 4 +- computer_vision/harris_corner.py | 4 +- conversions/binary_to_hexadecimal.py | 2 +- conversions/decimal_to_any.py | 2 +- conversions/prefix_conversions.py | 32 +-- conversions/roman_numerals.py | 2 +- data_structures/binary_tree/avl_tree.py | 42 ++-- .../binary_tree/lazy_segment_tree.py | 8 +- data_structures/binary_tree/segment_tree.py | 14 +- data_structures/binary_tree/treap.py | 16 +- data_structures/heap/min_heap.py | 22 +- .../stacks/infix_to_prefix_conversion.py | 60 +++--- data_structures/stacks/postfix_evaluation.py | 38 ++-- data_structures/stacks/stock_span_problem.py | 12 +- .../edge_detection/canny.py | 24 +-- .../filters/bilateral_filter.py | 18 +- .../histogram_stretch.py | 12 +- digital_image_processing/index_calculation.py | 190 +++++++++--------- .../test_digital_image_processing.py | 4 +- divide_and_conquer/inversions.py | 34 ++-- dynamic_programming/bitmask.py | 12 +- dynamic_programming/edit_distance.py | 34 ++-- dynamic_programming/floyd_warshall.py | 46 ++--- dynamic_programming/fractional_knapsack.py | 8 +- dynamic_programming/knapsack.py | 34 ++-- .../longest_common_subsequence.py | 10 +- .../longest_increasing_subsequence.py | 6 +- ...longest_increasing_subsequence_o(nlogn).py | 16 +- dynamic_programming/matrix_chain_order.py | 38 ++-- dynamic_programming/max_sub_array.py | 16 +- dynamic_programming/minimum_coin_change.py | 4 +- dynamic_programming/minimum_partition.py | 2 +- dynamic_programming/sum_of_subset.py | 18 +- fractals/sierpinski_triangle.py | 28 +-- geodesy/haversine_distance.py | 6 +- geodesy/lamberts_ellipsoidal_distance.py | 24 +-- graphs/articulation_points.py | 30 +-- graphs/basic_graphs.py | 78 +++---- graphs/check_bipartite_graph_bfs.py | 4 +- graphs/dijkstra.py | 12 +- graphs/dijkstra_2.py | 36 ++-- graphs/dijkstra_algorithm.py | 14 +- .../edmonds_karp_multiple_source_and_sink.py | 161 +++++++-------- ...n_path_and_circuit_for_undirected_graph.py | 20 +- graphs/frequent_pattern_graph_miner.py | 28 +-- graphs/kahns_algorithm_long.py | 12 +- graphs/kahns_algorithm_topo.py | 4 +- graphs/minimum_spanning_tree_prims.py | 48 ++--- graphs/multi_heuristic_astar.py | 12 +- graphs/scc_kosaraju.py | 12 +- graphs/tests/test_min_spanning_tree_prim.py | 2 +- hashes/adler32.py | 2 +- hashes/chaos_machine.py | 16 +- hashes/hamming_code.py | 170 ++++++++-------- hashes/md5.py | 90 ++++----- hashes/sha1.py | 2 +- hashes/sha256.py | 8 +- linear_algebra/src/power_iteration.py | 4 +- linear_algebra/src/rayleigh_quotient.py | 16 +- linear_algebra/src/test_linear_algebra.py | 60 +++--- machine_learning/decision_tree.py | 54 ++--- machine_learning/gaussian_naive_bayes.py | 12 +- .../gradient_boosting_regressor.py | 14 +- machine_learning/k_means_clust.py | 16 +- .../local_weighted_learning.py | 4 +- machine_learning/logistic_regression.py | 36 ++-- .../multilayer_perceptron_classifier.py | 4 +- machine_learning/random_forest_classifier.py | 6 +- machine_learning/random_forest_regressor.py | 6 +- .../sequential_minimum_optimization.py | 64 +++--- machine_learning/word_frequency_functions.py | 10 +- maths/binomial_coefficient.py | 8 +- maths/carmichael_number.py | 4 +- maths/decimal_isolate.py | 6 +- maths/euler_method.py | 6 +- maths/euler_modified.py | 6 +- maths/hardy_ramanujanalgo.py | 6 +- maths/jaccard_similarity.py | 48 ++--- maths/krishnamurthy_number.py | 6 +- maths/kth_lexicographic_permutation.py | 6 +- maths/lucas_lehmer_primality_test.py | 4 +- maths/primelib.py | 140 ++++++------- maths/qr_decomposition.py | 20 +- maths/radix2_fft.py | 72 +++---- maths/runge_kutta.py | 6 +- maths/softmax.py | 6 +- matrix/count_islands_in_matrix.py | 10 +- matrix/inverse_of_matrix.py | 6 +- matrix/sherman_morrison.py | 26 +-- networking_flow/ford_fulkerson.py | 8 +- networking_flow/minimum_cut.py | 4 +- neural_network/convolution_neural_network.py | 6 +- other/davisb_putnamb_logemannb_loveland.py | 36 ++-- other/greedy.py | 38 ++-- other/nested_brackets.py | 12 +- other/sdes.py | 8 +- other/tower_of_hanoi.py | 14 +- physics/n_body_simulation.py | 6 +- project_euler/problem_011/sol1.py | 30 +-- project_euler/problem_012/sol1.py | 16 +- project_euler/problem_023/sol1.py | 8 +- project_euler/problem_029/sol1.py | 16 +- project_euler/problem_032/sol32.py | 8 +- project_euler/problem_042/solution42.py | 4 +- project_euler/problem_054/test_poker_hand.py | 2 +- project_euler/problem_064/sol1.py | 2 +- project_euler/problem_097/sol1.py | 4 +- .../problem_104/{sol.py => sol.py.FIXME} | 0 project_euler/problem_125/sol1.py | 2 +- .../non_preemptive_shortest_job_first.py | 4 +- searches/tabu_search.py | 4 +- sorts/odd_even_transposition_parallel.py | 92 ++++----- sorts/radix_sort.py | 2 +- sorts/random_normal_distribution_quicksort.py | 44 ++-- sorts/random_pivot_quick_sort.py | 24 +-- sorts/tree_sort.py | 8 +- strings/boyer_moore_search.py | 8 +- .../can_string_be_rearranged_as_palindrome.py | 6 +- strings/check_anagrams.py | 8 +- strings/word_patterns.py | 8 +- web_programming/fetch_quotes.py | 4 +- 140 files changed, 1552 insertions(+), 1536 deletions(-) rename project_euler/problem_104/{sol.py => sol.py.FIXME} (100%) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0abe647b0..2f6a92814 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,6 +40,7 @@ repos: - --ignore=E203,W503 - --max-complexity=25 - --max-line-length=88 + additional_dependencies: [pep8-naming] - repo: https://github.com/pre-commit/mirrors-mypy rev: v0.982 diff --git a/arithmetic_analysis/lu_decomposition.py b/arithmetic_analysis/lu_decomposition.py index 371f7b166..1e98b9066 100644 --- a/arithmetic_analysis/lu_decomposition.py +++ b/arithmetic_analysis/lu_decomposition.py @@ -6,13 +6,13 @@ Reference: from __future__ import annotations import numpy as np -import numpy.typing as NDArray from numpy import float64 +from numpy.typing import ArrayLike def lower_upper_decomposition( - table: NDArray[float64], -) -> tuple[NDArray[float64], NDArray[float64]]: + table: ArrayLike[float64], +) -> tuple[ArrayLike[float64], ArrayLike[float64]]: """Lower-Upper (LU) Decomposition Example: diff --git a/backtracking/n_queens.py b/backtracking/n_queens.py index b8ace5978..bbf0ce44f 100644 --- a/backtracking/n_queens.py +++ b/backtracking/n_queens.py @@ -12,7 +12,7 @@ from __future__ import annotations solution = [] -def isSafe(board: list[list[int]], row: int, column: int) -> bool: +def is_safe(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. @@ -63,7 +63,7 @@ def solve(board: list[list[int]], row: int) -> bool: If all the combinations for that particular branch are successful the board is reinitialized for the next possible combination. """ - if isSafe(board, row, i): + if is_safe(board, row, i): board[row][i] = 1 solve(board, row + 1) board[row][i] = 0 diff --git a/ciphers/affine_cipher.py b/ciphers/affine_cipher.py index d3b806ba1..cd1e33b88 100644 --- a/ciphers/affine_cipher.py +++ b/ciphers/affine_cipher.py @@ -9,26 +9,26 @@ SYMBOLS = ( ) -def check_keys(keyA: int, keyB: int, mode: str) -> None: +def check_keys(key_a: int, key_b: int, mode: str) -> None: if mode == "encrypt": - if keyA == 1: + if key_a == 1: sys.exit( "The affine cipher becomes weak when key " "A is set to 1. Choose different key" ) - if keyB == 0: + if key_b == 0: sys.exit( "The affine cipher becomes weak when key " "B is set to 0. Choose different key" ) - if keyA < 0 or keyB < 0 or keyB > len(SYMBOLS) - 1: + if key_a < 0 or key_b < 0 or key_b > len(SYMBOLS) - 1: sys.exit( "Key A must be greater than 0 and key B must " f"be between 0 and {len(SYMBOLS) - 1}." ) - if cryptomath.gcd(keyA, len(SYMBOLS)) != 1: + if cryptomath.gcd(key_a, len(SYMBOLS)) != 1: sys.exit( - f"Key A {keyA} and the symbol set size {len(SYMBOLS)} " + f"Key A {key_a} and the symbol set size {len(SYMBOLS)} " "are not relatively prime. Choose a different key." ) @@ -39,16 +39,16 @@ def encrypt_message(key: int, message: str) -> str: ... 'substitution cipher.') 'VL}p MM{I}p~{HL}Gp{vp pFsH}pxMpyxIx JHL O}F{~pvuOvF{FuF{xIp~{HL}Gi' """ - keyA, keyB = divmod(key, len(SYMBOLS)) - check_keys(keyA, keyB, "encrypt") - cipherText = "" + key_a, key_b = divmod(key, len(SYMBOLS)) + check_keys(key_a, key_b, "encrypt") + cipher_text = "" for symbol in message: if symbol in SYMBOLS: - symIndex = SYMBOLS.find(symbol) - cipherText += SYMBOLS[(symIndex * keyA + keyB) % len(SYMBOLS)] + sym_index = SYMBOLS.find(symbol) + cipher_text += SYMBOLS[(sym_index * key_a + key_b) % len(SYMBOLS)] else: - cipherText += symbol - return cipherText + cipher_text += symbol + return cipher_text def decrypt_message(key: int, message: str) -> str: @@ -57,25 +57,27 @@ def decrypt_message(key: int, message: str) -> str: ... '{xIp~{HL}Gi') 'The affine cipher is a type of monoalphabetic substitution cipher.' """ - keyA, keyB = divmod(key, len(SYMBOLS)) - check_keys(keyA, keyB, "decrypt") - plainText = "" - modInverseOfkeyA = cryptomath.find_mod_inverse(keyA, len(SYMBOLS)) + key_a, key_b = divmod(key, len(SYMBOLS)) + check_keys(key_a, key_b, "decrypt") + plain_text = "" + mod_inverse_of_key_a = cryptomath.find_mod_inverse(key_a, len(SYMBOLS)) for symbol in message: if symbol in SYMBOLS: - symIndex = SYMBOLS.find(symbol) - plainText += SYMBOLS[(symIndex - keyB) * modInverseOfkeyA % len(SYMBOLS)] + sym_index = SYMBOLS.find(symbol) + plain_text += SYMBOLS[ + (sym_index - key_b) * mod_inverse_of_key_a % len(SYMBOLS) + ] else: - plainText += symbol - return plainText + plain_text += symbol + return plain_text def get_random_key() -> int: while True: - keyA = random.randint(2, len(SYMBOLS)) - keyB = random.randint(2, len(SYMBOLS)) - if cryptomath.gcd(keyA, len(SYMBOLS)) == 1 and keyB % len(SYMBOLS) != 0: - return keyA * len(SYMBOLS) + keyB + key_b = random.randint(2, len(SYMBOLS)) + key_b = random.randint(2, len(SYMBOLS)) + if cryptomath.gcd(key_b, len(SYMBOLS)) == 1 and key_b % len(SYMBOLS) != 0: + return key_b * len(SYMBOLS) + key_b def main() -> None: diff --git a/ciphers/bifid.py b/ciphers/bifid.py index c1b071155..54d55574c 100644 --- a/ciphers/bifid.py +++ b/ciphers/bifid.py @@ -12,7 +12,7 @@ import numpy as np class BifidCipher: def __init__(self) -> None: - SQUARE = [ + SQUARE = [ # noqa: N806 ["a", "b", "c", "d", "e"], ["f", "g", "h", "i", "k"], ["l", "m", "n", "o", "p"], diff --git a/ciphers/brute_force_caesar_cipher.py b/ciphers/brute_force_caesar_cipher.py index 8ab6e7730..cc97111e0 100644 --- a/ciphers/brute_force_caesar_cipher.py +++ b/ciphers/brute_force_caesar_cipher.py @@ -28,7 +28,7 @@ def decrypt(message: str) -> None: Decryption using Key #24: VOFGVWZ ROFXW Decryption using Key #25: UNEFUVY QNEWV """ - LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" # noqa: N806 for key in range(len(LETTERS)): translated = "" for symbol in message: diff --git a/ciphers/elgamal_key_generator.py b/ciphers/elgamal_key_generator.py index 485b77595..4d72128ae 100644 --- a/ciphers/elgamal_key_generator.py +++ b/ciphers/elgamal_key_generator.py @@ -26,7 +26,7 @@ def primitive_root(p_val: int) -> int: def generate_key(key_size: int) -> tuple[tuple[int, int, int, int], tuple[int, int]]: print("Generating prime p...") - p = rabin_miller.generateLargePrime(key_size) # select large prime number. + p = rabin_miller.generate_large_prime(key_size) # select large prime number. e_1 = primitive_root(p) # one primitive root on modulo p. d = random.randrange(3, p) # private_key -> have to be greater than 2 for safety. e_2 = cryptomath.find_mod_inverse(pow(e_1, d, p), p) @@ -37,7 +37,7 @@ def generate_key(key_size: int) -> tuple[tuple[int, int, int, int], tuple[int, i return public_key, private_key -def make_key_files(name: str, keySize: int) -> None: +def make_key_files(name: str, key_size: int) -> None: if os.path.exists(f"{name}_pubkey.txt") or os.path.exists(f"{name}_privkey.txt"): print("\nWARNING:") print( @@ -47,16 +47,16 @@ def make_key_files(name: str, keySize: int) -> None: ) sys.exit() - publicKey, privateKey = generate_key(keySize) + public_key, private_key = generate_key(key_size) print(f"\nWriting public key to file {name}_pubkey.txt...") with open(f"{name}_pubkey.txt", "w") as fo: fo.write( - "%d,%d,%d,%d" % (publicKey[0], publicKey[1], publicKey[2], publicKey[3]) + "%d,%d,%d,%d" % (public_key[0], public_key[1], public_key[2], public_key[3]) ) print(f"Writing private key to file {name}_privkey.txt...") with open(f"{name}_privkey.txt", "w") as fo: - fo.write("%d,%d" % (privateKey[0], privateKey[1])) + fo.write("%d,%d" % (private_key[0], private_key[1])) def main() -> None: diff --git a/ciphers/hill_cipher.py b/ciphers/hill_cipher.py index d8e436e92..f646d567b 100644 --- a/ciphers/hill_cipher.py +++ b/ciphers/hill_cipher.py @@ -201,11 +201,11 @@ class HillCipher: def main() -> None: - N = int(input("Enter the order of the encryption key: ")) + n = int(input("Enter the order of the encryption key: ")) hill_matrix = [] print("Enter each row of the encryption key with space separated integers") - for _ in range(N): + for _ in range(n): row = [int(x) for x in input().split()] hill_matrix.append(row) diff --git a/ciphers/polybius.py b/ciphers/polybius.py index 2a45f02a3..bf5d62f8d 100644 --- a/ciphers/polybius.py +++ b/ciphers/polybius.py @@ -11,7 +11,7 @@ import numpy as np class PolybiusCipher: def __init__(self) -> None: - SQUARE = [ + SQUARE = [ # noqa: N806 ["a", "b", "c", "d", "e"], ["f", "g", "h", "i", "k"], ["l", "m", "n", "o", "p"], diff --git a/ciphers/rabin_miller.py b/ciphers/rabin_miller.py index a9b834bfb..0aab80eb9 100644 --- a/ciphers/rabin_miller.py +++ b/ciphers/rabin_miller.py @@ -3,7 +3,7 @@ import random -def rabinMiller(num: int) -> bool: +def rabin_miller(num: int) -> bool: s = num - 1 t = 0 @@ -29,7 +29,7 @@ def is_prime_low_num(num: int) -> bool: if num < 2: return False - lowPrimes = [ + low_primes = [ 2, 3, 5, @@ -200,17 +200,17 @@ def is_prime_low_num(num: int) -> bool: 997, ] - if num in lowPrimes: + if num in low_primes: return True - for prime in lowPrimes: + for prime in low_primes: if (num % prime) == 0: return False - return rabinMiller(num) + return rabin_miller(num) -def generateLargePrime(keysize: int = 1024) -> int: +def generate_large_prime(keysize: int = 1024) -> int: while True: num = random.randrange(2 ** (keysize - 1), 2 ** (keysize)) if is_prime_low_num(num): @@ -218,6 +218,6 @@ def generateLargePrime(keysize: int = 1024) -> int: if __name__ == "__main__": - num = generateLargePrime() + num = generate_large_prime() print(("Prime number:", num)) print(("is_prime_low_num:", is_prime_low_num(num))) diff --git a/ciphers/rsa_cipher.py b/ciphers/rsa_cipher.py index c6bfaa0fb..de26992f5 100644 --- a/ciphers/rsa_cipher.py +++ b/ciphers/rsa_cipher.py @@ -37,12 +37,12 @@ def get_text_from_blocks( def encrypt_message( - message: str, key: tuple[int, int], blockSize: int = DEFAULT_BLOCK_SIZE + message: str, key: tuple[int, int], block_size: int = DEFAULT_BLOCK_SIZE ) -> list[int]: encrypted_blocks = [] n, e = key - for block in get_blocks_from_text(message, blockSize): + for block in get_blocks_from_text(message, block_size): encrypted_blocks.append(pow(block, e, n)) return encrypted_blocks @@ -63,8 +63,8 @@ def decrypt_message( def read_key_file(key_filename: str) -> tuple[int, int, int]: with open(key_filename) as fo: content = fo.read() - key_size, n, EorD = content.split(",") - return (int(key_size), int(n), int(EorD)) + key_size, n, eor_d = content.split(",") + return (int(key_size), int(n), int(eor_d)) def encrypt_and_write_to_file( @@ -125,15 +125,15 @@ def main() -> None: if mode == "encrypt": if not os.path.exists("rsa_pubkey.txt"): - rkg.makeKeyFiles("rsa", 1024) + rkg.make_key_files("rsa", 1024) message = input("\nEnter message: ") pubkey_filename = "rsa_pubkey.txt" print(f"Encrypting and writing to {filename}...") - encryptedText = encrypt_and_write_to_file(filename, pubkey_filename, message) + encrypted_text = encrypt_and_write_to_file(filename, pubkey_filename, message) print("\nEncrypted text:") - print(encryptedText) + print(encrypted_text) elif mode == "decrypt": privkey_filename = "rsa_privkey.txt" diff --git a/ciphers/rsa_factorization.py b/ciphers/rsa_factorization.py index de4df2777..9ee52777e 100644 --- a/ciphers/rsa_factorization.py +++ b/ciphers/rsa_factorization.py @@ -13,7 +13,7 @@ import math import random -def rsafactor(d: int, e: int, N: int) -> list[int]: +def rsafactor(d: int, e: int, n: int) -> list[int]: """ This function returns the factors of N, where p*q=N Return: [p, q] @@ -35,16 +35,16 @@ def rsafactor(d: int, e: int, N: int) -> list[int]: p = 0 q = 0 while p == 0: - g = random.randint(2, N - 1) + g = random.randint(2, n - 1) t = k while True: if t % 2 == 0: t = t // 2 - x = (g**t) % N - y = math.gcd(x - 1, N) + x = (g**t) % n + y = math.gcd(x - 1, n) if x > 1 and y > 1: p = y - q = N // y + q = n // y break # find the correct factors else: break # t is not divisible by 2, break and choose another g diff --git a/ciphers/rsa_key_generator.py b/ciphers/rsa_key_generator.py index d983c14f1..f64bc7dd0 100644 --- a/ciphers/rsa_key_generator.py +++ b/ciphers/rsa_key_generator.py @@ -2,38 +2,38 @@ import os import random import sys -from . import cryptomath_module as cryptoMath -from . import rabin_miller as rabinMiller +from . import cryptomath_module as cryptoMath # noqa: N812 +from . import rabin_miller as rabinMiller # noqa: N812 def main() -> None: print("Making key files...") - makeKeyFiles("rsa", 1024) + make_key_files("rsa", 1024) print("Key files generation successful.") -def generateKey(keySize: int) -> tuple[tuple[int, int], tuple[int, int]]: +def generate_key(key_size: int) -> tuple[tuple[int, int], tuple[int, int]]: print("Generating prime p...") - p = rabinMiller.generateLargePrime(keySize) + p = rabinMiller.generate_large_prime(key_size) print("Generating prime q...") - q = rabinMiller.generateLargePrime(keySize) + q = rabinMiller.generate_large_prime(key_size) n = p * q print("Generating e that is relatively prime to (p - 1) * (q - 1)...") while True: - e = random.randrange(2 ** (keySize - 1), 2 ** (keySize)) + e = random.randrange(2 ** (key_size - 1), 2 ** (key_size)) if cryptoMath.gcd(e, (p - 1) * (q - 1)) == 1: break print("Calculating d that is mod inverse of e...") d = cryptoMath.find_mod_inverse(e, (p - 1) * (q - 1)) - publicKey = (n, e) - privateKey = (n, d) - return (publicKey, privateKey) + public_key = (n, e) + private_key = (n, d) + return (public_key, private_key) -def makeKeyFiles(name: str, keySize: int) -> None: +def make_key_files(name: str, key_size: int) -> None: if os.path.exists(f"{name}_pubkey.txt") or os.path.exists(f"{name}_privkey.txt"): print("\nWARNING:") print( @@ -43,14 +43,14 @@ def makeKeyFiles(name: str, keySize: int) -> None: ) sys.exit() - publicKey, privateKey = generateKey(keySize) + public_key, private_key = generate_key(key_size) print(f"\nWriting public key to file {name}_pubkey.txt...") with open(f"{name}_pubkey.txt", "w") as out_file: - out_file.write(f"{keySize},{publicKey[0]},{publicKey[1]}") + out_file.write(f"{key_size},{public_key[0]},{public_key[1]}") print(f"Writing private key to file {name}_privkey.txt...") with open(f"{name}_privkey.txt", "w") as out_file: - out_file.write(f"{keySize},{privateKey[0]},{privateKey[1]}") + out_file.write(f"{key_size},{private_key[0]},{private_key[1]}") if __name__ == "__main__": diff --git a/ciphers/simple_substitution_cipher.py b/ciphers/simple_substitution_cipher.py index a763bd6b6..291a9bccd 100644 --- a/ciphers/simple_substitution_cipher.py +++ b/ciphers/simple_substitution_cipher.py @@ -9,66 +9,66 @@ def main() -> None: key = "LFWOAYUISVKMNXPBDCRJTQEGHZ" resp = input("Encrypt/Decrypt [e/d]: ") - checkValidKey(key) + check_valid_key(key) if resp.lower().startswith("e"): mode = "encrypt" - translated = encryptMessage(key, message) + translated = encrypt_message(key, message) elif resp.lower().startswith("d"): mode = "decrypt" - translated = decryptMessage(key, message) + translated = decrypt_message(key, message) print(f"\n{mode.title()}ion: \n{translated}") -def checkValidKey(key: str) -> None: - keyList = list(key) - lettersList = list(LETTERS) - keyList.sort() - lettersList.sort() +def check_valid_key(key: str) -> None: + key_list = list(key) + letters_list = list(LETTERS) + key_list.sort() + letters_list.sort() - if keyList != lettersList: + if key_list != letters_list: sys.exit("Error in the key or symbol set.") -def encryptMessage(key: str, message: str) -> str: +def encrypt_message(key: str, message: str) -> str: """ - >>> encryptMessage('LFWOAYUISVKMNXPBDCRJTQEGHZ', 'Harshil Darji') + >>> encrypt_message('LFWOAYUISVKMNXPBDCRJTQEGHZ', 'Harshil Darji') 'Ilcrism Olcvs' """ - return translateMessage(key, message, "encrypt") + return translate_message(key, message, "encrypt") -def decryptMessage(key: str, message: str) -> str: +def decrypt_message(key: str, message: str) -> str: """ - >>> decryptMessage('LFWOAYUISVKMNXPBDCRJTQEGHZ', 'Ilcrism Olcvs') + >>> decrypt_message('LFWOAYUISVKMNXPBDCRJTQEGHZ', 'Ilcrism Olcvs') 'Harshil Darji' """ - return translateMessage(key, message, "decrypt") + return translate_message(key, message, "decrypt") -def translateMessage(key: str, message: str, mode: str) -> str: +def translate_message(key: str, message: str, mode: str) -> str: translated = "" - charsA = LETTERS - charsB = key + chars_a = LETTERS + chars_b = key if mode == "decrypt": - charsA, charsB = charsB, charsA + chars_a, chars_b = chars_b, chars_a for symbol in message: - if symbol.upper() in charsA: - symIndex = charsA.find(symbol.upper()) + if symbol.upper() in chars_a: + sym_index = chars_a.find(symbol.upper()) if symbol.isupper(): - translated += charsB[symIndex].upper() + translated += chars_b[sym_index].upper() else: - translated += charsB[symIndex].lower() + translated += chars_b[sym_index].lower() else: translated += symbol return translated -def getRandomKey() -> str: +def get_random_key() -> str: key = list(LETTERS) random.shuffle(key) return "".join(key) diff --git a/ciphers/trafid_cipher.py b/ciphers/trafid_cipher.py index b12ceff72..108ac652f 100644 --- a/ciphers/trafid_cipher.py +++ b/ciphers/trafid_cipher.py @@ -2,12 +2,12 @@ from __future__ import annotations -def __encryptPart(messagePart: str, character2Number: dict[str, str]) -> str: +def __encrypt_part(message_part: str, character_to_number: dict[str, str]) -> str: one, two, three = "", "", "" tmp = [] - for character in messagePart: - tmp.append(character2Number[character]) + for character in message_part: + tmp.append(character_to_number[character]) for each in tmp: one += each[0] @@ -17,18 +17,18 @@ def __encryptPart(messagePart: str, character2Number: dict[str, str]) -> str: return one + two + three -def __decryptPart( - messagePart: str, character2Number: dict[str, str] +def __decrypt_part( + message_part: str, character_to_number: dict[str, str] ) -> tuple[str, str, str]: - tmp, thisPart = "", "" + tmp, this_part = "", "" result = [] - for character in messagePart: - thisPart += character2Number[character] + for character in message_part: + this_part += character_to_number[character] - for digit in thisPart: + for digit in this_part: tmp += digit - if len(tmp) == len(messagePart): + if len(tmp) == len(message_part): result.append(tmp) tmp = "" @@ -79,51 +79,57 @@ def __prepare( "332", "333", ) - character2Number = {} - number2Character = {} + character_to_number = {} + number_to_character = {} for letter, number in zip(alphabet, numbers): - character2Number[letter] = number - number2Character[number] = letter + character_to_number[letter] = number + number_to_character[number] = letter - return message, alphabet, character2Number, number2Character + return message, alphabet, character_to_number, number_to_character -def encryptMessage( +def encrypt_message( message: str, alphabet: str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.", period: int = 5 ) -> str: - message, alphabet, character2Number, number2Character = __prepare(message, alphabet) + message, alphabet, character_to_number, number_to_character = __prepare( + message, alphabet + ) encrypted, encrypted_numeric = "", "" for i in range(0, len(message) + 1, period): - encrypted_numeric += __encryptPart(message[i : i + period], character2Number) + encrypted_numeric += __encrypt_part( + message[i : i + period], character_to_number + ) for i in range(0, len(encrypted_numeric), 3): - encrypted += number2Character[encrypted_numeric[i : i + 3]] + encrypted += number_to_character[encrypted_numeric[i : i + 3]] return encrypted -def decryptMessage( +def decrypt_message( message: str, alphabet: str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.", period: int = 5 ) -> str: - message, alphabet, character2Number, number2Character = __prepare(message, alphabet) + message, alphabet, character_to_number, number_to_character = __prepare( + message, alphabet + ) decrypted_numeric = [] decrypted = "" for i in range(0, len(message) + 1, period): - a, b, c = __decryptPart(message[i : i + period], character2Number) + a, b, c = __decrypt_part(message[i : i + period], character_to_number) for j in range(0, len(a)): decrypted_numeric.append(a[j] + b[j] + c[j]) for each in decrypted_numeric: - decrypted += number2Character[each] + decrypted += number_to_character[each] return decrypted if __name__ == "__main__": msg = "DEFEND THE EAST WALL OF THE CASTLE." - encrypted = encryptMessage(msg, "EPSDUCVWYM.ZLKXNBTFGORIJHAQ") - decrypted = decryptMessage(encrypted, "EPSDUCVWYM.ZLKXNBTFGORIJHAQ") + encrypted = encrypt_message(msg, "EPSDUCVWYM.ZLKXNBTFGORIJHAQ") + decrypted = decrypt_message(encrypted, "EPSDUCVWYM.ZLKXNBTFGORIJHAQ") print(f"Encrypted: {encrypted}\nDecrypted: {decrypted}") diff --git a/ciphers/transposition_cipher.py b/ciphers/transposition_cipher.py index ed9923a6b..f1f07ddc3 100644 --- a/ciphers/transposition_cipher.py +++ b/ciphers/transposition_cipher.py @@ -14,53 +14,53 @@ def main() -> None: mode = input("Encryption/Decryption [e/d]: ") if mode.lower().startswith("e"): - text = encryptMessage(key, message) + text = encrypt_message(key, message) elif mode.lower().startswith("d"): - text = decryptMessage(key, message) + text = decrypt_message(key, message) # Append pipe symbol (vertical bar) to identify spaces at the end. print(f"Output:\n{text + '|'}") -def encryptMessage(key: int, message: str) -> str: +def encrypt_message(key: int, message: str) -> str: """ - >>> encryptMessage(6, 'Harshil Darji') + >>> encrypt_message(6, 'Harshil Darji') 'Hlia rDsahrij' """ - cipherText = [""] * key + cipher_text = [""] * key for col in range(key): pointer = col while pointer < len(message): - cipherText[col] += message[pointer] + cipher_text[col] += message[pointer] pointer += key - return "".join(cipherText) + return "".join(cipher_text) -def decryptMessage(key: int, message: str) -> str: +def decrypt_message(key: int, message: str) -> str: """ - >>> decryptMessage(6, 'Hlia rDsahrij') + >>> decrypt_message(6, 'Hlia rDsahrij') 'Harshil Darji' """ - numCols = math.ceil(len(message) / key) - numRows = key - numShadedBoxes = (numCols * numRows) - len(message) - plainText = [""] * numCols + num_cols = math.ceil(len(message) / key) + num_rows = key + num_shaded_boxes = (num_cols * num_rows) - len(message) + plain_text = [""] * num_cols col = 0 row = 0 for symbol in message: - plainText[col] += symbol + plain_text[col] += symbol col += 1 if ( - (col == numCols) - or (col == numCols - 1) - and (row >= numRows - numShadedBoxes) + (col == num_cols) + or (col == num_cols - 1) + and (row >= num_rows - num_shaded_boxes) ): col = 0 row += 1 - return "".join(plainText) + return "".join(plain_text) if __name__ == "__main__": diff --git a/ciphers/transposition_cipher_encrypt_decrypt_file.py b/ciphers/transposition_cipher_encrypt_decrypt_file.py index 926a1b36a..6296b1e6d 100644 --- a/ciphers/transposition_cipher_encrypt_decrypt_file.py +++ b/ciphers/transposition_cipher_encrypt_decrypt_file.py @@ -2,39 +2,39 @@ import os import sys import time -from . import transposition_cipher as transCipher +from . import transposition_cipher as trans_cipher def main() -> None: - inputFile = "Prehistoric Men.txt" - outputFile = "Output.txt" + input_file = "Prehistoric Men.txt" + output_file = "Output.txt" key = int(input("Enter key: ")) mode = input("Encrypt/Decrypt [e/d]: ") - if not os.path.exists(inputFile): - print(f"File {inputFile} does not exist. Quitting...") + if not os.path.exists(input_file): + print(f"File {input_file} does not exist. Quitting...") sys.exit() - if os.path.exists(outputFile): - print(f"Overwrite {outputFile}? [y/n]") + if os.path.exists(output_file): + print(f"Overwrite {output_file}? [y/n]") response = input("> ") if not response.lower().startswith("y"): sys.exit() - startTime = time.time() + start_time = time.time() if mode.lower().startswith("e"): - with open(inputFile) as f: + with open(input_file) as f: content = f.read() - translated = transCipher.encryptMessage(key, content) + translated = trans_cipher.encrypt_message(key, content) elif mode.lower().startswith("d"): - with open(outputFile) as f: + with open(output_file) as f: content = f.read() - translated = transCipher.decryptMessage(key, content) + translated = trans_cipher.decrypt_message(key, content) - with open(outputFile, "w") as outputObj: - outputObj.write(translated) + with open(output_file, "w") as output_obj: + output_obj.write(translated) - totalTime = round(time.time() - startTime, 2) - print(("Done (", totalTime, "seconds )")) + total_time = round(time.time() - start_time, 2) + print(("Done (", total_time, "seconds )")) if __name__ == "__main__": diff --git a/ciphers/vigenere_cipher.py b/ciphers/vigenere_cipher.py index 2e3987708..e76161351 100644 --- a/ciphers/vigenere_cipher.py +++ b/ciphers/vigenere_cipher.py @@ -8,43 +8,43 @@ def main() -> None: if mode.lower().startswith("e"): mode = "encrypt" - translated = encryptMessage(key, message) + translated = encrypt_message(key, message) elif mode.lower().startswith("d"): mode = "decrypt" - translated = decryptMessage(key, message) + translated = decrypt_message(key, message) print(f"\n{mode.title()}ed message:") print(translated) -def encryptMessage(key: str, message: str) -> str: +def encrypt_message(key: str, message: str) -> str: """ - >>> encryptMessage('HDarji', 'This is Harshil Darji from Dharmaj.') + >>> encrypt_message('HDarji', 'This is Harshil Darji from Dharmaj.') 'Akij ra Odrjqqs Gaisq muod Mphumrs.' """ - return translateMessage(key, message, "encrypt") + return translate_message(key, message, "encrypt") -def decryptMessage(key: str, message: str) -> str: +def decrypt_message(key: str, message: str) -> str: """ - >>> decryptMessage('HDarji', 'Akij ra Odrjqqs Gaisq muod Mphumrs.') + >>> decrypt_message('HDarji', 'Akij ra Odrjqqs Gaisq muod Mphumrs.') 'This is Harshil Darji from Dharmaj.' """ - return translateMessage(key, message, "decrypt") + return translate_message(key, message, "decrypt") -def translateMessage(key: str, message: str, mode: str) -> str: +def translate_message(key: str, message: str, mode: str) -> str: translated = [] - keyIndex = 0 + key_index = 0 key = key.upper() for symbol in message: num = LETTERS.find(symbol.upper()) if num != -1: if mode == "encrypt": - num += LETTERS.find(key[keyIndex]) + num += LETTERS.find(key[key_index]) elif mode == "decrypt": - num -= LETTERS.find(key[keyIndex]) + num -= LETTERS.find(key[key_index]) num %= len(LETTERS) @@ -53,9 +53,9 @@ def translateMessage(key: str, message: str, mode: str) -> str: elif symbol.islower(): translated.append(LETTERS[num].lower()) - keyIndex += 1 - if keyIndex == len(key): - keyIndex = 0 + key_index += 1 + if key_index == len(key): + key_index = 0 else: translated.append(symbol) return "".join(translated) diff --git a/compression/lempel_ziv_decompress.py b/compression/lempel_ziv_decompress.py index 4d3c2c0d2..ddedc3d6d 100644 --- a/compression/lempel_ziv_decompress.py +++ b/compression/lempel_ziv_decompress.py @@ -43,10 +43,10 @@ def decompress_data(data_bits: str) -> str: lexicon[curr_string] = last_match_id + "0" if math.log2(index).is_integer(): - newLex = {} + new_lex = {} for curr_key in list(lexicon): - newLex["0" + curr_key] = lexicon.pop(curr_key) - lexicon = newLex + new_lex["0" + curr_key] = lexicon.pop(curr_key) + lexicon = new_lex lexicon[bin(index)[2:]] = last_match_id + "1" index += 1 diff --git a/compression/peak_signal_to_noise_ratio.py b/compression/peak_signal_to_noise_ratio.py index dded2a712..66b18b50b 100644 --- a/compression/peak_signal_to_noise_ratio.py +++ b/compression/peak_signal_to_noise_ratio.py @@ -16,8 +16,8 @@ def psnr(original: float, contrast: float) -> float: mse = np.mean((original - contrast) ** 2) if mse == 0: return 100 - PIXEL_MAX = 255.0 - PSNR = 20 * math.log10(PIXEL_MAX / math.sqrt(mse)) + PIXEL_MAX = 255.0 # noqa: N806 + PSNR = 20 * math.log10(PIXEL_MAX / math.sqrt(mse)) # noqa: N806 return PSNR diff --git a/computer_vision/harris_corner.py b/computer_vision/harris_corner.py index 886ff52ea..7850085f8 100644 --- a/computer_vision/harris_corner.py +++ b/computer_vision/harris_corner.py @@ -7,7 +7,7 @@ https://en.wikipedia.org/wiki/Harris_Corner_Detector """ -class Harris_Corner: +class HarrisCorner: def __init__(self, k: float, window_size: int): """ @@ -70,6 +70,6 @@ class Harris_Corner: if __name__ == "__main__": - edge_detect = Harris_Corner(0.04, 3) + edge_detect = HarrisCorner(0.04, 3) color_img, _ = edge_detect.detect("path_to_image") cv2.imwrite("detect.png", color_img) diff --git a/conversions/binary_to_hexadecimal.py b/conversions/binary_to_hexadecimal.py index f94a12390..61f335a4c 100644 --- a/conversions/binary_to_hexadecimal.py +++ b/conversions/binary_to_hexadecimal.py @@ -17,7 +17,7 @@ def bin_to_hexadecimal(binary_str: str) -> str: ... ValueError: Empty string was passed to the function """ - BITS_TO_HEX = { + BITS_TO_HEX = { # noqa: N806 "0000": "0", "0001": "1", "0010": "2", diff --git a/conversions/decimal_to_any.py b/conversions/decimal_to_any.py index 3c72a7732..e54fa154a 100644 --- a/conversions/decimal_to_any.py +++ b/conversions/decimal_to_any.py @@ -66,7 +66,7 @@ def decimal_to_any(num: int, base: int) -> str: if base > 36: raise ValueError("base must be <= 36") # fmt: off - ALPHABET_VALUES = {'10': 'A', '11': 'B', '12': 'C', '13': 'D', '14': 'E', '15': 'F', + ALPHABET_VALUES = {'10': 'A', '11': 'B', '12': 'C', '13': 'D', '14': 'E', '15': 'F', # noqa: N806, E501 '16': 'G', '17': 'H', '18': 'I', '19': 'J', '20': 'K', '21': 'L', '22': 'M', '23': 'N', '24': 'O', '25': 'P', '26': 'Q', '27': 'R', '28': 'S', '29': 'T', '30': 'U', '31': 'V', '32': 'W', '33': 'X', diff --git a/conversions/prefix_conversions.py b/conversions/prefix_conversions.py index a77556433..06b759e35 100644 --- a/conversions/prefix_conversions.py +++ b/conversions/prefix_conversions.py @@ -6,7 +6,7 @@ from __future__ import annotations from enum import Enum -class SI_Unit(Enum): +class SIUnit(Enum): yotta = 24 zetta = 21 exa = 18 @@ -29,7 +29,7 @@ class SI_Unit(Enum): yocto = -24 -class Binary_Unit(Enum): +class BinaryUnit(Enum): yotta = 8 zetta = 7 exa = 6 @@ -42,17 +42,17 @@ class Binary_Unit(Enum): def convert_si_prefix( known_amount: float, - known_prefix: str | SI_Unit, - unknown_prefix: str | SI_Unit, + known_prefix: str | SIUnit, + unknown_prefix: str | SIUnit, ) -> float: """ Wikipedia reference: https://en.wikipedia.org/wiki/Binary_prefix Wikipedia reference: https://en.wikipedia.org/wiki/International_System_of_Units - >>> convert_si_prefix(1, SI_Unit.giga, SI_Unit.mega) + >>> convert_si_prefix(1, SIUnit.giga, SIUnit.mega) 1000 - >>> convert_si_prefix(1, SI_Unit.mega, SI_Unit.giga) + >>> convert_si_prefix(1, SIUnit.mega, SIUnit.giga) 0.001 - >>> convert_si_prefix(1, SI_Unit.kilo, SI_Unit.kilo) + >>> convert_si_prefix(1, SIUnit.kilo, SIUnit.kilo) 1 >>> convert_si_prefix(1, 'giga', 'mega') 1000 @@ -60,9 +60,9 @@ def convert_si_prefix( 1000 """ if isinstance(known_prefix, str): - known_prefix = SI_Unit[known_prefix.lower()] + known_prefix = SIUnit[known_prefix.lower()] if isinstance(unknown_prefix, str): - unknown_prefix = SI_Unit[unknown_prefix.lower()] + unknown_prefix = SIUnit[unknown_prefix.lower()] unknown_amount: float = known_amount * ( 10 ** (known_prefix.value - unknown_prefix.value) ) @@ -71,16 +71,16 @@ def convert_si_prefix( def convert_binary_prefix( known_amount: float, - known_prefix: str | Binary_Unit, - unknown_prefix: str | Binary_Unit, + known_prefix: str | BinaryUnit, + unknown_prefix: str | BinaryUnit, ) -> float: """ Wikipedia reference: https://en.wikipedia.org/wiki/Metric_prefix - >>> convert_binary_prefix(1, Binary_Unit.giga, Binary_Unit.mega) + >>> convert_binary_prefix(1, BinaryUnit.giga, BinaryUnit.mega) 1024 - >>> convert_binary_prefix(1, Binary_Unit.mega, Binary_Unit.giga) + >>> convert_binary_prefix(1, BinaryUnit.mega, BinaryUnit.giga) 0.0009765625 - >>> convert_binary_prefix(1, Binary_Unit.kilo, Binary_Unit.kilo) + >>> convert_binary_prefix(1, BinaryUnit.kilo, BinaryUnit.kilo) 1 >>> convert_binary_prefix(1, 'giga', 'mega') 1024 @@ -88,9 +88,9 @@ def convert_binary_prefix( 1024 """ if isinstance(known_prefix, str): - known_prefix = Binary_Unit[known_prefix.lower()] + known_prefix = BinaryUnit[known_prefix.lower()] if isinstance(unknown_prefix, str): - unknown_prefix = Binary_Unit[unknown_prefix.lower()] + unknown_prefix = BinaryUnit[unknown_prefix.lower()] unknown_amount: float = known_amount * ( 2 ** ((known_prefix.value - unknown_prefix.value) * 10) ) diff --git a/conversions/roman_numerals.py b/conversions/roman_numerals.py index 9933e6a78..960d41342 100644 --- a/conversions/roman_numerals.py +++ b/conversions/roman_numerals.py @@ -29,7 +29,7 @@ def int_to_roman(number: int) -> str: >>> all(int_to_roman(value) == key for key, value in tests.items()) True """ - ROMAN = [ + ROMAN = [ # noqa: N806 (1000, "M"), (900, "CM"), (500, "D"), diff --git a/data_structures/binary_tree/avl_tree.py b/data_structures/binary_tree/avl_tree.py index 1ab13777b..2f4bd60d9 100644 --- a/data_structures/binary_tree/avl_tree.py +++ b/data_structures/binary_tree/avl_tree.py @@ -12,7 +12,7 @@ import random from typing import Any -class my_queue: +class MyQueue: def __init__(self) -> None: self.data: list[Any] = [] self.head: int = 0 @@ -39,20 +39,20 @@ class my_queue: print(self.data[self.head : self.tail]) -class my_node: +class MyNode: def __init__(self, data: Any) -> None: self.data = data - self.left: my_node | None = None - self.right: my_node | None = None + self.left: MyNode | None = None + self.right: MyNode | None = None self.height: int = 1 def get_data(self) -> Any: return self.data - def get_left(self) -> my_node | None: + def get_left(self) -> MyNode | None: return self.left - def get_right(self) -> my_node | None: + def get_right(self) -> MyNode | None: return self.right def get_height(self) -> int: @@ -62,11 +62,11 @@ class my_node: self.data = data return - def set_left(self, node: my_node | None) -> None: + def set_left(self, node: MyNode | None) -> None: self.left = node return - def set_right(self, node: my_node | None) -> None: + def set_right(self, node: MyNode | None) -> None: self.right = node return @@ -75,7 +75,7 @@ class my_node: return -def get_height(node: my_node | None) -> int: +def get_height(node: MyNode | None) -> int: if node is None: return 0 return node.get_height() @@ -87,7 +87,7 @@ def my_max(a: int, b: int) -> int: return b -def right_rotation(node: my_node) -> my_node: +def right_rotation(node: MyNode) -> MyNode: r""" A B / \ / \ @@ -110,7 +110,7 @@ def right_rotation(node: my_node) -> my_node: return ret -def left_rotation(node: my_node) -> my_node: +def left_rotation(node: MyNode) -> MyNode: """ a mirror symmetry rotation of the left_rotation """ @@ -126,7 +126,7 @@ def left_rotation(node: my_node) -> my_node: return ret -def lr_rotation(node: my_node) -> my_node: +def lr_rotation(node: MyNode) -> MyNode: r""" A A Br / \ / \ / \ @@ -143,16 +143,16 @@ def lr_rotation(node: my_node) -> my_node: return right_rotation(node) -def rl_rotation(node: my_node) -> my_node: +def rl_rotation(node: MyNode) -> MyNode: right_child = node.get_right() assert right_child is not None node.set_right(right_rotation(right_child)) return left_rotation(node) -def insert_node(node: my_node | None, data: Any) -> my_node | None: +def insert_node(node: MyNode | None, data: Any) -> MyNode | None: if node is None: - return my_node(data) + return MyNode(data) if data < node.get_data(): node.set_left(insert_node(node.get_left(), data)) if ( @@ -180,7 +180,7 @@ def insert_node(node: my_node | None, data: Any) -> my_node | None: return node -def get_rightMost(root: my_node) -> Any: +def get_right_most(root: MyNode) -> Any: while True: right_child = root.get_right() if right_child is None: @@ -189,7 +189,7 @@ def get_rightMost(root: my_node) -> Any: return root.get_data() -def get_leftMost(root: my_node) -> Any: +def get_left_most(root: MyNode) -> Any: while True: left_child = root.get_left() if left_child is None: @@ -198,12 +198,12 @@ def get_leftMost(root: my_node) -> Any: return root.get_data() -def del_node(root: my_node, data: Any) -> my_node | None: +def del_node(root: MyNode, data: Any) -> MyNode | None: left_child = root.get_left() right_child = root.get_right() if root.get_data() == data: if left_child is not None and right_child is not None: - temp_data = get_leftMost(right_child) + temp_data = get_left_most(right_child) root.set_data(temp_data) root.set_right(del_node(right_child, temp_data)) elif left_child is not None: @@ -276,7 +276,7 @@ class AVLtree: """ def __init__(self) -> None: - self.root: my_node | None = None + self.root: MyNode | None = None def get_height(self) -> int: return get_height(self.root) @@ -296,7 +296,7 @@ class AVLtree: self, ) -> str: # a level traversale, gives a more intuitive look on the tree output = "" - q = my_queue() + q = MyQueue() q.push(self.root) layer = self.get_height() if layer == 0: diff --git a/data_structures/binary_tree/lazy_segment_tree.py b/data_structures/binary_tree/lazy_segment_tree.py index 94329cb43..050dfe0a6 100644 --- a/data_structures/binary_tree/lazy_segment_tree.py +++ b/data_structures/binary_tree/lazy_segment_tree.py @@ -37,14 +37,14 @@ 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] + self.segment_tree[idx] = a[left_element - 1] else: mid = (left_element + right_element) // 2 - self.build(self.left(idx), left_element, mid, A) - self.build(self.right(idx), mid + 1, right_element, A) + self.build(self.left(idx), left_element, mid, a) + self.build(self.right(idx), mid + 1, right_element, a) self.segment_tree[idx] = max( self.segment_tree[self.left(idx)], self.segment_tree[self.right(idx)] ) diff --git a/data_structures/binary_tree/segment_tree.py b/data_structures/binary_tree/segment_tree.py index 10451ae68..949a3ecdd 100644 --- a/data_structures/binary_tree/segment_tree.py +++ b/data_structures/binary_tree/segment_tree.py @@ -2,8 +2,8 @@ import math class SegmentTree: - def __init__(self, A): - self.N = len(A) + def __init__(self, a): + self.N = len(a) self.st = [0] * ( 4 * self.N ) # approximate the overall size of segment tree with array N @@ -58,11 +58,11 @@ class SegmentTree: q2 = self.query_recursive(self.right(idx), mid + 1, r, a, b) return max(q1, q2) - def showData(self): - showList = [] + def show_data(self): + show_list = [] for i in range(1, N + 1): - showList += [self.query(i, i)] - print(showList) + show_list += [self.query(i, i)] + print(show_list) if __name__ == "__main__": @@ -75,4 +75,4 @@ if __name__ == "__main__": segt.update(1, 3, 111) print(segt.query(1, 15)) segt.update(7, 8, 235) - segt.showData() + segt.show_data() diff --git a/data_structures/binary_tree/treap.py b/data_structures/binary_tree/treap.py index 0526b139b..a53ac566e 100644 --- a/data_structures/binary_tree/treap.py +++ b/data_structures/binary_tree/treap.py @@ -121,28 +121,28 @@ def inorder(root: Node | None) -> None: inorder(root.right) -def interactTreap(root: Node | None, args: str) -> Node | None: +def interact_treap(root: Node | None, args: str) -> Node | None: """ Commands: + value to add value into treap - value to erase all nodes with value - >>> root = interactTreap(None, "+1") + >>> root = interact_treap(None, "+1") >>> inorder(root) 1, - >>> root = interactTreap(root, "+3 +5 +17 +19 +2 +16 +4 +0") + >>> root = interact_treap(root, "+3 +5 +17 +19 +2 +16 +4 +0") >>> inorder(root) 0,1,2,3,4,5,16,17,19, - >>> root = interactTreap(root, "+4 +4 +4") + >>> root = interact_treap(root, "+4 +4 +4") >>> inorder(root) 0,1,2,3,4,4,4,4,5,16,17,19, - >>> root = interactTreap(root, "-0") + >>> root = interact_treap(root, "-0") >>> inorder(root) 1,2,3,4,4,4,4,5,16,17,19, - >>> root = interactTreap(root, "-4") + >>> root = interact_treap(root, "-4") >>> inorder(root) 1,2,3,5,16,17,19, - >>> root = interactTreap(root, "=0") + >>> root = interact_treap(root, "=0") Unknown command """ for arg in args.split(): @@ -168,7 +168,7 @@ def main() -> None: args = input() while args != "q": - root = interactTreap(root, args) + root = interact_treap(root, args) print(root) args = input() diff --git a/data_structures/heap/min_heap.py b/data_structures/heap/min_heap.py index 9265c4839..d8975eb2d 100644 --- a/data_structures/heap/min_heap.py +++ b/data_structures/heap/min_heap.py @@ -52,14 +52,14 @@ class MinHeap: return self.heap_dict[key] def build_heap(self, array): - lastIdx = len(array) - 1 - startFrom = self.get_parent_idx(lastIdx) + last_idx = len(array) - 1 + start_from = self.get_parent_idx(last_idx) for idx, i in enumerate(array): self.idx_of_element[i] = idx self.heap_dict[i.name] = i.val - for i in range(startFrom, -1, -1): + for i in range(start_from, -1, -1): self.sift_down(i, array) return array @@ -123,12 +123,12 @@ class MinHeap: def is_empty(self): return True if len(self.heap) == 0 else False - def decrease_key(self, node, newValue): + def decrease_key(self, node, new_value): assert ( - self.heap[self.idx_of_element[node]].val > newValue + self.heap[self.idx_of_element[node]].val > new_value ), "newValue must be less that current value" - node.val = newValue - self.heap_dict[node.name] = newValue + node.val = new_value + self.heap_dict[node.name] = new_value self.sift_up(self.idx_of_element[node]) @@ -143,7 +143,7 @@ e = Node("E", 4) # Use one of these two ways to generate Min-Heap # Generating Min-Heap from array -myMinHeap = MinHeap([r, b, a, x, e]) +my_min_heap = MinHeap([r, b, a, x, e]) # Generating Min-Heap by Insert method # myMinHeap.insert(a) @@ -154,14 +154,14 @@ myMinHeap = MinHeap([r, b, a, x, e]) # Before print("Min Heap - before decrease key") -for i in myMinHeap.heap: +for i in my_min_heap.heap: print(i) print("Min Heap - After decrease key of node [B -> -17]") -myMinHeap.decrease_key(b, -17) +my_min_heap.decrease_key(b, -17) # After -for i in myMinHeap.heap: +for i in my_min_heap.heap: print(i) if __name__ == "__main__": diff --git a/data_structures/stacks/infix_to_prefix_conversion.py b/data_structures/stacks/infix_to_prefix_conversion.py index d3dc9e3e9..6f6d5d57e 100644 --- a/data_structures/stacks/infix_to_prefix_conversion.py +++ b/data_structures/stacks/infix_to_prefix_conversion.py @@ -15,9 +15,9 @@ Enter an Infix Equation = a + b ^c """ -def infix_2_postfix(Infix): - Stack = [] - Postfix = [] +def infix_2_postfix(infix): + stack = [] + post_fix = [] priority = { "^": 3, "*": 2, @@ -26,7 +26,7 @@ def infix_2_postfix(Infix): "+": 1, "-": 1, } # Priority of each operator - print_width = len(Infix) if (len(Infix) > 7) else 7 + print_width = len(infix) if (len(infix) > 7) else 7 # Print table header for output print( @@ -37,52 +37,52 @@ def infix_2_postfix(Infix): ) print("-" * (print_width * 3 + 7)) - for x in Infix: + for x in infix: if x.isalpha() or x.isdigit(): - Postfix.append(x) # if x is Alphabet / Digit, add it to Postfix + post_fix.append(x) # if x is Alphabet / Digit, add it to Postfix elif x == "(": - Stack.append(x) # if x is "(" push to Stack + stack.append(x) # if x is "(" push to Stack elif x == ")": # if x is ")" pop stack until "(" is encountered - while Stack[-1] != "(": - Postfix.append(Stack.pop()) # Pop stack & add the content to Postfix - Stack.pop() + while stack[-1] != "(": + post_fix.append(stack.pop()) # Pop stack & add the content to Postfix + stack.pop() else: - if len(Stack) == 0: - Stack.append(x) # If stack is empty, push x to stack + if len(stack) == 0: + stack.append(x) # If stack is empty, push x to stack else: # while priority of x is not > priority of element in the stack - while len(Stack) > 0 and priority[x] <= priority[Stack[-1]]: - Postfix.append(Stack.pop()) # pop stack & add to Postfix - Stack.append(x) # push x to stack + while len(stack) > 0 and priority[x] <= priority[stack[-1]]: + post_fix.append(stack.pop()) # pop stack & add to Postfix + stack.append(x) # push x to stack print( x.center(8), - ("".join(Stack)).ljust(print_width), - ("".join(Postfix)).ljust(print_width), + ("".join(stack)).ljust(print_width), + ("".join(post_fix)).ljust(print_width), sep=" | ", ) # Output in tabular format - while len(Stack) > 0: # while stack is not empty - Postfix.append(Stack.pop()) # pop stack & add to Postfix + while len(stack) > 0: # while stack is not empty + post_fix.append(stack.pop()) # pop stack & add to Postfix print( " ".center(8), - ("".join(Stack)).ljust(print_width), - ("".join(Postfix)).ljust(print_width), + ("".join(stack)).ljust(print_width), + ("".join(post_fix)).ljust(print_width), sep=" | ", ) # Output in tabular format - return "".join(Postfix) # return Postfix as str + return "".join(post_fix) # return Postfix as str -def infix_2_prefix(Infix): - Infix = list(Infix[::-1]) # reverse the infix equation +def infix_2_prefix(infix): + infix = list(infix[::-1]) # reverse the infix equation - for i in range(len(Infix)): - if Infix[i] == "(": - Infix[i] = ")" # change "(" to ")" - elif Infix[i] == ")": - Infix[i] = "(" # change ")" to "(" + for i in range(len(infix)): + if infix[i] == "(": + infix[i] = ")" # change "(" to ")" + elif infix[i] == ")": + infix[i] = "(" # change ")" to "(" - return (infix_2_postfix("".join(Infix)))[ + return (infix_2_postfix("".join(infix)))[ ::-1 ] # call infix_2_postfix on Infix, return reverse of Postfix diff --git a/data_structures/stacks/postfix_evaluation.py b/data_structures/stacks/postfix_evaluation.py index 574acac71..28128f82e 100644 --- a/data_structures/stacks/postfix_evaluation.py +++ b/data_structures/stacks/postfix_evaluation.py @@ -20,49 +20,49 @@ Enter a Postfix Equation (space separated) = 5 6 9 * + import operator as op -def Solve(Postfix): - Stack = [] - Div = lambda x, y: int(x / y) # noqa: E731 integer division operation - Opr = { +def solve(post_fix): + stack = [] + div = lambda x, y: int(x / y) # noqa: E731 integer division operation + opr = { "^": op.pow, "*": op.mul, - "/": Div, + "/": div, "+": op.add, "-": op.sub, } # operators & their respective operation # print table header print("Symbol".center(8), "Action".center(12), "Stack", sep=" | ") - print("-" * (30 + len(Postfix))) + print("-" * (30 + len(post_fix))) - for x in Postfix: + for x in post_fix: if x.isdigit(): # if x in digit - Stack.append(x) # append x to stack + stack.append(x) # append x to stack # output in tabular format - print(x.rjust(8), ("push(" + x + ")").ljust(12), ",".join(Stack), sep=" | ") + print(x.rjust(8), ("push(" + x + ")").ljust(12), ",".join(stack), sep=" | ") else: - B = Stack.pop() # pop stack + b = stack.pop() # pop stack # output in tabular format - print("".rjust(8), ("pop(" + B + ")").ljust(12), ",".join(Stack), sep=" | ") + print("".rjust(8), ("pop(" + b + ")").ljust(12), ",".join(stack), sep=" | ") - A = Stack.pop() # pop stack + a = stack.pop() # pop stack # output in tabular format - print("".rjust(8), ("pop(" + A + ")").ljust(12), ",".join(Stack), sep=" | ") + print("".rjust(8), ("pop(" + a + ")").ljust(12), ",".join(stack), sep=" | ") - Stack.append( - str(Opr[x](int(A), int(B))) + stack.append( + str(opr[x](int(a), int(b))) ) # evaluate the 2 values popped from stack & push result to stack # output in tabular format print( x.rjust(8), - ("push(" + A + x + B + ")").ljust(12), - ",".join(Stack), + ("push(" + a + x + b + ")").ljust(12), + ",".join(stack), sep=" | ", ) - return int(Stack[0]) + return int(stack[0]) if __name__ == "__main__": Postfix = input("\n\nEnter a Postfix Equation (space separated) = ").split(" ") - print("\n\tResult = ", Solve(Postfix)) + print("\n\tResult = ", solve(Postfix)) diff --git a/data_structures/stacks/stock_span_problem.py b/data_structures/stacks/stock_span_problem.py index cc2adfdd6..19a81bd36 100644 --- a/data_structures/stacks/stock_span_problem.py +++ b/data_structures/stacks/stock_span_problem.py @@ -8,7 +8,7 @@ on the current day is less than or equal to its price on the given day. """ -def calculateSpan(price, S): +def calculation_span(price, s): n = len(price) # Create a stack and push index of fist element to it @@ -16,7 +16,7 @@ def calculateSpan(price, S): st.append(0) # Span value of first element is always 1 - S[0] = 1 + s[0] = 1 # Calculate span values for rest of the elements for i in range(1, n): @@ -30,14 +30,14 @@ def calculateSpan(price, S): # than all elements on left of it, i.e. price[0], # price[1], ..price[i-1]. Else the price[i] is # greater than elements after top of stack - S[i] = i + 1 if len(st) <= 0 else (i - st[0]) + s[i] = i + 1 if len(st) <= 0 else (i - st[0]) # Push this element to stack st.append(i) # A utility function to print elements of array -def printArray(arr, n): +def print_array(arr, n): for i in range(0, n): print(arr[i], end=" ") @@ -47,7 +47,7 @@ price = [10, 4, 5, 90, 120, 80] S = [0 for i in range(len(price) + 1)] # Fill the span values in array S[] -calculateSpan(price, S) +calculation_span(price, S) # Print the calculated span values -printArray(S, len(price)) +print_array(S, len(price)) diff --git a/digital_image_processing/edge_detection/canny.py b/digital_image_processing/edge_detection/canny.py index 295b4d825..a83035526 100644 --- a/digital_image_processing/edge_detection/canny.py +++ b/digital_image_processing/edge_detection/canny.py @@ -43,33 +43,33 @@ def canny(image, threshold_low=15, threshold_high=30, weak=128, strong=255): or 15 * PI / 8 <= direction <= 2 * PI or 7 * PI / 8 <= direction <= 9 * PI / 8 ): - W = sobel_grad[row, col - 1] - E = sobel_grad[row, col + 1] - if sobel_grad[row, col] >= W and sobel_grad[row, col] >= E: + w = sobel_grad[row, col - 1] + e = sobel_grad[row, col + 1] + if sobel_grad[row, col] >= w and sobel_grad[row, col] >= e: dst[row, col] = sobel_grad[row, col] elif (PI / 8 <= direction < 3 * PI / 8) or ( 9 * PI / 8 <= direction < 11 * PI / 8 ): - SW = sobel_grad[row + 1, col - 1] - NE = sobel_grad[row - 1, col + 1] - if sobel_grad[row, col] >= SW and sobel_grad[row, col] >= NE: + sw = sobel_grad[row + 1, col - 1] + ne = sobel_grad[row - 1, col + 1] + if sobel_grad[row, col] >= sw and sobel_grad[row, col] >= ne: dst[row, col] = sobel_grad[row, col] elif (3 * PI / 8 <= direction < 5 * PI / 8) or ( 11 * PI / 8 <= direction < 13 * PI / 8 ): - N = sobel_grad[row - 1, col] - S = sobel_grad[row + 1, col] - if sobel_grad[row, col] >= N and sobel_grad[row, col] >= S: + n = sobel_grad[row - 1, col] + s = sobel_grad[row + 1, col] + if sobel_grad[row, col] >= n and sobel_grad[row, col] >= s: dst[row, col] = sobel_grad[row, col] elif (5 * PI / 8 <= direction < 7 * PI / 8) or ( 13 * PI / 8 <= direction < 15 * PI / 8 ): - NW = sobel_grad[row - 1, col - 1] - SE = sobel_grad[row + 1, col + 1] - if sobel_grad[row, col] >= NW and sobel_grad[row, col] >= SE: + nw = sobel_grad[row - 1, col - 1] + se = sobel_grad[row + 1, col + 1] + if sobel_grad[row, col] >= nw and sobel_grad[row, col] >= se: dst[row, col] = sobel_grad[row, col] """ diff --git a/digital_image_processing/filters/bilateral_filter.py b/digital_image_processing/filters/bilateral_filter.py index 76ae4dd20..1afa01d3f 100644 --- a/digital_image_processing/filters/bilateral_filter.py +++ b/digital_image_processing/filters/bilateral_filter.py @@ -46,16 +46,16 @@ def bilateral_filter( kernel_size: int, ) -> np.ndarray: img2 = np.zeros(img.shape) - gaussKer = get_gauss_kernel(kernel_size, spatial_variance) - sizeX, sizeY = img.shape - for i in range(kernel_size // 2, sizeX - kernel_size // 2): - for j in range(kernel_size // 2, sizeY - kernel_size // 2): + gauss_ker = get_gauss_kernel(kernel_size, spatial_variance) + size_x, size_y = img.shape + for i in range(kernel_size // 2, size_x - kernel_size // 2): + for j in range(kernel_size // 2, size_y - kernel_size // 2): - imgS = get_slice(img, i, j, kernel_size) - imgI = imgS - imgS[kernel_size // 2, kernel_size // 2] - imgIG = vec_gaussian(imgI, intensity_variance) - weights = np.multiply(gaussKer, imgIG) - vals = np.multiply(imgS, weights) + img_s = get_slice(img, i, j, kernel_size) + img_i = img_s - img_s[kernel_size // 2, kernel_size // 2] + img_ig = vec_gaussian(img_i, intensity_variance) + weights = np.multiply(gauss_ker, img_ig) + vals = np.multiply(img_s, weights) val = np.sum(vals) / np.sum(weights) img2[i, j] = val return img2 diff --git a/digital_image_processing/histogram_equalization/histogram_stretch.py b/digital_image_processing/histogram_equalization/histogram_stretch.py index 0288a2c1f..5ea7773e3 100644 --- a/digital_image_processing/histogram_equalization/histogram_stretch.py +++ b/digital_image_processing/histogram_equalization/histogram_stretch.py @@ -11,7 +11,7 @@ import numpy as np from matplotlib import pyplot as plt -class contrastStretch: +class ConstantStretch: def __init__(self): self.img = "" self.original_image = "" @@ -45,10 +45,10 @@ class contrastStretch: self.img[j][i] = self.last_list[num] cv2.imwrite("output_data/output.jpg", self.img) - def plotHistogram(self): + def plot_histogram(self): plt.hist(self.img.ravel(), 256, [0, 256]) - def showImage(self): + def show_image(self): cv2.imshow("Output-Image", self.img) cv2.imshow("Input-Image", self.original_image) cv2.waitKey(5000) @@ -57,7 +57,7 @@ class contrastStretch: if __name__ == "__main__": file_path = os.path.join(os.path.basename(__file__), "image_data/input.jpg") - stretcher = contrastStretch() + stretcher = ConstantStretch() stretcher.stretch(file_path) - stretcher.plotHistogram() - stretcher.showImage() + stretcher.plot_histogram() + stretcher.show_image() diff --git a/digital_image_processing/index_calculation.py b/digital_image_processing/index_calculation.py index 033334af8..2f8fdc066 100644 --- a/digital_image_processing/index_calculation.py +++ b/digital_image_processing/index_calculation.py @@ -104,72 +104,72 @@ class IndexCalculation: #RGBIndex = ["GLI", "CI", "Hue", "I", "NGRDI", "RI", "S", "IF"] """ - def __init__(self, red=None, green=None, blue=None, redEdge=None, nir=None): + def __init__(self, red=None, green=None, blue=None, red_edge=None, nir=None): # print("Numpy version: " + np.__version__) - self.setMatrices(red=red, green=green, blue=blue, redEdge=redEdge, nir=nir) + self.set_matricies(red=red, green=green, blue=blue, red_edge=red_edge, nir=nir) - def setMatrices(self, red=None, green=None, blue=None, redEdge=None, nir=None): + def set_matricies(self, red=None, green=None, blue=None, red_edge=None, nir=None): if red is not None: self.red = red if green is not None: self.green = green if blue is not None: self.blue = blue - if redEdge is not None: - self.redEdge = redEdge + if red_edge is not None: + self.redEdge = red_edge if nir is not None: self.nir = nir return True def calculation( - self, index="", red=None, green=None, blue=None, redEdge=None, nir=None + self, index="", red=None, green=None, blue=None, red_edge=None, nir=None ): """ performs the calculation of the index with the values instantiated in the class :str index: abbreviation of index name to perform """ - self.setMatrices(red=red, green=green, blue=blue, redEdge=redEdge, nir=nir) + self.set_matricies(red=red, green=green, blue=blue, red_edge=red_edge, nir=nir) funcs = { - "ARVI2": self.ARVI2, - "CCCI": self.CCCI, - "CVI": self.CVI, - "GLI": self.GLI, - "NDVI": self.NDVI, - "BNDVI": self.BNDVI, - "redEdgeNDVI": self.redEdgeNDVI, - "GNDVI": self.GNDVI, - "GBNDVI": self.GBNDVI, - "GRNDVI": self.GRNDVI, - "RBNDVI": self.RBNDVI, - "PNDVI": self.PNDVI, - "ATSAVI": self.ATSAVI, - "BWDRVI": self.BWDRVI, - "CIgreen": self.CIgreen, - "CIrededge": self.CIrededge, - "CI": self.CI, - "CTVI": self.CTVI, - "GDVI": self.GDVI, - "EVI": self.EVI, - "GEMI": self.GEMI, - "GOSAVI": self.GOSAVI, - "GSAVI": self.GSAVI, - "Hue": self.Hue, - "IVI": self.IVI, - "IPVI": self.IPVI, - "I": self.I, - "RVI": self.RVI, - "MRVI": self.MRVI, - "MSAVI": self.MSAVI, - "NormG": self.NormG, - "NormNIR": self.NormNIR, - "NormR": self.NormR, - "NGRDI": self.NGRDI, - "RI": self.RI, - "S": self.S, - "IF": self.IF, - "DVI": self.DVI, - "TVI": self.TVI, - "NDRE": self.NDRE, + "ARVI2": self.arv12, + "CCCI": self.ccci, + "CVI": self.cvi, + "GLI": self.gli, + "NDVI": self.ndvi, + "BNDVI": self.bndvi, + "redEdgeNDVI": self.red_edge_ndvi, + "GNDVI": self.gndvi, + "GBNDVI": self.gbndvi, + "GRNDVI": self.grndvi, + "RBNDVI": self.rbndvi, + "PNDVI": self.pndvi, + "ATSAVI": self.atsavi, + "BWDRVI": self.bwdrvi, + "CIgreen": self.ci_green, + "CIrededge": self.ci_rededge, + "CI": self.ci, + "CTVI": self.ctvi, + "GDVI": self.gdvi, + "EVI": self.evi, + "GEMI": self.gemi, + "GOSAVI": self.gosavi, + "GSAVI": self.gsavi, + "Hue": self.hue, + "IVI": self.ivi, + "IPVI": self.ipvi, + "I": self.i, + "RVI": self.rvi, + "MRVI": self.mrvi, + "MSAVI": self.m_savi, + "NormG": self.norm_g, + "NormNIR": self.norm_nir, + "NormR": self.norm_r, + "NGRDI": self.ngrdi, + "RI": self.ri, + "S": self.s, + "IF": self._if, + "DVI": self.dvi, + "TVI": self.tvi, + "NDRE": self.ndre, } try: @@ -178,7 +178,7 @@ class IndexCalculation: print("Index not in the list!") return False - def ARVI2(self): + def arv12(self): """ Atmospherically Resistant Vegetation Index 2 https://www.indexdatabase.de/db/i-single.php?id=396 @@ -187,7 +187,7 @@ class IndexCalculation: """ return -0.18 + (1.17 * ((self.nir - self.red) / (self.nir + self.red))) - def CCCI(self): + def ccci(self): """ Canopy Chlorophyll Content Index https://www.indexdatabase.de/db/i-single.php?id=224 @@ -197,7 +197,7 @@ class IndexCalculation: (self.nir - self.red) / (self.nir + self.red) ) - def CVI(self): + def cvi(self): """ Chlorophyll vegetation index https://www.indexdatabase.de/db/i-single.php?id=391 @@ -205,7 +205,7 @@ class IndexCalculation: """ return self.nir * (self.red / (self.green**2)) - def GLI(self): + def gli(self): """ self.green leaf index https://www.indexdatabase.de/db/i-single.php?id=375 @@ -215,7 +215,7 @@ class IndexCalculation: 2 * self.green + self.red + self.blue ) - def NDVI(self): + def ndvi(self): """ Normalized Difference self.nir/self.red Normalized Difference Vegetation Index, Calibrated NDVI - CDVI @@ -224,7 +224,7 @@ class IndexCalculation: """ return (self.nir - self.red) / (self.nir + self.red) - def BNDVI(self): + def bndvi(self): """ Normalized Difference self.nir/self.blue self.blue-normalized difference vegetation index @@ -233,7 +233,7 @@ class IndexCalculation: """ return (self.nir - self.blue) / (self.nir + self.blue) - def redEdgeNDVI(self): + def red_edge_ndvi(self): """ Normalized Difference self.rededge/self.red https://www.indexdatabase.de/db/i-single.php?id=235 @@ -241,7 +241,7 @@ class IndexCalculation: """ return (self.redEdge - self.red) / (self.redEdge + self.red) - def GNDVI(self): + def gndvi(self): """ Normalized Difference self.nir/self.green self.green NDVI https://www.indexdatabase.de/db/i-single.php?id=401 @@ -249,7 +249,7 @@ class IndexCalculation: """ return (self.nir - self.green) / (self.nir + self.green) - def GBNDVI(self): + def gbndvi(self): """ self.green-self.blue NDVI https://www.indexdatabase.de/db/i-single.php?id=186 @@ -259,7 +259,7 @@ class IndexCalculation: self.nir + (self.green + self.blue) ) - def GRNDVI(self): + def grndvi(self): """ self.green-self.red NDVI https://www.indexdatabase.de/db/i-single.php?id=185 @@ -269,7 +269,7 @@ class IndexCalculation: self.nir + (self.green + self.red) ) - def RBNDVI(self): + def rbndvi(self): """ self.red-self.blue NDVI https://www.indexdatabase.de/db/i-single.php?id=187 @@ -277,7 +277,7 @@ class IndexCalculation: """ return (self.nir - (self.blue + self.red)) / (self.nir + (self.blue + self.red)) - def PNDVI(self): + def pndvi(self): """ Pan NDVI https://www.indexdatabase.de/db/i-single.php?id=188 @@ -287,7 +287,7 @@ class IndexCalculation: self.nir + (self.green + self.red + self.blue) ) - def ATSAVI(self, X=0.08, a=1.22, b=0.03): + def atsavi(self, x=0.08, a=1.22, b=0.03): """ Adjusted transformed soil-adjusted VI https://www.indexdatabase.de/db/i-single.php?id=209 @@ -295,10 +295,10 @@ class IndexCalculation: """ return a * ( (self.nir - a * self.red - b) - / (a * self.nir + self.red - a * b + X * (1 + a**2)) + / (a * self.nir + self.red - a * b + x * (1 + a**2)) ) - def BWDRVI(self): + def bwdrvi(self): """ self.blue-wide dynamic range vegetation index https://www.indexdatabase.de/db/i-single.php?id=136 @@ -306,7 +306,7 @@ class IndexCalculation: """ return (0.1 * self.nir - self.blue) / (0.1 * self.nir + self.blue) - def CIgreen(self): + def ci_green(self): """ Chlorophyll Index self.green https://www.indexdatabase.de/db/i-single.php?id=128 @@ -314,7 +314,7 @@ class IndexCalculation: """ return (self.nir / self.green) - 1 - def CIrededge(self): + def ci_rededge(self): """ Chlorophyll Index self.redEdge https://www.indexdatabase.de/db/i-single.php?id=131 @@ -322,7 +322,7 @@ class IndexCalculation: """ return (self.nir / self.redEdge) - 1 - def CI(self): + def ci(self): """ Coloration Index https://www.indexdatabase.de/db/i-single.php?id=11 @@ -330,16 +330,16 @@ class IndexCalculation: """ return (self.red - self.blue) / self.red - def CTVI(self): + def ctvi(self): """ Corrected Transformed Vegetation Index https://www.indexdatabase.de/db/i-single.php?id=244 :return: index """ - ndvi = self.NDVI() + ndvi = self.ndvi() return ((ndvi + 0.5) / (abs(ndvi + 0.5))) * (abs(ndvi + 0.5) ** (1 / 2)) - def GDVI(self): + def gdvi(self): """ Difference self.nir/self.green self.green Difference Vegetation Index https://www.indexdatabase.de/db/i-single.php?id=27 @@ -347,7 +347,7 @@ class IndexCalculation: """ return self.nir - self.green - def EVI(self): + def evi(self): """ Enhanced Vegetation Index https://www.indexdatabase.de/db/i-single.php?id=16 @@ -357,7 +357,7 @@ class IndexCalculation: (self.nir - self.red) / (self.nir + 6 * self.red - 7.5 * self.blue + 1) ) - def GEMI(self): + def gemi(self): """ Global Environment Monitoring Index https://www.indexdatabase.de/db/i-single.php?id=25 @@ -368,25 +368,25 @@ class IndexCalculation: ) return n * (1 - 0.25 * n) - (self.red - 0.125) / (1 - self.red) - def GOSAVI(self, Y=0.16): + def gosavi(self, y=0.16): """ self.green Optimized Soil Adjusted Vegetation Index https://www.indexdatabase.de/db/i-single.php?id=29 mit Y = 0,16 :return: index """ - return (self.nir - self.green) / (self.nir + self.green + Y) + return (self.nir - self.green) / (self.nir + self.green + y) - def GSAVI(self, L=0.5): + def gsavi(self, n=0.5): """ self.green Soil Adjusted Vegetation Index https://www.indexdatabase.de/db/i-single.php?id=31 - mit L = 0,5 + mit N = 0,5 :return: index """ - return ((self.nir - self.green) / (self.nir + self.green + L)) * (1 + L) + return ((self.nir - self.green) / (self.nir + self.green + n)) * (1 + n) - def Hue(self): + def hue(self): """ Hue https://www.indexdatabase.de/db/i-single.php?id=34 @@ -396,7 +396,7 @@ class IndexCalculation: ((2 * self.red - self.green - self.blue) / 30.5) * (self.green - self.blue) ) - def IVI(self, a=None, b=None): + def ivi(self, a=None, b=None): """ Ideal vegetation index https://www.indexdatabase.de/db/i-single.php?id=276 @@ -406,15 +406,15 @@ class IndexCalculation: """ return (self.nir - b) / (a * self.red) - def IPVI(self): + def ipvi(self): """ Infraself.red percentage vegetation index https://www.indexdatabase.de/db/i-single.php?id=35 :return: index """ - return (self.nir / ((self.nir + self.red) / 2)) * (self.NDVI() + 1) + return (self.nir / ((self.nir + self.red) / 2)) * (self.ndvi() + 1) - def I(self): # noqa: E741,E743 + def i(self): # noqa: E741,E743 """ Intensity https://www.indexdatabase.de/db/i-single.php?id=36 @@ -422,7 +422,7 @@ class IndexCalculation: """ return (self.red + self.green + self.blue) / 30.5 - def RVI(self): + def rvi(self): """ Ratio-Vegetation-Index http://www.seos-project.eu/modules/remotesensing/remotesensing-c03-s01-p01.html @@ -430,15 +430,15 @@ class IndexCalculation: """ return self.nir / self.red - def MRVI(self): + def mrvi(self): """ Modified Normalized Difference Vegetation Index RVI https://www.indexdatabase.de/db/i-single.php?id=275 :return: index """ - return (self.RVI() - 1) / (self.RVI() + 1) + return (self.rvi() - 1) / (self.rvi() + 1) - def MSAVI(self): + def m_savi(self): """ Modified Soil Adjusted Vegetation Index https://www.indexdatabase.de/db/i-single.php?id=44 @@ -449,7 +449,7 @@ class IndexCalculation: - ((2 * self.nir + 1) ** 2 - 8 * (self.nir - self.red)) ** (1 / 2) ) / 2 - def NormG(self): + def norm_g(self): """ Norm G https://www.indexdatabase.de/db/i-single.php?id=50 @@ -457,7 +457,7 @@ class IndexCalculation: """ return self.green / (self.nir + self.red + self.green) - def NormNIR(self): + def norm_nir(self): """ Norm self.nir https://www.indexdatabase.de/db/i-single.php?id=51 @@ -465,7 +465,7 @@ class IndexCalculation: """ return self.nir / (self.nir + self.red + self.green) - def NormR(self): + def norm_r(self): """ Norm R https://www.indexdatabase.de/db/i-single.php?id=52 @@ -473,7 +473,7 @@ class IndexCalculation: """ return self.red / (self.nir + self.red + self.green) - def NGRDI(self): + def ngrdi(self): """ Normalized Difference self.green/self.red Normalized self.green self.red difference index, Visible Atmospherically Resistant Indices self.green @@ -483,7 +483,7 @@ class IndexCalculation: """ return (self.green - self.red) / (self.green + self.red) - def RI(self): + def ri(self): """ Normalized Difference self.red/self.green self.redness Index https://www.indexdatabase.de/db/i-single.php?id=74 @@ -491,7 +491,7 @@ class IndexCalculation: """ return (self.red - self.green) / (self.red + self.green) - def S(self): + def s(self): """ Saturation https://www.indexdatabase.de/db/i-single.php?id=77 @@ -501,7 +501,7 @@ class IndexCalculation: min = np.min([np.min(self.red), np.min(self.green), np.min(self.blue)]) return (max - min) / max - def IF(self): + def _if(self): """ Shape Index https://www.indexdatabase.de/db/i-single.php?id=79 @@ -509,7 +509,7 @@ class IndexCalculation: """ return (2 * self.red - self.green - self.blue) / (self.green - self.blue) - def DVI(self): + def dvi(self): """ Simple Ratio self.nir/self.red Difference Vegetation Index, Vegetation Index Number (VIN) @@ -518,15 +518,15 @@ class IndexCalculation: """ return self.nir / self.red - def TVI(self): + def tvi(self): """ Transformed Vegetation Index https://www.indexdatabase.de/db/i-single.php?id=98 :return: index """ - return (self.NDVI() + 0.5) ** (1 / 2) + return (self.ndvi() + 0.5) ** (1 / 2) - def NDRE(self): + def ndre(self): return (self.nir - self.redEdge) / (self.nir + self.redEdge) diff --git a/digital_image_processing/test_digital_image_processing.py b/digital_image_processing/test_digital_image_processing.py index 1f42fddf2..fdcebfdad 100644 --- a/digital_image_processing/test_digital_image_processing.py +++ b/digital_image_processing/test_digital_image_processing.py @@ -62,8 +62,8 @@ def test_gen_gaussian_kernel_filter(): def test_convolve_filter(): # laplace diagonals - Laplace = array([[0.25, 0.5, 0.25], [0.5, -3, 0.5], [0.25, 0.5, 0.25]]) - res = conv.img_convolve(gray, Laplace).astype(uint8) + laplace = array([[0.25, 0.5, 0.25], [0.5, -3, 0.5], [0.25, 0.5, 0.25]]) + res = conv.img_convolve(gray, laplace).astype(uint8) assert res.any() diff --git a/divide_and_conquer/inversions.py b/divide_and_conquer/inversions.py index e20d35dac..35f78fe5c 100644 --- a/divide_and_conquer/inversions.py +++ b/divide_and_conquer/inversions.py @@ -63,18 +63,18 @@ def count_inversions_recursive(arr): if len(arr) <= 1: return arr, 0 mid = len(arr) // 2 - P = arr[0:mid] - Q = arr[mid:] + p = arr[0:mid] + q = arr[mid:] - A, inversion_p = count_inversions_recursive(P) - B, inversions_q = count_inversions_recursive(Q) - C, cross_inversions = _count_cross_inversions(A, B) + a, inversion_p = count_inversions_recursive(p) + b, inversions_q = count_inversions_recursive(q) + c, cross_inversions = _count_cross_inversions(a, b) num_inversions = inversion_p + inversions_q + cross_inversions - return C, num_inversions + return c, num_inversions -def _count_cross_inversions(P, Q): +def _count_cross_inversions(p, q): """ Counts the inversions across two sorted arrays. And combine the two arrays into one sorted array @@ -96,26 +96,26 @@ def _count_cross_inversions(P, Q): ([1, 2, 3, 3, 4, 5], 0) """ - R = [] + r = [] i = j = num_inversion = 0 - while i < len(P) and j < len(Q): - if P[i] > Q[j]: + while i < len(p) and j < len(q): + if p[i] > q[j]: # if P[1] > Q[j], then P[k] > Q[k] for all i < k <= len(P) # These are all inversions. The claim emerges from the # property that P is sorted. - num_inversion += len(P) - i - R.append(Q[j]) + num_inversion += len(p) - i + r.append(q[j]) j += 1 else: - R.append(P[i]) + r.append(p[i]) i += 1 - if i < len(P): - R.extend(P[i:]) + if i < len(p): + r.extend(p[i:]) else: - R.extend(Q[j:]) + r.extend(q[j:]) - return R, num_inversion + return r, num_inversion def main(): diff --git a/dynamic_programming/bitmask.py b/dynamic_programming/bitmask.py index 2994db5b5..f45250c9c 100644 --- a/dynamic_programming/bitmask.py +++ b/dynamic_programming/bitmask.py @@ -28,7 +28,7 @@ class AssignmentUsingBitmask: # to 1 self.final_mask = (1 << len(task_performed)) - 1 - def CountWaysUtil(self, mask, task_no): + def count_ways_until(self, mask, task_no): # if mask == self.finalmask all persons are distributed tasks, return 1 if mask == self.final_mask: @@ -43,7 +43,7 @@ class AssignmentUsingBitmask: return self.dp[mask][task_no] # Number of ways when we don't this task in the arrangement - total_ways_util = self.CountWaysUtil(mask, task_no + 1) + total_ways_util = self.count_ways_until(mask, task_no + 1) # now assign the tasks one by one to all possible persons and recursively # assign for the remaining tasks. @@ -56,14 +56,14 @@ class AssignmentUsingBitmask: # assign this task to p and change the mask value. And recursively # assign tasks with the new mask value. - total_ways_util += self.CountWaysUtil(mask | (1 << p), task_no + 1) + total_ways_util += self.count_ways_until(mask | (1 << p), task_no + 1) # save the value. self.dp[mask][task_no] = total_ways_util return self.dp[mask][task_no] - def countNoOfWays(self, task_performed): + def count_no_of_ways(self, task_performed): # Store the list of persons for each task for i in range(len(task_performed)): @@ -71,7 +71,7 @@ class AssignmentUsingBitmask: self.task[j].append(i) # call the function to fill the DP table, final answer is stored in dp[0][1] - return self.CountWaysUtil(0, 1) + return self.count_ways_until(0, 1) if __name__ == "__main__": @@ -81,7 +81,7 @@ if __name__ == "__main__": # the list of tasks that can be done by M persons. task_performed = [[1, 3, 4], [1, 2, 5], [3, 4]] print( - AssignmentUsingBitmask(task_performed, total_tasks).countNoOfWays( + AssignmentUsingBitmask(task_performed, total_tasks).count_no_of_ways( task_performed ) ) diff --git a/dynamic_programming/edit_distance.py b/dynamic_programming/edit_distance.py index 56877e0c5..d63e559e3 100644 --- a/dynamic_programming/edit_distance.py +++ b/dynamic_programming/edit_distance.py @@ -21,10 +21,10 @@ class EditDistance: def __init__(self): self.__prepare__() - def __prepare__(self, N=0, M=0): - self.dp = [[-1 for y in range(0, M)] for x in range(0, N)] + def __prepare__(self, n=0, m=0): + self.dp = [[-1 for y in range(0, m)] for x in range(0, n)] - def __solveDP(self, x, y): + def __solve_dp(self, x, y): if x == -1: return y + 1 elif y == -1: @@ -32,30 +32,30 @@ class EditDistance: elif self.dp[x][y] > -1: return self.dp[x][y] else: - if self.A[x] == self.B[y]: - self.dp[x][y] = self.__solveDP(x - 1, y - 1) + if self.a[x] == self.b[y]: + self.dp[x][y] = self.__solve_dp(x - 1, y - 1) else: self.dp[x][y] = 1 + min( - self.__solveDP(x, y - 1), - self.__solveDP(x - 1, y), - self.__solveDP(x - 1, y - 1), + self.__solve_dp(x, y - 1), + self.__solve_dp(x - 1, y), + self.__solve_dp(x - 1, y - 1), ) return self.dp[x][y] - def solve(self, A, B): - if isinstance(A, bytes): - A = A.decode("ascii") + def solve(self, a, b): + if isinstance(a, bytes): + a = a.decode("ascii") - if isinstance(B, bytes): - B = B.decode("ascii") + if isinstance(b, bytes): + b = b.decode("ascii") - self.A = str(A) - self.B = str(B) + self.a = str(a) + self.b = str(b) - self.__prepare__(len(A), len(B)) + self.__prepare__(len(a), len(b)) - return self.__solveDP(len(A) - 1, len(B) - 1) + return self.__solve_dp(len(a) - 1, len(b) - 1) def min_distance_bottom_up(word1: str, word2: str) -> int: diff --git a/dynamic_programming/floyd_warshall.py b/dynamic_programming/floyd_warshall.py index a4b6c6a82..614a3c72a 100644 --- a/dynamic_programming/floyd_warshall.py +++ b/dynamic_programming/floyd_warshall.py @@ -2,41 +2,41 @@ import math class Graph: - def __init__(self, N=0): # a graph with Node 0,1,...,N-1 - self.N = N - self.W = [ - [math.inf for j in range(0, N)] for i in range(0, N) + def __init__(self, n=0): # a graph with Node 0,1,...,N-1 + self.n = n + self.w = [ + [math.inf for j in range(0, n)] for i in range(0, n) ] # adjacency matrix for weight self.dp = [ - [math.inf for j in range(0, N)] for i in range(0, N) + [math.inf for j in range(0, n)] for i in range(0, n) ] # dp[i][j] stores minimum distance from i to j - def addEdge(self, u, v, w): + def add_edge(self, u, v, w): self.dp[u][v] = w def floyd_warshall(self): - for k in range(0, self.N): - for i in range(0, self.N): - for j in range(0, self.N): + for k in range(0, self.n): + for i in range(0, self.n): + for j in range(0, self.n): self.dp[i][j] = min(self.dp[i][j], self.dp[i][k] + self.dp[k][j]) - def showMin(self, u, v): + def show_min(self, u, v): return self.dp[u][v] if __name__ == "__main__": graph = Graph(5) - graph.addEdge(0, 2, 9) - graph.addEdge(0, 4, 10) - graph.addEdge(1, 3, 5) - graph.addEdge(2, 3, 7) - graph.addEdge(3, 0, 10) - graph.addEdge(3, 1, 2) - graph.addEdge(3, 2, 1) - graph.addEdge(3, 4, 6) - graph.addEdge(4, 1, 3) - graph.addEdge(4, 2, 4) - graph.addEdge(4, 3, 9) + graph.add_edge(0, 2, 9) + graph.add_edge(0, 4, 10) + graph.add_edge(1, 3, 5) + graph.add_edge(2, 3, 7) + graph.add_edge(3, 0, 10) + graph.add_edge(3, 1, 2) + graph.add_edge(3, 2, 1) + graph.add_edge(3, 4, 6) + graph.add_edge(4, 1, 3) + graph.add_edge(4, 2, 4) + graph.add_edge(4, 3, 9) graph.floyd_warshall() - graph.showMin(1, 4) - graph.showMin(0, 3) + graph.show_min(1, 4) + graph.show_min(0, 3) diff --git a/dynamic_programming/fractional_knapsack.py b/dynamic_programming/fractional_knapsack.py index c74af7ef8..6f7a2a08c 100644 --- a/dynamic_programming/fractional_knapsack.py +++ b/dynamic_programming/fractional_knapsack.py @@ -2,20 +2,20 @@ from bisect import bisect from itertools import accumulate -def fracKnapsack(vl, wt, W, n): +def frac_knapsack(vl, wt, w, n): """ - >>> fracKnapsack([60, 100, 120], [10, 20, 30], 50, 3) + >>> frac_knapsack([60, 100, 120], [10, 20, 30], 50, 3) 240.0 """ r = list(sorted(zip(vl, wt), key=lambda x: x[0] / x[1], reverse=True)) vl, wt = [i[0] for i in r], [i[1] for i in r] acc = list(accumulate(wt)) - k = bisect(acc, W) + k = bisect(acc, w) return ( 0 if k == 0 - else sum(vl[:k]) + (W - acc[k - 1]) * (vl[k]) / (wt[k]) + else sum(vl[:k]) + (w - acc[k - 1]) * (vl[k]) / (wt[k]) if k != n else sum(vl[:k]) ) diff --git a/dynamic_programming/knapsack.py b/dynamic_programming/knapsack.py index 804d7d4f1..9efb60bab 100644 --- a/dynamic_programming/knapsack.py +++ b/dynamic_programming/knapsack.py @@ -7,39 +7,39 @@ Note that only the integer weights 0-1 knapsack problem is solvable """ -def MF_knapsack(i, wt, val, j): +def mf_knapsack(i, wt, val, j): """ This code involves the concept of memory functions. Here we solve the subproblems which are needed unlike the below example F is a 2D array with -1s filled up """ - global F # a global dp table for knapsack - if F[i][j] < 0: + global f # a global dp table for knapsack + if f[i][j] < 0: if j < wt[i - 1]: - val = MF_knapsack(i - 1, wt, val, j) + val = mf_knapsack(i - 1, wt, val, j) else: val = max( - MF_knapsack(i - 1, wt, val, j), - MF_knapsack(i - 1, wt, val, j - wt[i - 1]) + val[i - 1], + mf_knapsack(i - 1, wt, val, j), + mf_knapsack(i - 1, wt, val, j - wt[i - 1]) + val[i - 1], ) - F[i][j] = val - return F[i][j] + f[i][j] = val + return f[i][j] -def knapsack(W, wt, val, n): - dp = [[0 for i in range(W + 1)] for j in range(n + 1)] +def knapsack(w, wt, val, n): + dp = [[0 for i in range(w + 1)] for j in range(n + 1)] for i in range(1, n + 1): - for w in range(1, W + 1): + for w in range(1, w + 1): if wt[i - 1] <= w: dp[i][w] = max(val[i - 1] + dp[i - 1][w - wt[i - 1]], dp[i - 1][w]) else: dp[i][w] = dp[i - 1][w] - return dp[n][W], dp + return dp[n][w], dp -def knapsack_with_example_solution(W: int, wt: list, val: list): +def knapsack_with_example_solution(w: int, wt: list, val: list): """ Solves the integer weights knapsack problem returns one of the several possible optimal subsets. @@ -90,9 +90,9 @@ def knapsack_with_example_solution(W: int, wt: list, val: list): f"got weight of type {type(wt[i])} at index {i}" ) - optimal_val, dp_table = knapsack(W, wt, val, num_items) + optimal_val, dp_table = knapsack(w, wt, val, num_items) example_optional_set: set = set() - _construct_solution(dp_table, wt, num_items, W, example_optional_set) + _construct_solution(dp_table, wt, num_items, w, example_optional_set) return optimal_val, example_optional_set @@ -136,10 +136,10 @@ if __name__ == "__main__": wt = [4, 3, 2, 3] n = 4 w = 6 - F = [[0] * (w + 1)] + [[0] + [-1 for i in range(w + 1)] for j in range(n + 1)] + f = [[0] * (w + 1)] + [[0] + [-1 for i in range(w + 1)] for j in range(n + 1)] optimal_solution, _ = knapsack(w, wt, val, n) print(optimal_solution) - print(MF_knapsack(n, wt, val, w)) # switched the n and w + print(mf_knapsack(n, wt, val, w)) # switched the n and w # testing the dynamic programming problem with example # the optimal subset for the above example are items 3 and 4 diff --git a/dynamic_programming/longest_common_subsequence.py b/dynamic_programming/longest_common_subsequence.py index fdcf3311a..3468fd87d 100644 --- a/dynamic_programming/longest_common_subsequence.py +++ b/dynamic_programming/longest_common_subsequence.py @@ -38,7 +38,7 @@ def longest_common_subsequence(x: str, y: str): n = len(y) # declaring the array for storing the dp values - L = [[0] * (n + 1) for _ in range(m + 1)] + l = [[0] * (n + 1) for _ in range(m + 1)] # noqa: E741 for i in range(1, m + 1): for j in range(1, n + 1): @@ -47,7 +47,7 @@ def longest_common_subsequence(x: str, y: str): else: match = 0 - L[i][j] = max(L[i - 1][j], L[i][j - 1], L[i - 1][j - 1] + match) + l[i][j] = max(l[i - 1][j], l[i][j - 1], l[i - 1][j - 1] + match) seq = "" i, j = m, n @@ -57,17 +57,17 @@ def longest_common_subsequence(x: str, y: str): else: match = 0 - if L[i][j] == L[i - 1][j - 1] + match: + if l[i][j] == l[i - 1][j - 1] + match: if match == 1: seq = x[i - 1] + seq i -= 1 j -= 1 - elif L[i][j] == L[i - 1][j]: + elif l[i][j] == l[i - 1][j]: i -= 1 else: j -= 1 - return L[m][n], seq + return l[m][n], seq if __name__ == "__main__": diff --git a/dynamic_programming/longest_increasing_subsequence.py b/dynamic_programming/longest_increasing_subsequence.py index a029f9be7..6feed2352 100644 --- a/dynamic_programming/longest_increasing_subsequence.py +++ b/dynamic_programming/longest_increasing_subsequence.py @@ -34,12 +34,12 @@ def longest_subsequence(array: list[int]) -> list[int]: # This function is recu return array # Else pivot = array[0] - isFound = False + is_found = False i = 1 longest_subseq: list[int] = [] - while not isFound and i < array_length: + while not is_found and i < array_length: if array[i] < pivot: - isFound = True + is_found = True temp_array = [element for element in array[i:] if element >= array[i]] temp_array = longest_subsequence(temp_array) if len(temp_array) > len(longest_subseq): diff --git a/dynamic_programming/longest_increasing_subsequence_o(nlogn).py b/dynamic_programming/longest_increasing_subsequence_o(nlogn).py index af536f8bb..5e11d729f 100644 --- a/dynamic_programming/longest_increasing_subsequence_o(nlogn).py +++ b/dynamic_programming/longest_increasing_subsequence_o(nlogn).py @@ -7,7 +7,7 @@ from __future__ import annotations -def CeilIndex(v, l, r, key): # noqa: E741 +def ceil_index(v, l, r, key): # noqa: E741 while r - l > 1: m = (l + r) // 2 if v[m] >= key: @@ -17,16 +17,16 @@ def CeilIndex(v, l, r, key): # noqa: E741 return r -def LongestIncreasingSubsequenceLength(v: list[int]) -> int: +def longest_increasing_subsequence_length(v: list[int]) -> int: """ - >>> LongestIncreasingSubsequenceLength([2, 5, 3, 7, 11, 8, 10, 13, 6]) + >>> longest_increasing_subsequence_length([2, 5, 3, 7, 11, 8, 10, 13, 6]) 6 - >>> LongestIncreasingSubsequenceLength([]) + >>> longest_increasing_subsequence_length([]) 0 - >>> LongestIncreasingSubsequenceLength([0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, - ... 11, 7, 15]) + >>> longest_increasing_subsequence_length([0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, + ... 3, 11, 7, 15]) 6 - >>> LongestIncreasingSubsequenceLength([5, 4, 3, 2, 1]) + >>> longest_increasing_subsequence_length([5, 4, 3, 2, 1]) 1 """ if len(v) == 0: @@ -44,7 +44,7 @@ def LongestIncreasingSubsequenceLength(v: list[int]) -> int: tail[length] = v[i] length += 1 else: - tail[CeilIndex(tail, -1, length - 1, v[i])] = v[i] + tail[ceil_index(tail, -1, length - 1, v[i])] = v[i] return length diff --git a/dynamic_programming/matrix_chain_order.py b/dynamic_programming/matrix_chain_order.py index 9411bc704..d612aea7b 100644 --- a/dynamic_programming/matrix_chain_order.py +++ b/dynamic_programming/matrix_chain_order.py @@ -8,34 +8,34 @@ Space Complexity: O(n^2) """ -def MatrixChainOrder(array): - N = len(array) - Matrix = [[0 for x in range(N)] for x in range(N)] - Sol = [[0 for x in range(N)] for x in range(N)] +def matrix_chain_order(array): + n = len(array) + matrix = [[0 for x in range(n)] for x in range(n)] + sol = [[0 for x in range(n)] for x in range(n)] - for ChainLength in range(2, N): - for a in range(1, N - ChainLength + 1): - b = a + ChainLength - 1 + for chain_length in range(2, n): + for a in range(1, n - chain_length + 1): + b = a + chain_length - 1 - Matrix[a][b] = sys.maxsize + matrix[a][b] = sys.maxsize for c in range(a, b): cost = ( - Matrix[a][c] + Matrix[c + 1][b] + array[a - 1] * array[c] * array[b] + matrix[a][c] + matrix[c + 1][b] + array[a - 1] * array[c] * array[b] ) - if cost < Matrix[a][b]: - Matrix[a][b] = cost - Sol[a][b] = c - return Matrix, Sol + if cost < matrix[a][b]: + matrix[a][b] = cost + sol[a][b] = c + return matrix, sol # Print order of matrix with Ai as Matrix -def PrintOptimalSolution(OptimalSolution, i, j): +def print_optiomal_solution(optimal_solution, i, j): if i == j: print("A" + str(i), end=" ") else: print("(", end=" ") - PrintOptimalSolution(OptimalSolution, i, OptimalSolution[i][j]) - PrintOptimalSolution(OptimalSolution, OptimalSolution[i][j] + 1, j) + print_optiomal_solution(optimal_solution, i, optimal_solution[i][j]) + print_optiomal_solution(optimal_solution, optimal_solution[i][j] + 1, j) print(")", end=" ") @@ -44,10 +44,10 @@ def main(): n = len(array) # Size of matrix created from above array will be # 30*35 35*15 15*5 5*10 10*20 20*25 - Matrix, OptimalSolution = MatrixChainOrder(array) + matrix, optimal_solution = matrix_chain_order(array) - print("No. of Operation required: " + str(Matrix[1][n - 1])) - PrintOptimalSolution(OptimalSolution, 1, n - 1) + print("No. of Operation required: " + str(matrix[1][n - 1])) + print_optiomal_solution(optimal_solution, 1, n - 1) if __name__ == "__main__": diff --git a/dynamic_programming/max_sub_array.py b/dynamic_programming/max_sub_array.py index 3060010ef..42eca79a9 100644 --- a/dynamic_programming/max_sub_array.py +++ b/dynamic_programming/max_sub_array.py @@ -4,14 +4,14 @@ author : Mayank Kumar Jha (mk9440) from __future__ import annotations -def find_max_sub_array(A, low, high): +def find_max_sub_array(a, low, high): if low == high: - return low, high, A[low] + return low, high, a[low] else: mid = (low + high) // 2 - left_low, left_high, left_sum = find_max_sub_array(A, low, mid) - right_low, right_high, right_sum = find_max_sub_array(A, mid + 1, high) - cross_left, cross_right, cross_sum = find_max_cross_sum(A, low, mid, high) + left_low, left_high, left_sum = find_max_sub_array(a, low, mid) + right_low, right_high, right_sum = find_max_sub_array(a, mid + 1, high) + cross_left, cross_right, cross_sum = find_max_cross_sum(a, low, mid, high) if left_sum >= right_sum and left_sum >= cross_sum: return left_low, left_high, left_sum elif right_sum >= left_sum and right_sum >= cross_sum: @@ -20,18 +20,18 @@ def find_max_sub_array(A, low, high): return cross_left, cross_right, cross_sum -def find_max_cross_sum(A, low, mid, high): +def find_max_cross_sum(a, low, mid, high): left_sum, max_left = -999999999, -1 right_sum, max_right = -999999999, -1 summ = 0 for i in range(mid, low - 1, -1): - summ += A[i] + summ += a[i] if summ > left_sum: left_sum = summ max_left = i summ = 0 for i in range(mid + 1, high + 1): - summ += A[i] + summ += a[i] if summ > right_sum: right_sum = summ max_right = i diff --git a/dynamic_programming/minimum_coin_change.py b/dynamic_programming/minimum_coin_change.py index 2869b5857..848bd654d 100644 --- a/dynamic_programming/minimum_coin_change.py +++ b/dynamic_programming/minimum_coin_change.py @@ -7,7 +7,7 @@ https://www.hackerrank.com/challenges/coin-change/problem """ -def dp_count(S, n): +def dp_count(s, n): """ >>> dp_count([1, 2, 3], 4) 4 @@ -33,7 +33,7 @@ def dp_count(S, n): # Pick all coins one by one and update table[] values # after the index greater than or equal to the value of the # picked coin - for coin_val in S: + for coin_val in s: for j in range(coin_val, n + 1): table[j] += table[j - coin_val] diff --git a/dynamic_programming/minimum_partition.py b/dynamic_programming/minimum_partition.py index 8fad4ef30..3daa9767f 100644 --- a/dynamic_programming/minimum_partition.py +++ b/dynamic_programming/minimum_partition.py @@ -3,7 +3,7 @@ Partition a set into two subsets such that the difference of subset sums is mini """ -def findMin(arr): +def find_min(arr): n = len(arr) s = sum(arr) diff --git a/dynamic_programming/sum_of_subset.py b/dynamic_programming/sum_of_subset.py index a12177b57..77672b0b8 100644 --- a/dynamic_programming/sum_of_subset.py +++ b/dynamic_programming/sum_of_subset.py @@ -1,25 +1,25 @@ -def isSumSubset(arr, arrLen, requiredSum): +def is_sum_subset(arr, arr_len, required_sum): """ - >>> isSumSubset([2, 4, 6, 8], 4, 5) + >>> is_sum_subset([2, 4, 6, 8], 4, 5) False - >>> isSumSubset([2, 4, 6, 8], 4, 14) + >>> is_sum_subset([2, 4, 6, 8], 4, 14) True """ # a subset value says 1 if that subset sum can be formed else 0 # initially no subsets can be formed hence False/0 - subset = [[False for i in range(requiredSum + 1)] for i in range(arrLen + 1)] + subset = [[False for i in range(required_sum + 1)] for i in range(arr_len + 1)] # for each arr value, a sum of zero(0) can be formed by not taking any element # hence True/1 - for i in range(arrLen + 1): + for i in range(arr_len + 1): subset[i][0] = True # sum is not zero and set is empty then false - for i in range(1, requiredSum + 1): + for i in range(1, required_sum + 1): subset[0][i] = False - for i in range(1, arrLen + 1): - for j in range(1, requiredSum + 1): + for i in range(1, arr_len + 1): + for j in range(1, required_sum + 1): if arr[i - 1] > j: subset[i][j] = subset[i - 1][j] if arr[i - 1] <= j: @@ -28,7 +28,7 @@ def isSumSubset(arr, arrLen, requiredSum): # uncomment to print the subset # for i in range(arrLen+1): # print(subset[i]) - print(subset[arrLen][requiredSum]) + print(subset[arr_len][required_sum]) if __name__ == "__main__": diff --git a/fractals/sierpinski_triangle.py b/fractals/sierpinski_triangle.py index cf41ffa5f..8be2897c1 100644 --- a/fractals/sierpinski_triangle.py +++ b/fractals/sierpinski_triangle.py @@ -35,30 +35,30 @@ PROGNAME = "Sierpinski Triangle" points = [[-175, -125], [0, 175], [175, -125]] # size of triangle -def getMid(p1, p2): +def get_mid(p1, p2): return ((p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2) # find midpoint def triangle(points, depth): - myPen.up() - myPen.goto(points[0][0], points[0][1]) - myPen.down() - myPen.goto(points[1][0], points[1][1]) - myPen.goto(points[2][0], points[2][1]) - myPen.goto(points[0][0], points[0][1]) + my_pen.up() + my_pen.goto(points[0][0], points[0][1]) + my_pen.down() + my_pen.goto(points[1][0], points[1][1]) + my_pen.goto(points[2][0], points[2][1]) + my_pen.goto(points[0][0], points[0][1]) if depth > 0: triangle( - [points[0], getMid(points[0], points[1]), getMid(points[0], points[2])], + [points[0], get_mid(points[0], points[1]), get_mid(points[0], points[2])], depth - 1, ) triangle( - [points[1], getMid(points[0], points[1]), getMid(points[1], points[2])], + [points[1], get_mid(points[0], points[1]), get_mid(points[1], points[2])], depth - 1, ) triangle( - [points[2], getMid(points[2], points[1]), getMid(points[0], points[2])], + [points[2], get_mid(points[2], points[1]), get_mid(points[0], points[2])], depth - 1, ) @@ -69,8 +69,8 @@ if __name__ == "__main__": "right format for using this script: " "$python fractals.py " ) - myPen = turtle.Turtle() - myPen.ht() - myPen.speed(5) - myPen.pencolor("red") + my_pen = turtle.Turtle() + my_pen.ht() + my_pen.speed(5) + my_pen.pencolor("red") triangle(points, int(sys.argv[1])) diff --git a/geodesy/haversine_distance.py b/geodesy/haversine_distance.py index de8ac7f88..b601d2fd1 100644 --- a/geodesy/haversine_distance.py +++ b/geodesy/haversine_distance.py @@ -30,9 +30,9 @@ def haversine_distance(lat1: float, lon1: float, lat2: float, lon2: float) -> fl """ # CONSTANTS per WGS84 https://en.wikipedia.org/wiki/World_Geodetic_System # Distance in metres(m) - AXIS_A = 6378137.0 - AXIS_B = 6356752.314245 - RADIUS = 6378137 + AXIS_A = 6378137.0 # noqa: N806 + AXIS_B = 6356752.314245 # noqa: N806 + RADIUS = 6378137 # noqa: N806 # Equation parameters # Equation https://en.wikipedia.org/wiki/Haversine_formula#Formulation flattening = (AXIS_A - AXIS_B) / AXIS_A diff --git a/geodesy/lamberts_ellipsoidal_distance.py b/geodesy/lamberts_ellipsoidal_distance.py index bf8f1b9a5..d36d39953 100644 --- a/geodesy/lamberts_ellipsoidal_distance.py +++ b/geodesy/lamberts_ellipsoidal_distance.py @@ -45,9 +45,9 @@ def lamberts_ellipsoidal_distance( # CONSTANTS per WGS84 https://en.wikipedia.org/wiki/World_Geodetic_System # Distance in metres(m) - AXIS_A = 6378137.0 - AXIS_B = 6356752.314245 - EQUATORIAL_RADIUS = 6378137 + AXIS_A = 6378137.0 # noqa: N806 + AXIS_B = 6356752.314245 # noqa: N806 + EQUATORIAL_RADIUS = 6378137 # noqa: N806 # Equation Parameters # https://en.wikipedia.org/wiki/Geographical_distance#Lambert's_formula_for_long_lines @@ -62,22 +62,22 @@ def lamberts_ellipsoidal_distance( sigma = haversine_distance(lat1, lon1, lat2, lon2) / EQUATORIAL_RADIUS # Intermediate P and Q values - P_value = (b_lat1 + b_lat2) / 2 - Q_value = (b_lat2 - b_lat1) / 2 + p_value = (b_lat1 + b_lat2) / 2 + q_value = (b_lat2 - b_lat1) / 2 # Intermediate X value # X = (sigma - sin(sigma)) * sin^2Pcos^2Q / cos^2(sigma/2) - X_numerator = (sin(P_value) ** 2) * (cos(Q_value) ** 2) - X_demonimator = cos(sigma / 2) ** 2 - X_value = (sigma - sin(sigma)) * (X_numerator / X_demonimator) + x_numerator = (sin(p_value) ** 2) * (cos(q_value) ** 2) + x_demonimator = cos(sigma / 2) ** 2 + x_value = (sigma - sin(sigma)) * (x_numerator / x_demonimator) # Intermediate Y value # Y = (sigma + sin(sigma)) * cos^2Psin^2Q / sin^2(sigma/2) - Y_numerator = (cos(P_value) ** 2) * (sin(Q_value) ** 2) - Y_denominator = sin(sigma / 2) ** 2 - Y_value = (sigma + sin(sigma)) * (Y_numerator / Y_denominator) + y_numerator = (cos(p_value) ** 2) * (sin(q_value) ** 2) + y_denominator = sin(sigma / 2) ** 2 + y_value = (sigma + sin(sigma)) * (y_numerator / y_denominator) - return EQUATORIAL_RADIUS * (sigma - ((flattening / 2) * (X_value + Y_value))) + return EQUATORIAL_RADIUS * (sigma - ((flattening / 2) * (x_value + y_value))) if __name__ == "__main__": diff --git a/graphs/articulation_points.py b/graphs/articulation_points.py index 7197369de..d28045282 100644 --- a/graphs/articulation_points.py +++ b/graphs/articulation_points.py @@ -1,14 +1,14 @@ # Finding Articulation Points in Undirected Graph -def computeAP(l): # noqa: E741 +def compute_ap(l): # noqa: E741 n = len(l) - outEdgeCount = 0 + out_edge_count = 0 low = [0] * n visited = [False] * n - isArt = [False] * n + is_art = [False] * n - def dfs(root, at, parent, outEdgeCount): + def dfs(root, at, parent, out_edge_count): if parent == root: - outEdgeCount += 1 + out_edge_count += 1 visited[at] = True low[at] = at @@ -16,27 +16,27 @@ def computeAP(l): # noqa: E741 if to == parent: pass elif not visited[to]: - outEdgeCount = dfs(root, to, at, outEdgeCount) + out_edge_count = dfs(root, to, at, out_edge_count) low[at] = min(low[at], low[to]) # AP found via bridge if at < low[to]: - isArt[at] = True + is_art[at] = True # AP found via cycle if at == low[to]: - isArt[at] = True + is_art[at] = True else: low[at] = min(low[at], to) - return outEdgeCount + return out_edge_count for i in range(n): if not visited[i]: - outEdgeCount = 0 - outEdgeCount = dfs(i, i, -1, outEdgeCount) - isArt[i] = outEdgeCount > 1 + out_edge_count = 0 + out_edge_count = dfs(i, i, -1, out_edge_count) + is_art[i] = out_edge_count > 1 - for x in range(len(isArt)): - if isArt[x] is True: + for x in range(len(is_art)): + if is_art[x] is True: print(x) @@ -52,4 +52,4 @@ data = { 7: [6, 8], 8: [5, 7], } -computeAP(data) +compute_ap(data) diff --git a/graphs/basic_graphs.py b/graphs/basic_graphs.py index db0ef8e7b..b02e9af65 100644 --- a/graphs/basic_graphs.py +++ b/graphs/basic_graphs.py @@ -76,20 +76,20 @@ if __name__ == "__main__": """ -def dfs(G, s): - vis, S = {s}, [s] +def dfs(g, s): + vis, _s = {s}, [s] print(s) - while S: + while _s: flag = 0 - for i in G[S[-1]]: + for i in g[_s[-1]]: if i not in vis: - S.append(i) + _s.append(i) vis.add(i) flag = 1 print(i) break if not flag: - S.pop() + _s.pop() """ @@ -103,15 +103,15 @@ def dfs(G, s): """ -def bfs(G, s): - vis, Q = {s}, deque([s]) +def bfs(g, s): + vis, q = {s}, deque([s]) print(s) - while Q: - u = Q.popleft() - for v in G[u]: + while q: + u = q.popleft() + for v in g[u]: if v not in vis: vis.add(v) - Q.append(v) + q.append(v) print(v) @@ -127,10 +127,10 @@ def bfs(G, s): """ -def dijk(G, s): +def dijk(g, s): dist, known, path = {s: 0}, set(), {s: 0} while True: - if len(known) == len(G) - 1: + if len(known) == len(g) - 1: break mini = 100000 for i in dist: @@ -138,7 +138,7 @@ def dijk(G, s): mini = dist[i] u = i known.add(u) - for v in G[u]: + for v in g[u]: if v[0] not in known: if dist[u] + v[1] < dist.get(v[0], 100000): dist[v[0]] = dist[u] + v[1] @@ -155,27 +155,27 @@ def dijk(G, s): """ -def topo(G, ind=None, Q=None): - if Q is None: - Q = [1] +def topo(g, ind=None, q=None): + if q is None: + q = [1] if ind is None: - ind = [0] * (len(G) + 1) # SInce oth Index is ignored - for u in G: - for v in G[u]: + ind = [0] * (len(g) + 1) # SInce oth Index is ignored + for u in g: + for v in g[u]: ind[v] += 1 - Q = deque() - for i in G: + q = deque() + for i in g: if ind[i] == 0: - Q.append(i) - if len(Q) == 0: + q.append(i) + if len(q) == 0: return - v = Q.popleft() + v = q.popleft() print(v) - for w in G[v]: + for w in g[v]: ind[w] -= 1 if ind[w] == 0: - Q.append(w) - topo(G, ind, Q) + q.append(w) + topo(g, ind, q) """ @@ -206,9 +206,9 @@ def adjm(): """ -def floy(A_and_n): - (A, n) = A_and_n - dist = list(A) +def floy(a_and_n): + (a, n) = a_and_n + dist = list(a) path = [[0] * n for i in range(n)] for k in range(n): for i in range(n): @@ -231,10 +231,10 @@ def floy(A_and_n): """ -def prim(G, s): +def prim(g, s): dist, known, path = {s: 0}, set(), {s: 0} while True: - if len(known) == len(G) - 1: + if len(known) == len(g) - 1: break mini = 100000 for i in dist: @@ -242,7 +242,7 @@ def prim(G, s): mini = dist[i] u = i known.add(u) - for v in G[u]: + for v in g[u]: if v[0] not in known: if v[1] < dist.get(v[0], 100000): dist[v[0]] = v[1] @@ -279,16 +279,16 @@ def edglist(): """ -def krusk(E_and_n): +def krusk(e_and_n): # Sort edges on the basis of distance - (E, n) = E_and_n - E.sort(reverse=True, key=lambda x: x[2]) + (e, n) = e_and_n + e.sort(reverse=True, key=lambda x: x[2]) s = [{i} for i in range(1, n + 1)] while True: if len(s) == 1: break print(s) - x = E.pop() + x = e.pop() for i in range(len(s)): if x[0] in s[i]: break diff --git a/graphs/check_bipartite_graph_bfs.py b/graphs/check_bipartite_graph_bfs.py index b5203b4c5..552b7eee2 100644 --- a/graphs/check_bipartite_graph_bfs.py +++ b/graphs/check_bipartite_graph_bfs.py @@ -9,7 +9,7 @@ from queue import Queue -def checkBipartite(graph): +def check_bipartite(graph): queue = Queue() visited = [False] * len(graph) color = [-1] * len(graph) @@ -45,4 +45,4 @@ def checkBipartite(graph): if __name__ == "__main__": # Adjacency List of graph - print(checkBipartite({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]})) + print(check_bipartite({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]})) diff --git a/graphs/dijkstra.py b/graphs/dijkstra.py index d15fcbbfe..62c60f2c6 100644 --- a/graphs/dijkstra.py +++ b/graphs/dijkstra.py @@ -103,14 +103,14 @@ G3 = { "G": [["F", 1]], } -shortDistance = dijkstra(G, "E", "C") -print(shortDistance) # E -- 3 --> F -- 3 --> C == 6 +short_distance = dijkstra(G, "E", "C") +print(short_distance) # E -- 3 --> F -- 3 --> C == 6 -shortDistance = dijkstra(G2, "E", "F") -print(shortDistance) # E -- 3 --> F == 3 +short_distance = dijkstra(G2, "E", "F") +print(short_distance) # E -- 3 --> F == 3 -shortDistance = dijkstra(G3, "E", "F") -print(shortDistance) # E -- 2 --> G -- 1 --> F == 3 +short_distance = dijkstra(G3, "E", "F") +print(short_distance) # E -- 2 --> G -- 1 --> F == 3 if __name__ == "__main__": import doctest diff --git a/graphs/dijkstra_2.py b/graphs/dijkstra_2.py index 762884136..3170765bc 100644 --- a/graphs/dijkstra_2.py +++ b/graphs/dijkstra_2.py @@ -1,6 +1,6 @@ -def printDist(dist, V): +def print_dist(dist, v): print("\nVertex Distance") - for i in range(V): + for i in range(v): if dist[i] != float("inf"): print(i, "\t", int(dist[i]), end="\t") else: @@ -8,26 +8,26 @@ def printDist(dist, V): print() -def minDist(mdist, vset, V): - minVal = float("inf") - minInd = -1 - for i in range(V): - if (not vset[i]) and mdist[i] < minVal: - minInd = i - minVal = mdist[i] - return minInd +def min_dist(mdist, vset, v): + min_val = float("inf") + min_ind = -1 + for i in range(v): + if (not vset[i]) and mdist[i] < min_val: + min_ind = i + min_val = mdist[i] + return min_ind -def Dijkstra(graph, V, src): - mdist = [float("inf") for i in range(V)] - vset = [False for i in range(V)] +def dijkstra(graph, v, src): + mdist = [float("inf") for i in range(v)] + vset = [False for i in range(v)] mdist[src] = 0.0 - for i in range(V - 1): - u = minDist(mdist, vset, V) + for i in range(v - 1): + u = min_dist(mdist, vset, v) vset[u] = True - for v in range(V): + for v in range(v): if ( (not vset[v]) and graph[u][v] != float("inf") @@ -35,7 +35,7 @@ def Dijkstra(graph, V, src): ): mdist[v] = mdist[u] + graph[u][v] - printDist(mdist, V) + print_dist(mdist, v) if __name__ == "__main__": @@ -55,4 +55,4 @@ if __name__ == "__main__": graph[src][dst] = weight gsrc = int(input("\nEnter shortest path source:").strip()) - Dijkstra(graph, V, gsrc) + dijkstra(graph, V, gsrc) diff --git a/graphs/dijkstra_algorithm.py b/graphs/dijkstra_algorithm.py index 6b64834ac..122821a37 100644 --- a/graphs/dijkstra_algorithm.py +++ b/graphs/dijkstra_algorithm.py @@ -15,7 +15,7 @@ class PriorityQueue: self.array = [] self.pos = {} # To store the pos of node in array - def isEmpty(self): + def is_empty(self): return self.cur_size == 0 def min_heapify(self, idx): @@ -110,24 +110,24 @@ class Graph: self.par = [-1] * self.num_nodes # src is the source node self.dist[src] = 0 - Q = PriorityQueue() - Q.insert((0, src)) # (dist from src, node) + q = PriorityQueue() + q.insert((0, src)) # (dist from src, node) for u in self.adjList.keys(): if u != src: self.dist[u] = sys.maxsize # Infinity self.par[u] = -1 - while not Q.isEmpty(): - u = Q.extract_min() # Returns node with the min dist from source + while not q.is_empty(): + u = q.extract_min() # Returns node with the min dist from source # Update the distance of all the neighbours of u and # if their prev dist was INFINITY then push them in Q for v, w in self.adjList[u]: new_dist = self.dist[u] + w if self.dist[v] > new_dist: if self.dist[v] == sys.maxsize: - Q.insert((new_dist, v)) + q.insert((new_dist, v)) else: - Q.decrease_key((self.dist[v], v), new_dist) + q.decrease_key((self.dist[v], v), new_dist) self.dist[v] = new_dist self.par[v] = u diff --git a/graphs/edmonds_karp_multiple_source_and_sink.py b/graphs/edmonds_karp_multiple_source_and_sink.py index 0f359ff1a..070d758e6 100644 --- a/graphs/edmonds_karp_multiple_source_and_sink.py +++ b/graphs/edmonds_karp_multiple_source_and_sink.py @@ -1,15 +1,15 @@ class FlowNetwork: def __init__(self, graph, sources, sinks): - self.sourceIndex = None - self.sinkIndex = None + self.source_index = None + self.sink_index = None self.graph = graph - self._normalizeGraph(sources, sinks) - self.verticesCount = len(graph) - self.maximumFlowAlgorithm = None + self._normalize_graph(sources, sinks) + self.vertices_count = len(graph) + self.maximum_flow_algorithm = None # make only one source and one sink - def _normalizeGraph(self, sources, sinks): + def _normalize_graph(self, sources, sinks): if sources is int: sources = [sources] if sinks is int: @@ -18,54 +18,54 @@ class FlowNetwork: if len(sources) == 0 or len(sinks) == 0: return - self.sourceIndex = sources[0] - self.sinkIndex = sinks[0] + self.source_index = sources[0] + self.sink_index = sinks[0] # make fake vertex if there are more # than one source or sink if len(sources) > 1 or len(sinks) > 1: - maxInputFlow = 0 + max_input_flow = 0 for i in sources: - maxInputFlow += sum(self.graph[i]) + max_input_flow += sum(self.graph[i]) size = len(self.graph) + 1 for room in self.graph: room.insert(0, 0) self.graph.insert(0, [0] * size) for i in sources: - self.graph[0][i + 1] = maxInputFlow - self.sourceIndex = 0 + self.graph[0][i + 1] = max_input_flow + self.source_index = 0 size = len(self.graph) + 1 for room in self.graph: room.append(0) self.graph.append([0] * size) for i in sinks: - self.graph[i + 1][size - 1] = maxInputFlow - self.sinkIndex = size - 1 + self.graph[i + 1][size - 1] = max_input_flow + self.sink_index = size - 1 - def findMaximumFlow(self): - if self.maximumFlowAlgorithm is None: + def find_maximum_flow(self): + if self.maximum_flow_algorithm is None: raise Exception("You need to set maximum flow algorithm before.") - if self.sourceIndex is None or self.sinkIndex is None: + if self.source_index is None or self.sink_index is None: return 0 - self.maximumFlowAlgorithm.execute() - return self.maximumFlowAlgorithm.getMaximumFlow() + self.maximum_flow_algorithm.execute() + return self.maximum_flow_algorithm.getMaximumFlow() - def setMaximumFlowAlgorithm(self, Algorithm): - self.maximumFlowAlgorithm = Algorithm(self) + def set_maximum_flow_algorithm(self, algorithm): + self.maximum_flow_algorithm = algorithm(self) class FlowNetworkAlgorithmExecutor: - def __init__(self, flowNetwork): - self.flowNetwork = flowNetwork - self.verticesCount = flowNetwork.verticesCount - self.sourceIndex = flowNetwork.sourceIndex - self.sinkIndex = flowNetwork.sinkIndex + def __init__(self, flow_network): + self.flow_network = flow_network + self.verticies_count = flow_network.verticesCount + self.source_index = flow_network.sourceIndex + self.sink_index = flow_network.sinkIndex # it's just a reference, so you shouldn't change # it in your algorithms, use deep copy before doing that - self.graph = flowNetwork.graph + self.graph = flow_network.graph self.executed = False def execute(self): @@ -79,95 +79,96 @@ class FlowNetworkAlgorithmExecutor: class MaximumFlowAlgorithmExecutor(FlowNetworkAlgorithmExecutor): - def __init__(self, flowNetwork): - super().__init__(flowNetwork) + def __init__(self, flow_network): + super().__init__(flow_network) # use this to save your result - self.maximumFlow = -1 + self.maximum_flow = -1 - def getMaximumFlow(self): + def get_maximum_flow(self): if not self.executed: raise Exception("You should execute algorithm before using its result!") - return self.maximumFlow + return self.maximum_flow class PushRelabelExecutor(MaximumFlowAlgorithmExecutor): - def __init__(self, flowNetwork): - super().__init__(flowNetwork) + def __init__(self, flow_network): + super().__init__(flow_network) - self.preflow = [[0] * self.verticesCount for i in range(self.verticesCount)] + self.preflow = [[0] * self.verticies_count for i in range(self.verticies_count)] - self.heights = [0] * self.verticesCount - self.excesses = [0] * self.verticesCount + self.heights = [0] * self.verticies_count + self.excesses = [0] * self.verticies_count def _algorithm(self): - self.heights[self.sourceIndex] = self.verticesCount + self.heights[self.source_index] = self.verticies_count # push some substance to graph - for nextVertexIndex, bandwidth in enumerate(self.graph[self.sourceIndex]): - self.preflow[self.sourceIndex][nextVertexIndex] += bandwidth - self.preflow[nextVertexIndex][self.sourceIndex] -= bandwidth - self.excesses[nextVertexIndex] += bandwidth + for nextvertex_index, bandwidth in enumerate(self.graph[self.source_index]): + self.preflow[self.source_index][nextvertex_index] += bandwidth + self.preflow[nextvertex_index][self.source_index] -= bandwidth + self.excesses[nextvertex_index] += bandwidth # Relabel-to-front selection rule - verticesList = [ + vertices_list = [ i - for i in range(self.verticesCount) - if i != self.sourceIndex and i != self.sinkIndex + for i in range(self.verticies_count) + if i != self.source_index and i != self.sink_index ] # move through list i = 0 - while i < len(verticesList): - vertexIndex = verticesList[i] - previousHeight = self.heights[vertexIndex] - self.processVertex(vertexIndex) - if self.heights[vertexIndex] > previousHeight: + while i < len(vertices_list): + vertex_index = vertices_list[i] + previous_height = self.heights[vertex_index] + self.process_vertex(vertex_index) + if self.heights[vertex_index] > previous_height: # if it was relabeled, swap elements # and start from 0 index - verticesList.insert(0, verticesList.pop(i)) + vertices_list.insert(0, vertices_list.pop(i)) i = 0 else: i += 1 - self.maximumFlow = sum(self.preflow[self.sourceIndex]) + self.maximum_flow = sum(self.preflow[self.source_index]) - def processVertex(self, vertexIndex): - while self.excesses[vertexIndex] > 0: - for neighbourIndex in range(self.verticesCount): + def process_vertex(self, vertex_index): + while self.excesses[vertex_index] > 0: + for neighbour_index in range(self.verticies_count): # if it's neighbour and current vertex is higher if ( - self.graph[vertexIndex][neighbourIndex] - - self.preflow[vertexIndex][neighbourIndex] + self.graph[vertex_index][neighbour_index] + - self.preflow[vertex_index][neighbour_index] > 0 - and self.heights[vertexIndex] > self.heights[neighbourIndex] + and self.heights[vertex_index] > self.heights[neighbour_index] ): - self.push(vertexIndex, neighbourIndex) + self.push(vertex_index, neighbour_index) - self.relabel(vertexIndex) + self.relabel(vertex_index) - def push(self, fromIndex, toIndex): - preflowDelta = min( - self.excesses[fromIndex], - self.graph[fromIndex][toIndex] - self.preflow[fromIndex][toIndex], + def push(self, from_index, to_index): + preflow_delta = min( + self.excesses[from_index], + self.graph[from_index][to_index] - self.preflow[from_index][to_index], ) - self.preflow[fromIndex][toIndex] += preflowDelta - self.preflow[toIndex][fromIndex] -= preflowDelta - self.excesses[fromIndex] -= preflowDelta - self.excesses[toIndex] += preflowDelta + self.preflow[from_index][to_index] += preflow_delta + self.preflow[to_index][from_index] -= preflow_delta + self.excesses[from_index] -= preflow_delta + self.excesses[to_index] += preflow_delta - def relabel(self, vertexIndex): - minHeight = None - for toIndex in range(self.verticesCount): + def relabel(self, vertex_index): + min_height = None + for to_index in range(self.verticies_count): if ( - self.graph[vertexIndex][toIndex] - self.preflow[vertexIndex][toIndex] + self.graph[vertex_index][to_index] + - self.preflow[vertex_index][to_index] > 0 ): - if minHeight is None or self.heights[toIndex] < minHeight: - minHeight = self.heights[toIndex] + if min_height is None or self.heights[to_index] < min_height: + min_height = self.heights[to_index] - if minHeight is not None: - self.heights[vertexIndex] = minHeight + 1 + if min_height is not None: + self.heights[vertex_index] = min_height + 1 if __name__ == "__main__": @@ -184,10 +185,10 @@ if __name__ == "__main__": graph = [[0, 7, 0, 0], [0, 0, 6, 0], [0, 0, 0, 8], [9, 0, 0, 0]] # prepare our network - flowNetwork = FlowNetwork(graph, entrances, exits) + flow_network = FlowNetwork(graph, entrances, exits) # set algorithm - flowNetwork.setMaximumFlowAlgorithm(PushRelabelExecutor) + flow_network.set_maximum_flow_algorithm(PushRelabelExecutor) # and calculate - maximumFlow = flowNetwork.findMaximumFlow() + maximum_flow = flow_network.find_maximum_flow() - print(f"maximum flow is {maximumFlow}") + print(f"maximum flow is {maximum_flow}") diff --git a/graphs/eulerian_path_and_circuit_for_undirected_graph.py b/graphs/eulerian_path_and_circuit_for_undirected_graph.py index fa4f73abd..6c43c5d3e 100644 --- a/graphs/eulerian_path_and_circuit_for_undirected_graph.py +++ b/graphs/eulerian_path_and_circuit_for_undirected_graph.py @@ -50,21 +50,21 @@ def check_euler(graph, max_node): def main(): - G1 = {1: [2, 3, 4], 2: [1, 3], 3: [1, 2], 4: [1, 5], 5: [4]} - G2 = {1: [2, 3, 4, 5], 2: [1, 3], 3: [1, 2], 4: [1, 5], 5: [1, 4]} - G3 = {1: [2, 3, 4], 2: [1, 3, 4], 3: [1, 2], 4: [1, 2, 5], 5: [4]} - G4 = {1: [2, 3], 2: [1, 3], 3: [1, 2]} - G5 = { + g1 = {1: [2, 3, 4], 2: [1, 3], 3: [1, 2], 4: [1, 5], 5: [4]} + g2 = {1: [2, 3, 4, 5], 2: [1, 3], 3: [1, 2], 4: [1, 5], 5: [1, 4]} + g3 = {1: [2, 3, 4], 2: [1, 3, 4], 3: [1, 2], 4: [1, 2, 5], 5: [4]} + g4 = {1: [2, 3], 2: [1, 3], 3: [1, 2]} + g5 = { 1: [], 2: [] # all degree is zero } max_node = 10 - check_euler(G1, max_node) - check_euler(G2, max_node) - check_euler(G3, max_node) - check_euler(G4, max_node) - check_euler(G5, max_node) + check_euler(g1, max_node) + check_euler(g2, max_node) + check_euler(g3, max_node) + check_euler(g4, max_node) + check_euler(g5, max_node) if __name__ == "__main__": diff --git a/graphs/frequent_pattern_graph_miner.py b/graphs/frequent_pattern_graph_miner.py index 548ce3c54..50081afa6 100644 --- a/graphs/frequent_pattern_graph_miner.py +++ b/graphs/frequent_pattern_graph_miner.py @@ -151,16 +151,16 @@ def create_edge(nodes, graph, cluster, c1): def construct_graph(cluster, nodes): - X = cluster[max(cluster.keys())] + x = cluster[max(cluster.keys())] cluster[max(cluster.keys()) + 1] = "Header" graph = {} - for i in X: + for i in x: if tuple(["Header"]) in graph: - graph[tuple(["Header"])].append(X[i]) + graph[tuple(["Header"])].append(x[i]) else: - graph[tuple(["Header"])] = [X[i]] - for i in X: - graph[tuple(X[i])] = [["Header"]] + graph[tuple(["Header"])] = [x[i]] + for i in x: + graph[tuple(x[i])] = [["Header"]] i = 1 while i < max(cluster) - 1: create_edge(nodes, graph, cluster, i) @@ -168,7 +168,7 @@ def construct_graph(cluster, nodes): return graph -def myDFS(graph, start, end, path=None): +def my_dfs(graph, start, end, path=None): """ find different DFS walk from given node to Header node """ @@ -177,7 +177,7 @@ def myDFS(graph, start, end, path=None): paths.append(path) for node in graph[start]: if tuple(node) not in path: - myDFS(graph, tuple(node), end, path) + my_dfs(graph, tuple(node), end, path) def find_freq_subgraph_given_support(s, cluster, graph): @@ -186,23 +186,23 @@ def find_freq_subgraph_given_support(s, cluster, graph): """ k = int(s / 100 * (len(cluster) - 1)) for i in cluster[k].keys(): - myDFS(graph, tuple(cluster[k][i]), tuple(["Header"])) + my_dfs(graph, tuple(cluster[k][i]), tuple(["Header"])) def freq_subgraphs_edge_list(paths): """ returns Edge list for frequent subgraphs """ - freq_sub_EL = [] + freq_sub_el = [] for edges in paths: - EL = [] + el = [] for j in range(len(edges) - 1): temp = list(edges[j]) for e in temp: edge = (e[0], e[1]) - EL.append(edge) - freq_sub_EL.append(EL) - return freq_sub_EL + el.append(edge) + freq_sub_el.append(el) + return freq_sub_el def preprocess(edge_array): diff --git a/graphs/kahns_algorithm_long.py b/graphs/kahns_algorithm_long.py index fed7517a2..776ae3a2f 100644 --- a/graphs/kahns_algorithm_long.py +++ b/graphs/kahns_algorithm_long.py @@ -1,8 +1,8 @@ # Finding longest distance in Directed Acyclic Graph using KahnsAlgorithm -def longestDistance(graph): +def longest_distance(graph): indegree = [0] * len(graph) queue = [] - longDist = [1] * len(graph) + long_dist = [1] * len(graph) for key, values in graph.items(): for i in values: @@ -17,15 +17,15 @@ def longestDistance(graph): for x in graph[vertex]: indegree[x] -= 1 - if longDist[vertex] + 1 > longDist[x]: - longDist[x] = longDist[vertex] + 1 + if long_dist[vertex] + 1 > long_dist[x]: + long_dist[x] = long_dist[vertex] + 1 if indegree[x] == 0: queue.append(x) - print(max(longDist)) + print(max(long_dist)) # Adjacency list of Graph graph = {0: [2, 3, 4], 1: [2, 7], 2: [5], 3: [5, 7], 4: [7], 5: [6], 6: [7], 7: []} -longestDistance(graph) +longest_distance(graph) diff --git a/graphs/kahns_algorithm_topo.py b/graphs/kahns_algorithm_topo.py index bf9f90299..6879b047f 100644 --- a/graphs/kahns_algorithm_topo.py +++ b/graphs/kahns_algorithm_topo.py @@ -1,4 +1,4 @@ -def topologicalSort(graph): +def topological_sort(graph): """ Kahn's Algorithm is used to find Topological ordering of Directed Acyclic Graph using BFS @@ -33,4 +33,4 @@ def topologicalSort(graph): # Adjacency List of Graph graph = {0: [1, 2], 1: [3], 2: [3], 3: [4, 5], 4: [], 5: []} -topologicalSort(graph) +topological_sort(graph) diff --git a/graphs/minimum_spanning_tree_prims.py b/graphs/minimum_spanning_tree_prims.py index 16b428614..9b2c645f1 100644 --- a/graphs/minimum_spanning_tree_prims.py +++ b/graphs/minimum_spanning_tree_prims.py @@ -2,15 +2,15 @@ import sys from collections import defaultdict -def PrimsAlgorithm(l): # noqa: E741 +def prisms_algorithm(l): # noqa: E741 - nodePosition = [] + node_position = [] def get_position(vertex): - return nodePosition[vertex] + return node_position[vertex] def set_position(vertex, pos): - nodePosition[vertex] = pos + node_position[vertex] = pos def top_to_bottom(heap, start, size, positions): if start > size // 2 - 1: @@ -64,44 +64,44 @@ def PrimsAlgorithm(l): # noqa: E741 for i in range(start, -1, -1): top_to_bottom(heap, i, len(heap), positions) - def deleteMinimum(heap, positions): + def delete_minimum(heap, positions): temp = positions[0] heap[0] = sys.maxsize top_to_bottom(heap, 0, len(heap), positions) return temp visited = [0 for i in range(len(l))] - Nbr_TV = [-1 for i in range(len(l))] # Neighboring Tree Vertex of selected vertex + nbr_tv = [-1 for i in range(len(l))] # Neighboring Tree Vertex of selected vertex # Minimum Distance of explored vertex with neighboring vertex of partial tree # formed in graph - Distance_TV = [] # Heap of Distance of vertices from their neighboring vertex - Positions = [] + distance_tv = [] # Heap of Distance of vertices from their neighboring vertex + positions = [] for x in range(len(l)): p = sys.maxsize - Distance_TV.append(p) - Positions.append(x) - nodePosition.append(x) + distance_tv.append(p) + positions.append(x) + node_position.append(x) - TreeEdges = [] + tree_edges = [] visited[0] = 1 - Distance_TV[0] = sys.maxsize + distance_tv[0] = sys.maxsize for x in l[0]: - Nbr_TV[x[0]] = 0 - Distance_TV[x[0]] = x[1] - heapify(Distance_TV, Positions) + nbr_tv[x[0]] = 0 + distance_tv[x[0]] = x[1] + heapify(distance_tv, positions) for i in range(1, len(l)): - vertex = deleteMinimum(Distance_TV, Positions) + vertex = delete_minimum(distance_tv, positions) if visited[vertex] == 0: - TreeEdges.append((Nbr_TV[vertex], vertex)) + tree_edges.append((nbr_tv[vertex], vertex)) visited[vertex] = 1 for v in l[vertex]: - if visited[v[0]] == 0 and v[1] < Distance_TV[get_position(v[0])]: - Distance_TV[get_position(v[0])] = v[1] - bottom_to_top(v[1], get_position(v[0]), Distance_TV, Positions) - Nbr_TV[v[0]] = vertex - return TreeEdges + if visited[v[0]] == 0 and v[1] < distance_tv[get_position(v[0])]: + distance_tv[get_position(v[0])] = v[1] + bottom_to_top(v[1], get_position(v[0]), distance_tv, positions) + nbr_tv[v[0]] = vertex + return tree_edges if __name__ == "__main__": # pragma: no cover @@ -113,4 +113,4 @@ if __name__ == "__main__": # pragma: no cover l = [int(x) for x in input().strip().split()] # noqa: E741 adjlist[l[0]].append([l[1], l[2]]) adjlist[l[1]].append([l[0], l[2]]) - print(PrimsAlgorithm(adjlist)) + print(prisms_algorithm(adjlist)) diff --git a/graphs/multi_heuristic_astar.py b/graphs/multi_heuristic_astar.py index 8607f51d8..e16a98393 100644 --- a/graphs/multi_heuristic_astar.py +++ b/graphs/multi_heuristic_astar.py @@ -55,21 +55,21 @@ class PriorityQueue: return (priority, item) -def consistent_heuristic(P: TPos, goal: TPos): +def consistent_heuristic(p: TPos, goal: TPos): # euclidean distance - a = np.array(P) + a = np.array(p) b = np.array(goal) return np.linalg.norm(a - b) -def heuristic_2(P: TPos, goal: TPos): +def heuristic_2(p: TPos, goal: TPos): # integer division by time variable - return consistent_heuristic(P, goal) // t + return consistent_heuristic(p, goal) // t -def heuristic_1(P: TPos, goal: TPos): +def heuristic_1(p: TPos, goal: TPos): # manhattan distance - return abs(P[0] - goal[0]) + abs(P[1] - goal[1]) + return abs(p[0] - goal[0]) + abs(p[1] - goal[1]) def key(start: TPos, i: int, goal: TPos, g_function: dict[TPos, float]): diff --git a/graphs/scc_kosaraju.py b/graphs/scc_kosaraju.py index fa182aa2f..ea9d35282 100644 --- a/graphs/scc_kosaraju.py +++ b/graphs/scc_kosaraju.py @@ -2,7 +2,7 @@ from __future__ import annotations def dfs(u): - global graph, reversedGraph, scc, component, visit, stack + global graph, reversed_graph, scc, component, visit, stack if visit[u]: return visit[u] = True @@ -12,17 +12,17 @@ def dfs(u): def dfs2(u): - global graph, reversedGraph, scc, component, visit, stack + global graph, reversed_graph, scc, component, visit, stack if visit[u]: return visit[u] = True component.append(u) - for v in reversedGraph[u]: + for v in reversed_graph[u]: dfs2(v) def kosaraju(): - global graph, reversedGraph, scc, component, visit, stack + global graph, reversed_graph, scc, component, visit, stack for i in range(n): dfs(i) visit = [False] * n @@ -40,12 +40,12 @@ if __name__ == "__main__": 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 + reversed_graph: 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) + reversed_graph[v].append(u) stack: list[int] = [] visit: list[bool] = [False] * n diff --git a/graphs/tests/test_min_spanning_tree_prim.py b/graphs/tests/test_min_spanning_tree_prim.py index 048fbf595..91feab28f 100644 --- a/graphs/tests/test_min_spanning_tree_prim.py +++ b/graphs/tests/test_min_spanning_tree_prim.py @@ -1,6 +1,6 @@ from collections import defaultdict -from graphs.minimum_spanning_tree_prims import PrimsAlgorithm as mst +from graphs.minimum_spanning_tree_prims import prisms_algorithm as mst def test_prim_successful_result(): diff --git a/hashes/adler32.py b/hashes/adler32.py index 4a61b97e3..80229f046 100644 --- a/hashes/adler32.py +++ b/hashes/adler32.py @@ -20,7 +20,7 @@ def adler32(plain_text: str) -> int: >>> adler32('go adler em all') 708642122 """ - MOD_ADLER = 65521 + MOD_ADLER = 65521 # noqa: N806 a = 1 b = 0 for plain_chr in plain_text: diff --git a/hashes/chaos_machine.py b/hashes/chaos_machine.py index a6d476eb7..69313fbb2 100644 --- a/hashes/chaos_machine.py +++ b/hashes/chaos_machine.py @@ -43,11 +43,11 @@ def pull(): global buffer_space, params_space, machine_time, K, m, t # PRNG (Xorshift by George Marsaglia) - def xorshift(X, Y): - X ^= Y >> 13 - Y ^= X << 17 - X ^= Y >> 5 - return X + def xorshift(x, y): + x ^= y >> 13 + y ^= x << 17 + x ^= y >> 5 + return x # Choosing Dynamical Systems (Increment) key = machine_time % m @@ -63,13 +63,13 @@ def pull(): params_space[key] = (machine_time * 0.01 + r * 1.01) % 1 + 3 # Choosing Chaotic Data - X = int(buffer_space[(key + 2) % m] * (10**10)) - Y = int(buffer_space[(key - 2) % m] * (10**10)) + x = int(buffer_space[(key + 2) % m] * (10**10)) + y = int(buffer_space[(key - 2) % m] * (10**10)) # Machine Time machine_time += 1 - return xorshift(X, Y) % 0xFFFFFFFF + return xorshift(x, y) % 0xFFFFFFFF def reset(): diff --git a/hashes/hamming_code.py b/hashes/hamming_code.py index ac20fe03b..a62d092a1 100644 --- a/hashes/hamming_code.py +++ b/hashes/hamming_code.py @@ -68,177 +68,177 @@ def text_from_bits(bits, encoding="utf-8", errors="surrogatepass"): # Functions of hamming code------------------------------------------- -def emitterConverter(sizePar, data): +def emitter_converter(size_par, data): """ - :param sizePar: how many parity bits the message must have + :param size_par: how many parity bits the message must have :param data: information bits :return: message to be transmitted by unreliable medium - bits of information merged with parity bits - >>> emitterConverter(4, "101010111111") + >>> emitter_converter(4, "101010111111") ['1', '1', '1', '1', '0', '1', '0', '0', '1', '0', '1', '1', '1', '1', '1', '1'] """ - if sizePar + len(data) <= 2**sizePar - (len(data) - 1): + if size_par + len(data) <= 2**size_par - (len(data) - 1): print("ERROR - size of parity don't match with size of data") exit(0) - dataOut = [] + data_out = [] parity = [] - binPos = [bin(x)[2:] for x in range(1, sizePar + len(data) + 1)] + bin_pos = [bin(x)[2:] for x in range(1, size_par + len(data) + 1)] # sorted information data for the size of the output data - dataOrd = [] + data_ord = [] # data position template + parity - dataOutGab = [] + data_out_gab = [] # parity bit counter - qtdBP = 0 + qtd_bp = 0 # counter position of data bits - contData = 0 + cont_data = 0 - for x in range(1, sizePar + len(data) + 1): + for x in range(1, size_par + len(data) + 1): # Performs a template of bit positions - who should be given, # and who should be parity - if qtdBP < sizePar: + if qtd_bp < size_par: if (np.log(x) / np.log(2)).is_integer(): - dataOutGab.append("P") - qtdBP = qtdBP + 1 + data_out_gab.append("P") + qtd_bp = qtd_bp + 1 else: - dataOutGab.append("D") + data_out_gab.append("D") else: - dataOutGab.append("D") + data_out_gab.append("D") # Sorts the data to the new output size - if dataOutGab[-1] == "D": - dataOrd.append(data[contData]) - contData += 1 + if data_out_gab[-1] == "D": + data_ord.append(data[cont_data]) + cont_data += 1 else: - dataOrd.append(None) + data_ord.append(None) # Calculates parity - qtdBP = 0 # parity bit counter - for bp in range(1, sizePar + 1): + qtd_bp = 0 # parity bit counter + for bp in range(1, size_par + 1): # Bit counter one for a given parity - contBO = 0 + cont_bo = 0 # counter to control the loop reading - contLoop = 0 - for x in dataOrd: + cont_loop = 0 + for x in data_ord: if x is not None: try: - aux = (binPos[contLoop])[-1 * (bp)] + aux = (bin_pos[cont_loop])[-1 * (bp)] except IndexError: aux = "0" if aux == "1": if x == "1": - contBO += 1 - contLoop += 1 - parity.append(contBO % 2) + cont_bo += 1 + cont_loop += 1 + parity.append(cont_bo % 2) - qtdBP += 1 + qtd_bp += 1 # Mount the message - ContBP = 0 # parity bit counter - for x in range(0, sizePar + len(data)): - if dataOrd[x] is None: - dataOut.append(str(parity[ContBP])) - ContBP += 1 + cont_bp = 0 # parity bit counter + for x in range(0, size_par + len(data)): + if data_ord[x] is None: + data_out.append(str(parity[cont_bp])) + cont_bp += 1 else: - dataOut.append(dataOrd[x]) + data_out.append(data_ord[x]) - return dataOut + return data_out -def receptorConverter(sizePar, data): +def receptor_converter(size_par, data): """ - >>> receptorConverter(4, "1111010010111111") + >>> receptor_converter(4, "1111010010111111") (['1', '0', '1', '0', '1', '0', '1', '1', '1', '1', '1', '1'], True) """ # data position template + parity - dataOutGab = [] + data_out_gab = [] # Parity bit counter - qtdBP = 0 + qtd_bp = 0 # Counter p data bit reading - contData = 0 + cont_data = 0 # list of parity received - parityReceived = [] - dataOutput = [] + parity_received = [] + data_output = [] for x in range(1, len(data) + 1): # Performs a template of bit positions - who should be given, # and who should be parity - if qtdBP < sizePar and (np.log(x) / np.log(2)).is_integer(): - dataOutGab.append("P") - qtdBP = qtdBP + 1 + if qtd_bp < size_par and (np.log(x) / np.log(2)).is_integer(): + data_out_gab.append("P") + qtd_bp = qtd_bp + 1 else: - dataOutGab.append("D") + data_out_gab.append("D") # Sorts the data to the new output size - if dataOutGab[-1] == "D": - dataOutput.append(data[contData]) + if data_out_gab[-1] == "D": + data_output.append(data[cont_data]) else: - parityReceived.append(data[contData]) - contData += 1 + parity_received.append(data[cont_data]) + cont_data += 1 # -----------calculates the parity with the data - dataOut = [] + data_out = [] parity = [] - binPos = [bin(x)[2:] for x in range(1, sizePar + len(dataOutput) + 1)] + bin_pos = [bin(x)[2:] for x in range(1, size_par + len(data_output) + 1)] # sorted information data for the size of the output data - dataOrd = [] + data_ord = [] # Data position feedback + parity - dataOutGab = [] + data_out_gab = [] # Parity bit counter - qtdBP = 0 + qtd_bp = 0 # Counter p data bit reading - contData = 0 + cont_data = 0 - for x in range(1, sizePar + len(dataOutput) + 1): + for x in range(1, size_par + len(data_output) + 1): # Performs a template position of bits - who should be given, # and who should be parity - if qtdBP < sizePar and (np.log(x) / np.log(2)).is_integer(): - dataOutGab.append("P") - qtdBP = qtdBP + 1 + if qtd_bp < size_par and (np.log(x) / np.log(2)).is_integer(): + data_out_gab.append("P") + qtd_bp = qtd_bp + 1 else: - dataOutGab.append("D") + data_out_gab.append("D") # Sorts the data to the new output size - if dataOutGab[-1] == "D": - dataOrd.append(dataOutput[contData]) - contData += 1 + if data_out_gab[-1] == "D": + data_ord.append(data_output[cont_data]) + cont_data += 1 else: - dataOrd.append(None) + data_ord.append(None) # Calculates parity - qtdBP = 0 # parity bit counter - for bp in range(1, sizePar + 1): + qtd_bp = 0 # parity bit counter + for bp in range(1, size_par + 1): # Bit counter one for a certain parity - contBO = 0 + cont_bo = 0 # Counter to control loop reading - contLoop = 0 - for x in dataOrd: + cont_loop = 0 + for x in data_ord: if x is not None: try: - aux = (binPos[contLoop])[-1 * (bp)] + aux = (bin_pos[cont_loop])[-1 * (bp)] except IndexError: aux = "0" if aux == "1" and x == "1": - contBO += 1 - contLoop += 1 - parity.append(str(contBO % 2)) + cont_bo += 1 + cont_loop += 1 + parity.append(str(cont_bo % 2)) - qtdBP += 1 + qtd_bp += 1 # Mount the message - ContBP = 0 # Parity bit counter - for x in range(0, sizePar + len(dataOutput)): - if dataOrd[x] is None: - dataOut.append(str(parity[ContBP])) - ContBP += 1 + cont_bp = 0 # Parity bit counter + for x in range(0, size_par + len(data_output)): + if data_ord[x] is None: + data_out.append(str(parity[cont_bp])) + cont_bp += 1 else: - dataOut.append(dataOrd[x]) + data_out.append(data_ord[x]) - ack = parityReceived == parity - return dataOutput, ack + ack = parity_received == parity + return data_output, ack # --------------------------------------------------------------------- diff --git a/hashes/md5.py b/hashes/md5.py index c56c073cc..2020bf2e5 100644 --- a/hashes/md5.py +++ b/hashes/md5.py @@ -1,7 +1,7 @@ import math -def rearrange(bitString32): +def rearrange(bit_string_32): """[summary] Regroups the given binary string. @@ -17,21 +17,21 @@ def rearrange(bitString32): 'pqrstuvwhijklmno90abcdfg12345678' """ - if len(bitString32) != 32: + if len(bit_string_32) != 32: raise ValueError("Need length 32") - newString = "" + new_string = "" for i in [3, 2, 1, 0]: - newString += bitString32[8 * i : 8 * i + 8] - return newString + new_string += bit_string_32[8 * i : 8 * i + 8] + return new_string -def reformatHex(i): +def reformat_hex(i): """[summary] Converts the given integer into 8-digit hex number. Arguments: i {[int]} -- [integer] - >>> reformatHex(666) + >>> reformat_hex(666) '9a020000' """ @@ -42,7 +42,7 @@ def reformatHex(i): return thing -def pad(bitString): +def pad(bit_string): """[summary] Fills up the binary string to a 512 bit binary string @@ -52,33 +52,33 @@ def pad(bitString): Returns: [string] -- [binary string] """ - startLength = len(bitString) - bitString += "1" - while len(bitString) % 512 != 448: - bitString += "0" - lastPart = format(startLength, "064b") - bitString += rearrange(lastPart[32:]) + rearrange(lastPart[:32]) - return bitString + start_length = len(bit_string) + bit_string += "1" + while len(bit_string) % 512 != 448: + bit_string += "0" + last_part = format(start_length, "064b") + bit_string += rearrange(last_part[32:]) + rearrange(last_part[:32]) + return bit_string -def getBlock(bitString): +def get_block(bit_string): """[summary] Iterator: Returns by each call a list of length 16 with the 32 bit integer blocks. Arguments: - bitString {[string]} -- [binary string >= 512] + bit_string {[string]} -- [binary string >= 512] """ - currPos = 0 - while currPos < len(bitString): - currPart = bitString[currPos : currPos + 512] - mySplits = [] + curr_pos = 0 + while curr_pos < len(bit_string): + curr_part = bit_string[curr_pos : curr_pos + 512] + my_splits = [] for i in range(16): - mySplits.append(int(rearrange(currPart[32 * i : 32 * i + 32]), 2)) - yield mySplits - currPos += 512 + my_splits.append(int(rearrange(curr_part[32 * i : 32 * i + 32]), 2)) + yield my_splits + curr_pos += 512 def not32(i): @@ -101,7 +101,7 @@ def leftrot32(i, s): return (i << s) ^ (i >> (32 - s)) -def md5me(testString): +def md5me(test_string): """[summary] Returns a 32-bit hash code of the string 'testString' @@ -110,7 +110,7 @@ def md5me(testString): """ bs = "" - for i in testString: + for i in test_string: bs += format(ord(i), "08b") bs = pad(bs) @@ -188,37 +188,37 @@ def md5me(testString): 21, ] - for m in getBlock(bs): - A = a0 - B = b0 - C = c0 - D = d0 + for m in get_block(bs): + a = a0 + b = b0 + c = c0 + d = d0 for i in range(64): if i <= 15: # f = (B & C) | (not32(B) & D) - f = D ^ (B & (C ^ D)) + f = d ^ (b & (c ^ d)) g = i elif i <= 31: # f = (D & B) | (not32(D) & C) - f = C ^ (D & (B ^ C)) + f = c ^ (d & (b ^ c)) g = (5 * i + 1) % 16 elif i <= 47: - f = B ^ C ^ D + f = b ^ c ^ d g = (3 * i + 5) % 16 else: - f = C ^ (B | not32(D)) + f = c ^ (b | not32(d)) g = (7 * i) % 16 - dtemp = D - D = C - C = B - B = sum32(B, leftrot32((A + f + tvals[i] + m[g]) % 2**32, s[i])) - A = dtemp - a0 = sum32(a0, A) - b0 = sum32(b0, B) - c0 = sum32(c0, C) - d0 = sum32(d0, D) + dtemp = d + d = c + c = b + b = sum32(b, leftrot32((a + f + tvals[i] + m[g]) % 2**32, s[i])) + a = dtemp + a0 = sum32(a0, a) + b0 = sum32(b0, b) + c0 = sum32(c0, c) + d0 = sum32(d0, d) - digest = reformatHex(a0) + reformatHex(b0) + reformatHex(c0) + reformatHex(d0) + digest = reformat_hex(a0) + reformat_hex(b0) + reformat_hex(c0) + reformat_hex(d0) return digest diff --git a/hashes/sha1.py b/hashes/sha1.py index dde1efc55..b19e0cfaf 100644 --- a/hashes/sha1.py +++ b/hashes/sha1.py @@ -133,7 +133,7 @@ class SHA1HashTest(unittest.TestCase): Test class for the SHA1Hash class. Inherits the TestCase class from unittest """ - def testMatchHashes(self): + def testMatchHashes(self): # noqa: N802 msg = bytes("Test String", "utf-8") self.assertEqual(SHA1Hash(msg).final_hash(), hashlib.sha1(msg).hexdigest()) diff --git a/hashes/sha256.py b/hashes/sha256.py index 9d4f250fe..98f7c096e 100644 --- a/hashes/sha256.py +++ b/hashes/sha256.py @@ -157,14 +157,14 @@ class SHA256: ) % 0x100000000 # Compression - S1 = self.ror(e, 6) ^ self.ror(e, 11) ^ self.ror(e, 25) + s1 = self.ror(e, 6) ^ self.ror(e, 11) ^ self.ror(e, 25) ch = (e & f) ^ ((~e & (0xFFFFFFFF)) & g) temp1 = ( - h + S1 + ch + self.round_constants[index] + words[index] + h + s1 + ch + self.round_constants[index] + words[index] ) % 0x100000000 - S0 = self.ror(a, 2) ^ self.ror(a, 13) ^ self.ror(a, 22) + s0 = self.ror(a, 2) ^ self.ror(a, 13) ^ self.ror(a, 22) maj = (a & b) ^ (a & c) ^ (b & c) - temp2 = (S0 + maj) % 0x100000000 + temp2 = (s0 + maj) % 0x100000000 h, g, f, e, d, c, b, a = ( g, diff --git a/linear_algebra/src/power_iteration.py b/linear_algebra/src/power_iteration.py index 4b866331b..24fbd9a5e 100644 --- a/linear_algebra/src/power_iteration.py +++ b/linear_algebra/src/power_iteration.py @@ -63,8 +63,8 @@ def power_iteration( vector = w / np.linalg.norm(w) # Find rayleigh quotient # (faster than usual b/c we know vector is normalized already) - vectorH = vector.conj().T if is_complex else vector.T - lambda_ = np.dot(vectorH, np.dot(input_matrix, vector)) + vector_h = vector.conj().T if is_complex else vector.T + lambda_ = np.dot(vector_h, np.dot(input_matrix, vector)) # Check convergence. error = np.abs(lambda_ - lambda_previous) / lambda_ diff --git a/linear_algebra/src/rayleigh_quotient.py b/linear_algebra/src/rayleigh_quotient.py index 78083aa75..4773429cb 100644 --- a/linear_algebra/src/rayleigh_quotient.py +++ b/linear_algebra/src/rayleigh_quotient.py @@ -26,7 +26,7 @@ def is_hermitian(matrix: np.ndarray) -> bool: return np.array_equal(matrix, matrix.conjugate().T) -def rayleigh_quotient(A: np.ndarray, v: np.ndarray) -> Any: +def rayleigh_quotient(a: np.ndarray, v: np.ndarray) -> Any: """ Returns the Rayleigh quotient of a Hermitian matrix A and vector v. @@ -45,20 +45,20 @@ def rayleigh_quotient(A: np.ndarray, v: np.ndarray) -> Any: array([[3.]]) """ v_star = v.conjugate().T - v_star_dot = v_star.dot(A) + v_star_dot = v_star.dot(a) assert isinstance(v_star_dot, np.ndarray) return (v_star_dot.dot(v)) / (v_star.dot(v)) def tests() -> None: - A = np.array([[2, 2 + 1j, 4], [2 - 1j, 3, 1j], [4, -1j, 1]]) + a = np.array([[2, 2 + 1j, 4], [2 - 1j, 3, 1j], [4, -1j, 1]]) v = np.array([[1], [2], [3]]) - assert is_hermitian(A), f"{A} is not hermitian." - print(rayleigh_quotient(A, v)) + assert is_hermitian(a), f"{a} is not hermitian." + print(rayleigh_quotient(a, v)) - A = np.array([[1, 2, 4], [2, 3, -1], [4, -1, 1]]) - assert is_hermitian(A), f"{A} is not hermitian." - assert rayleigh_quotient(A, v) == float(3) + a = np.array([[1, 2, 4], [2, 3, -1], [4, -1, 1]]) + assert is_hermitian(a), f"{a} is not hermitian." + assert rayleigh_quotient(a, v) == float(3) if __name__ == "__main__": diff --git a/linear_algebra/src/test_linear_algebra.py b/linear_algebra/src/test_linear_algebra.py index 724ceef25..97c06cb44 100644 --- a/linear_algebra/src/test_linear_algebra.py +++ b/linear_algebra/src/test_linear_algebra.py @@ -85,13 +85,13 @@ class Test(unittest.TestCase): self.assertEqual(str(x * 3.0), "(3.0,6.0,9.0)") self.assertEqual((a * b), 0) - def test_zeroVector(self) -> None: + def test_zero_vector(self) -> None: """ test for global function zero_vector() """ self.assertTrue(str(zero_vector(10)).count("0") == 10) - def test_unitBasisVector(self) -> None: + def test_unit_basis_vector(self) -> None: """ test for global function unit_basis_vector() """ @@ -113,7 +113,7 @@ class Test(unittest.TestCase): y = x.copy() self.assertEqual(str(x), str(y)) - def test_changeComponent(self) -> None: + def test_change_component(self) -> None: """ test for method change_component() """ @@ -126,77 +126,77 @@ class Test(unittest.TestCase): """ test for Matrix method str() """ - A = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) - self.assertEqual("|1,2,3|\n|2,4,5|\n|6,7,8|\n", str(A)) + a = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) + self.assertEqual("|1,2,3|\n|2,4,5|\n|6,7,8|\n", str(a)) def test_minor(self) -> None: """ test for Matrix method minor() """ - A = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) + a = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) minors = [[-3, -14, -10], [-5, -10, -5], [-2, -1, 0]] - for x in range(A.height()): - for y in range(A.width()): - self.assertEqual(minors[x][y], A.minor(x, y)) + for x in range(a.height()): + for y in range(a.width()): + self.assertEqual(minors[x][y], a.minor(x, y)) def test_cofactor(self) -> None: """ test for Matrix method cofactor() """ - A = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) + a = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) cofactors = [[-3, 14, -10], [5, -10, 5], [-2, 1, 0]] - for x in range(A.height()): - for y in range(A.width()): - self.assertEqual(cofactors[x][y], A.cofactor(x, y)) + for x in range(a.height()): + for y in range(a.width()): + self.assertEqual(cofactors[x][y], a.cofactor(x, y)) def test_determinant(self) -> None: """ test for Matrix method determinant() """ - A = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) - self.assertEqual(-5, A.determinant()) + a = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) + self.assertEqual(-5, a.determinant()) def test__mul__matrix(self) -> None: """ test for Matrix * operator """ - A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]], 3, 3) + a = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]], 3, 3) x = Vector([1, 2, 3]) - self.assertEqual("(14,32,50)", str(A * x)) - self.assertEqual("|2,4,6|\n|8,10,12|\n|14,16,18|\n", str(A * 2)) + self.assertEqual("(14,32,50)", str(a * x)) + self.assertEqual("|2,4,6|\n|8,10,12|\n|14,16,18|\n", str(a * 2)) def test_change_component_matrix(self) -> None: """ test for Matrix method change_component() """ - A = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) - A.change_component(0, 2, 5) - self.assertEqual("|1,2,5|\n|2,4,5|\n|6,7,8|\n", str(A)) + a = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) + a.change_component(0, 2, 5) + self.assertEqual("|1,2,5|\n|2,4,5|\n|6,7,8|\n", str(a)) def test_component_matrix(self) -> None: """ test for Matrix method component() """ - A = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) - self.assertEqual(7, A.component(2, 1), 0.01) + a = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) + self.assertEqual(7, a.component(2, 1), 0.01) def test__add__matrix(self) -> None: """ test for Matrix + operator """ - A = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) - B = Matrix([[1, 2, 7], [2, 4, 5], [6, 7, 10]], 3, 3) - self.assertEqual("|2,4,10|\n|4,8,10|\n|12,14,18|\n", str(A + B)) + a = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) + b = Matrix([[1, 2, 7], [2, 4, 5], [6, 7, 10]], 3, 3) + self.assertEqual("|2,4,10|\n|4,8,10|\n|12,14,18|\n", str(a + b)) def test__sub__matrix(self) -> None: """ test for Matrix - operator """ - A = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) - B = Matrix([[1, 2, 7], [2, 4, 5], [6, 7, 10]], 3, 3) - self.assertEqual("|0,0,-4|\n|0,0,0|\n|0,0,-2|\n", str(A - B)) + a = Matrix([[1, 2, 3], [2, 4, 5], [6, 7, 8]], 3, 3) + b = Matrix([[1, 2, 7], [2, 4, 5], [6, 7, 10]], 3, 3) + self.assertEqual("|0,0,-4|\n|0,0,0|\n|0,0,-2|\n", str(a - b)) - def test_squareZeroMatrix(self) -> None: + def test_square_zero_matrix(self) -> None: """ test for global function square_zero_matrix() """ diff --git a/machine_learning/decision_tree.py b/machine_learning/decision_tree.py index ace6fb0fa..4a86e5322 100644 --- a/machine_learning/decision_tree.py +++ b/machine_learning/decision_tree.py @@ -6,7 +6,7 @@ Output: The decision tree maps a real number input to a real number output. import numpy as np -class Decision_Tree: +class DecisionTree: def __init__(self, depth=5, min_leaf_size=5): self.depth = depth self.decision_boundary = 0 @@ -22,17 +22,17 @@ class Decision_Tree: @param prediction: a floating point value return value: mean_squared_error calculates the error if prediction is used to estimate the labels - >>> tester = Decision_Tree() + >>> tester = DecisionTree() >>> test_labels = np.array([1,2,3,4,5,6,7,8,9,10]) >>> test_prediction = np.float(6) >>> tester.mean_squared_error(test_labels, test_prediction) == ( - ... Test_Decision_Tree.helper_mean_squared_error_test(test_labels, + ... TestDecisionTree.helper_mean_squared_error_test(test_labels, ... test_prediction)) True >>> test_labels = np.array([1,2,3]) >>> test_prediction = np.float(2) >>> tester.mean_squared_error(test_labels, test_prediction) == ( - ... Test_Decision_Tree.helper_mean_squared_error_test(test_labels, + ... TestDecisionTree.helper_mean_squared_error_test(test_labels, ... test_prediction)) True """ @@ -41,10 +41,10 @@ class Decision_Tree: return np.mean((labels - prediction) ** 2) - def train(self, X, y): + def train(self, x, y): """ train: - @param X: a one dimensional numpy array + @param x: a one dimensional numpy array @param y: a one dimensional numpy array. The contents of y are the labels for the corresponding X values @@ -55,17 +55,17 @@ class Decision_Tree: this section is to check that the inputs conform to our dimensionality constraints """ - if X.ndim != 1: + if x.ndim != 1: print("Error: Input data set must be one dimensional") return - if len(X) != len(y): + if len(x) != len(y): print("Error: X and y have different lengths") return if y.ndim != 1: print("Error: Data set labels must be one dimensional") return - if len(X) < 2 * self.min_leaf_size: + if len(x) < 2 * self.min_leaf_size: self.prediction = np.mean(y) return @@ -74,7 +74,7 @@ class Decision_Tree: return best_split = 0 - min_error = self.mean_squared_error(X, np.mean(y)) * 2 + min_error = self.mean_squared_error(x, np.mean(y)) * 2 """ loop over all possible splits for the decision tree. find the best split. @@ -82,34 +82,34 @@ class Decision_Tree: then the data set is not split and the average for the entire array is used as the predictor """ - for i in range(len(X)): - if len(X[:i]) < self.min_leaf_size: + for i in range(len(x)): + if len(x[:i]) < self.min_leaf_size: continue - elif len(X[i:]) < self.min_leaf_size: + elif len(x[i:]) < self.min_leaf_size: continue else: - error_left = self.mean_squared_error(X[:i], np.mean(y[:i])) - error_right = self.mean_squared_error(X[i:], np.mean(y[i:])) + error_left = self.mean_squared_error(x[:i], np.mean(y[:i])) + error_right = self.mean_squared_error(x[i:], np.mean(y[i:])) error = error_left + error_right if error < min_error: best_split = i min_error = error if best_split != 0: - left_X = X[:best_split] + left_x = x[:best_split] left_y = y[:best_split] - right_X = X[best_split:] + right_x = x[best_split:] right_y = y[best_split:] - self.decision_boundary = X[best_split] - self.left = Decision_Tree( + self.decision_boundary = x[best_split] + self.left = DecisionTree( depth=self.depth - 1, min_leaf_size=self.min_leaf_size ) - self.right = Decision_Tree( + self.right = DecisionTree( depth=self.depth - 1, min_leaf_size=self.min_leaf_size ) - self.left.train(left_X, left_y) - self.right.train(right_X, right_y) + self.left.train(left_x, left_y) + self.right.train(right_x, right_y) else: self.prediction = np.mean(y) @@ -134,7 +134,7 @@ class Decision_Tree: return None -class Test_Decision_Tree: +class TestDecisionTree: """Decision Tres test class""" @staticmethod @@ -159,11 +159,11 @@ def main(): predict the label of 10 different test values. Then the mean squared error over this test is displayed. """ - X = np.arange(-1.0, 1.0, 0.005) - y = np.sin(X) + x = np.arange(-1.0, 1.0, 0.005) + y = np.sin(x) - tree = Decision_Tree(depth=10, min_leaf_size=10) - tree.train(X, y) + tree = DecisionTree(depth=10, min_leaf_size=10) + tree.train(x, y) test_cases = (np.random.rand(10) * 2) - 1 predictions = np.array([tree.predict(x) for x in test_cases]) diff --git a/machine_learning/gaussian_naive_bayes.py b/machine_learning/gaussian_naive_bayes.py index c200aa5a4..77e732662 100644 --- a/machine_learning/gaussian_naive_bayes.py +++ b/machine_learning/gaussian_naive_bayes.py @@ -17,19 +17,19 @@ def main(): iris = load_iris() # Split dataset into train and test data - X = iris["data"] # features - Y = iris["target"] + x = iris["data"] # features + y = iris["target"] x_train, x_test, y_train, y_test = train_test_split( - X, Y, test_size=0.3, random_state=1 + x, y, test_size=0.3, random_state=1 ) # Gaussian Naive Bayes - NB_model = GaussianNB() - NB_model.fit(x_train, y_train) + nb_model = GaussianNB() + nb_model.fit(x_train, y_train) # Display Confusion Matrix plot_confusion_matrix( - NB_model, + nb_model, x_test, y_test, display_labels=iris["target_names"], diff --git a/machine_learning/gradient_boosting_regressor.py b/machine_learning/gradient_boosting_regressor.py index c73e30680..c082f3caf 100644 --- a/machine_learning/gradient_boosting_regressor.py +++ b/machine_learning/gradient_boosting_regressor.py @@ -26,25 +26,25 @@ def main(): print(df_boston.describe().T) # Feature selection - X = df_boston.iloc[:, :-1] + x = df_boston.iloc[:, :-1] y = df_boston.iloc[:, -1] # target variable # split the data with 75% train and 25% test sets. - X_train, X_test, y_train, y_test = train_test_split( - X, y, random_state=0, test_size=0.25 + x_train, x_test, y_train, y_test = train_test_split( + x, y, random_state=0, test_size=0.25 ) model = GradientBoostingRegressor( n_estimators=500, max_depth=5, min_samples_split=4, learning_rate=0.01 ) # training the model - model.fit(X_train, y_train) + model.fit(x_train, y_train) # to see how good the model fit the data - training_score = model.score(X_train, y_train).round(3) - test_score = model.score(X_test, y_test).round(3) + training_score = model.score(x_train, y_train).round(3) + test_score = model.score(x_test, y_test).round(3) print("Training score of GradientBoosting is :", training_score) print("The test score of GradientBoosting is :", test_score) # Let us evaluation the model by finding the errors - y_pred = model.predict(X_test) + y_pred = model.predict(x_test) # The mean squared error print(f"Mean squared error: {mean_squared_error(y_test, y_pred):.2f}") diff --git a/machine_learning/k_means_clust.py b/machine_learning/k_means_clust.py index 60450b7f8..5dc2b7118 100644 --- a/machine_learning/k_means_clust.py +++ b/machine_learning/k_means_clust.py @@ -69,8 +69,8 @@ def get_initial_centroids(data, k, seed=None): return centroids -def centroid_pairwise_dist(X, centroids): - return pairwise_distances(X, centroids, metric="euclidean") +def centroid_pairwise_dist(x, centroids): + return pairwise_distances(x, centroids, metric="euclidean") def assign_clusters(data, centroids): @@ -197,8 +197,8 @@ if False: # change to true to run this test case. plot_heterogeneity(heterogeneity, k) -def ReportGenerator( - df: pd.DataFrame, ClusteringVariables: np.ndarray, FillMissingReport=None +def report_generator( + df: pd.DataFrame, clustering_variables: np.ndarray, fill_missing_report=None ) -> pd.DataFrame: """ Function generates easy-erading clustering report. It takes 2 arguments as an input: @@ -214,7 +214,7 @@ def ReportGenerator( >>> data['col2'] = [100, 200, 300] >>> data['col3'] = [10, 20, 30] >>> data['Cluster'] = [1, 1, 2] - >>> ReportGenerator(data, ['col1', 'col2'], 0) + >>> report_generator(data, ['col1', 'col2'], 0) Features Type Mark 1 2 0 # of Customers ClusterSize False 2.000000 1.000000 1 % of Customers ClusterProportion False 0.666667 0.333333 @@ -231,8 +231,8 @@ def ReportGenerator( [104 rows x 5 columns] """ # Fill missing values with given rules - if FillMissingReport: - df.fillna(value=FillMissingReport, inplace=True) + if fill_missing_report: + df.fillna(value=fill_missing_report, inplace=True) df["dummy"] = 1 numeric_cols = df.select_dtypes(np.number).columns report = ( @@ -313,7 +313,7 @@ def ReportGenerator( report = pd.concat( [report, a, clustersize, clusterproportion], axis=0 ) # concat report with clustert size and nan values - report["Mark"] = report["Features"].isin(ClusteringVariables) + report["Mark"] = report["Features"].isin(clustering_variables) cols = report.columns.tolist() cols = cols[0:2] + cols[-1:] + cols[2:-1] report = report[cols] diff --git a/machine_learning/local_weighted_learning/local_weighted_learning.py b/machine_learning/local_weighted_learning/local_weighted_learning.py index db6868687..6c542ab82 100644 --- a/machine_learning/local_weighted_learning/local_weighted_learning.py +++ b/machine_learning/local_weighted_learning/local_weighted_learning.py @@ -41,11 +41,11 @@ def local_weight( [0.08272556]]) """ weight = weighted_matrix(point, training_data_x, bandwidth) - W = (training_data_x.T * (weight * training_data_x)).I * ( + w = (training_data_x.T * (weight * training_data_x)).I * ( training_data_x.T * weight * training_data_y.T ) - return W + return w def local_weight_regression( diff --git a/machine_learning/logistic_regression.py b/machine_learning/logistic_regression.py index 48d88ef61..87bc8f668 100644 --- a/machine_learning/logistic_regression.py +++ b/machine_learning/logistic_regression.py @@ -35,25 +35,25 @@ def cost_function(h, y): return (-y * np.log(h) - (1 - y) * np.log(1 - h)).mean() -def log_likelihood(X, Y, weights): - scores = np.dot(X, weights) - return np.sum(Y * scores - np.log(1 + np.exp(scores))) +def log_likelihood(x, y, weights): + scores = np.dot(x, weights) + return np.sum(y * scores - np.log(1 + np.exp(scores))) # here alpha is the learning rate, X is the feature matrix,y is the target matrix -def logistic_reg(alpha, X, y, max_iterations=70000): - theta = np.zeros(X.shape[1]) +def logistic_reg(alpha, x, y, max_iterations=70000): + theta = np.zeros(x.shape[1]) for iterations in range(max_iterations): - z = np.dot(X, theta) + z = np.dot(x, theta) h = sigmoid_function(z) - gradient = np.dot(X.T, h - y) / y.size + gradient = np.dot(x.T, h - y) / y.size theta = theta - alpha * gradient # updating the weights - z = np.dot(X, theta) + z = np.dot(x, theta) h = sigmoid_function(z) - J = cost_function(h, y) + j = cost_function(h, y) if iterations % 100 == 0: - print(f"loss: {J} \t") # printing the loss after every 100 iterations + print(f"loss: {j} \t") # printing the loss after every 100 iterations return theta @@ -61,23 +61,23 @@ def logistic_reg(alpha, X, y, max_iterations=70000): if __name__ == "__main__": iris = datasets.load_iris() - X = iris.data[:, :2] + x = iris.data[:, :2] y = (iris.target != 0) * 1 alpha = 0.1 - theta = logistic_reg(alpha, X, y, max_iterations=70000) + theta = logistic_reg(alpha, x, y, max_iterations=70000) print("theta: ", theta) # printing the theta i.e our weights vector - def predict_prob(X): + def predict_prob(x): return sigmoid_function( - np.dot(X, theta) + np.dot(x, theta) ) # predicting the value of probability from the logistic regression algorithm plt.figure(figsize=(10, 6)) - plt.scatter(X[y == 0][:, 0], X[y == 0][:, 1], color="b", label="0") - plt.scatter(X[y == 1][:, 0], X[y == 1][:, 1], color="r", label="1") - (x1_min, x1_max) = (X[:, 0].min(), X[:, 0].max()) - (x2_min, x2_max) = (X[:, 1].min(), X[:, 1].max()) + plt.scatter(x[y == 0][:, 0], x[y == 0][:, 1], color="b", label="0") + plt.scatter(x[y == 1][:, 0], x[y == 1][:, 1], color="r", label="1") + (x1_min, x1_max) = (x[:, 0].min(), x[:, 0].max()) + (x2_min, x2_max) = (x[:, 1].min(), x[:, 1].max()) (xx1, xx2) = np.meshgrid(np.linspace(x1_min, x1_max), np.linspace(x2_min, x2_max)) grid = np.c_[xx1.ravel(), xx2.ravel()] probs = predict_prob(grid).reshape(xx1.shape) diff --git a/machine_learning/multilayer_perceptron_classifier.py b/machine_learning/multilayer_perceptron_classifier.py index 604185cef..e99a4131e 100644 --- a/machine_learning/multilayer_perceptron_classifier.py +++ b/machine_learning/multilayer_perceptron_classifier.py @@ -15,12 +15,12 @@ test = [[0.0, 0.0], [0.0, 1.0], [1.0, 1.0]] Y = clf.predict(test) -def wrapper(Y): +def wrapper(y): """ >>> wrapper(Y) [0, 0, 1] """ - return list(Y) + return list(y) if __name__ == "__main__": diff --git a/machine_learning/random_forest_classifier.py b/machine_learning/random_forest_classifier.py index 637025409..3267fa209 100644 --- a/machine_learning/random_forest_classifier.py +++ b/machine_learning/random_forest_classifier.py @@ -17,10 +17,10 @@ def main(): iris = load_iris() # Split dataset into train and test data - X = iris["data"] # features - Y = iris["target"] + x = iris["data"] # features + y = iris["target"] x_train, x_test, y_train, y_test = train_test_split( - X, Y, test_size=0.3, random_state=1 + x, y, test_size=0.3, random_state=1 ) # Random Forest Classifier diff --git a/machine_learning/random_forest_regressor.py b/machine_learning/random_forest_regressor.py index 0aade626b..1001931a1 100644 --- a/machine_learning/random_forest_regressor.py +++ b/machine_learning/random_forest_regressor.py @@ -17,10 +17,10 @@ def main(): print(boston.keys()) # Split dataset into train and test data - X = boston["data"] # features - Y = boston["target"] + x = boston["data"] # features + y = boston["target"] x_train, x_test, y_train, y_test = train_test_split( - X, Y, test_size=0.3, random_state=1 + x, y, test_size=0.3, random_state=1 ) # Random Forest Regressor diff --git a/machine_learning/sequential_minimum_optimization.py b/machine_learning/sequential_minimum_optimization.py index cc7868d0f..fb4b35f31 100644 --- a/machine_learning/sequential_minimum_optimization.py +++ b/machine_learning/sequential_minimum_optimization.py @@ -80,7 +80,7 @@ class SmoSVM: # Calculate alphas using SMO algorithm def fit(self): - K = self._k + k = self._k state = None while True: @@ -106,14 +106,14 @@ class SmoSVM: # 3: update threshold(b) b1_new = np.float64( -e1 - - y1 * K(i1, i1) * (a1_new - a1) - - y2 * K(i2, i1) * (a2_new - a2) + - y1 * k(i1, i1) * (a1_new - a1) + - y2 * k(i2, i1) * (a2_new - a2) + self._b ) b2_new = np.float64( -e2 - - y2 * K(i2, i2) * (a2_new - a2) - - y1 * K(i1, i2) * (a1_new - a1) + - y2 * k(i2, i2) * (a2_new - a2) + - y1 * k(i1, i2) * (a1_new - a1) + self._b ) if 0.0 < a1_new < self._c: @@ -134,8 +134,8 @@ class SmoSVM: if s == i1 or s == i2: continue self._error[s] += ( - y1 * (a1_new - a1) * K(i1, s) - + y2 * (a2_new - a2) * K(i2, s) + y1 * (a1_new - a1) * k(i1, s) + + y2 * (a2_new - a2) * k(i2, s) + (self._b - b_old) ) @@ -305,56 +305,56 @@ class SmoSVM: # Get the new alpha2 and new alpha1 def _get_new_alpha(self, i1, i2, a1, a2, e1, e2, y1, y2): - K = self._k + k = self._k if i1 == i2: return None, None # calculate L and H which bound the new alpha2 s = y1 * y2 if s == -1: - L, H = max(0.0, a2 - a1), min(self._c, self._c + a2 - a1) + l, h = max(0.0, a2 - a1), min(self._c, self._c + a2 - a1) else: - L, H = max(0.0, a2 + a1 - self._c), min(self._c, a2 + a1) - if L == H: + l, h = max(0.0, a2 + a1 - self._c), min(self._c, a2 + a1) + if l == h: # noqa: E741 return None, None # calculate eta - k11 = K(i1, i1) - k22 = K(i2, i2) - k12 = K(i1, i2) + k11 = k(i1, i1) + k22 = k(i2, i2) + k12 = k(i1, i2) eta = k11 + k22 - 2.0 * k12 # select the new alpha2 which could get the minimal objectives if eta > 0.0: a2_new_unc = a2 + (y2 * (e1 - e2)) / eta # a2_new has a boundary - if a2_new_unc >= H: - a2_new = H - elif a2_new_unc <= L: - a2_new = L + if a2_new_unc >= h: + a2_new = h + elif a2_new_unc <= l: + a2_new = l else: a2_new = a2_new_unc else: b = self._b - l1 = a1 + s * (a2 - L) - h1 = a1 + s * (a2 - H) + l1 = a1 + s * (a2 - l) + h1 = a1 + s * (a2 - h) # way 1 - f1 = y1 * (e1 + b) - a1 * K(i1, i1) - s * a2 * K(i1, i2) - f2 = y2 * (e2 + b) - a2 * K(i2, i2) - s * a1 * K(i1, i2) + f1 = y1 * (e1 + b) - a1 * k(i1, i1) - s * a2 * k(i1, i2) + f2 = y2 * (e2 + b) - a2 * k(i2, i2) - s * a1 * k(i1, i2) ol = ( l1 * f1 - + L * f2 - + 1 / 2 * l1**2 * K(i1, i1) - + 1 / 2 * L**2 * K(i2, i2) - + s * L * l1 * K(i1, i2) + + l * f2 + + 1 / 2 * l1**2 * k(i1, i1) + + 1 / 2 * l**2 * k(i2, i2) + + s * l * l1 * k(i1, i2) ) oh = ( h1 * f1 - + H * f2 - + 1 / 2 * h1**2 * K(i1, i1) - + 1 / 2 * H**2 * K(i2, i2) - + s * H * h1 * K(i1, i2) + + h * f2 + + 1 / 2 * h1**2 * k(i1, i1) + + 1 / 2 * h**2 * k(i2, i2) + + s * h * h1 * k(i1, i2) ) """ # way 2 @@ -362,9 +362,9 @@ class SmoSVM: objectives """ if ol < (oh - self._eps): - a2_new = L + a2_new = l elif ol > oh + self._eps: - a2_new = H + a2_new = h else: a2_new = a2 diff --git a/machine_learning/word_frequency_functions.py b/machine_learning/word_frequency_functions.py index 3e8faf39c..8fd2741f6 100644 --- a/machine_learning/word_frequency_functions.py +++ b/machine_learning/word_frequency_functions.py @@ -83,7 +83,7 @@ the third document in the corpus.") return (len([doc for doc in docs if term in doc]), len(docs)) -def inverse_document_frequency(df: int, N: int, smoothing=False) -> float: +def inverse_document_frequency(df: int, n: int, smoothing=False) -> float: """ Return an integer denoting the importance of a word. This measure of importance is @@ -109,15 +109,15 @@ def inverse_document_frequency(df: int, N: int, smoothing=False) -> float: 1.477 """ if smoothing: - if N == 0: + if n == 0: raise ValueError("log10(0) is undefined.") - return round(1 + log10(N / (1 + df)), 3) + return round(1 + log10(n / (1 + df)), 3) if df == 0: raise ZeroDivisionError("df must be > 0") - elif N == 0: + elif n == 0: raise ValueError("log10(0) is undefined.") - return round(log10(N / df), 3) + return round(log10(n / df), 3) def tf_idf(tf: int, idf: int) -> float: diff --git a/maths/binomial_coefficient.py b/maths/binomial_coefficient.py index 4def04149..0d4b3d1a8 100644 --- a/maths/binomial_coefficient.py +++ b/maths/binomial_coefficient.py @@ -5,16 +5,16 @@ def binomial_coefficient(n, r): >>> binomial_coefficient(10, 5) 252 """ - C = [0 for i in range(r + 1)] + c = [0 for i in range(r + 1)] # nc0 = 1 - C[0] = 1 + c[0] = 1 for i in range(1, n + 1): # to compute current row from previous row. j = min(i, r) while j > 0: - C[j] += C[j - 1] + c[j] += c[j - 1] j -= 1 - return C[r] + return c[r] print(binomial_coefficient(n=10, r=5)) diff --git a/maths/carmichael_number.py b/maths/carmichael_number.py index 09a4fedfb..c9c144759 100644 --- a/maths/carmichael_number.py +++ b/maths/carmichael_number.py @@ -30,7 +30,7 @@ def power(x: int, y: int, mod: int) -> int: return temp -def isCarmichaelNumber(n: int) -> bool: +def is_carmichael_number(n: int) -> bool: b = 2 while b < n: if gcd(b, n) == 1 and power(b, n - 1, n) != 1: @@ -41,7 +41,7 @@ def isCarmichaelNumber(n: int) -> bool: if __name__ == "__main__": number = int(input("Enter number: ").strip()) - if isCarmichaelNumber(number): + if is_carmichael_number(number): print(f"{number} is a Carmichael Number.") else: print(f"{number} is not a Carmichael Number.") diff --git a/maths/decimal_isolate.py b/maths/decimal_isolate.py index 0e3967a46..1b8f6cbca 100644 --- a/maths/decimal_isolate.py +++ b/maths/decimal_isolate.py @@ -4,7 +4,7 @@ https://stackoverflow.com/questions/3886402/how-to-get-numbers-after-decimal-poi """ -def decimal_isolate(number, digitAmount): +def decimal_isolate(number, digit_amount): """ Isolates the decimal part of a number. @@ -28,8 +28,8 @@ def decimal_isolate(number, digitAmount): >>> decimal_isolate(-14.123, 3) -0.123 """ - if digitAmount > 0: - return round(number - int(number), digitAmount) + if digit_amount > 0: + return round(number - int(number), digit_amount) return number - int(number) diff --git a/maths/euler_method.py b/maths/euler_method.py index af7eecb2f..30f193e6d 100644 --- a/maths/euler_method.py +++ b/maths/euler_method.py @@ -29,12 +29,12 @@ def explicit_euler( >>> y[-1] 144.77277243257308 """ - N = int(np.ceil((x_end - x0) / step_size)) - y = np.zeros((N + 1,)) + n = int(np.ceil((x_end - x0) / step_size)) + y = np.zeros((n + 1,)) y[0] = y0 x = x0 - for k in range(N): + for k in range(n): y[k + 1] = y[k] + step_size * ode_func(x, y[k]) x += step_size diff --git a/maths/euler_modified.py b/maths/euler_modified.py index 5659fa063..14bddadf4 100644 --- a/maths/euler_modified.py +++ b/maths/euler_modified.py @@ -33,12 +33,12 @@ def euler_modified( >>> y[-1] 0.5525976431951775 """ - N = int(np.ceil((x_end - x0) / step_size)) - y = np.zeros((N + 1,)) + n = int(np.ceil((x_end - x0) / step_size)) + y = np.zeros((n + 1,)) y[0] = y0 x = x0 - for k in range(N): + for k in range(n): y_get = y[k] + step_size * ode_func(x, y[k]) y[k + 1] = y[k] + ( (step_size / 2) * (ode_func(x, y[k]) + ode_func(x + step_size, y_get)) diff --git a/maths/hardy_ramanujanalgo.py b/maths/hardy_ramanujanalgo.py index e36f763da..6929533fc 100644 --- a/maths/hardy_ramanujanalgo.py +++ b/maths/hardy_ramanujanalgo.py @@ -4,9 +4,9 @@ import math -def exactPrimeFactorCount(n): +def exact_prime_factor_count(n): """ - >>> exactPrimeFactorCount(51242183) + >>> exact_prime_factor_count(51242183) 3 """ count = 0 @@ -36,7 +36,7 @@ def exactPrimeFactorCount(n): if __name__ == "__main__": n = 51242183 - print(f"The number of distinct prime factors is/are {exactPrimeFactorCount(n)}") + print(f"The number of distinct prime factors is/are {exact_prime_factor_count(n)}") print(f"The value of log(log(n)) is {math.log(math.log(n)):.4f}") """ diff --git a/maths/jaccard_similarity.py b/maths/jaccard_similarity.py index 4f24d308f..77f4b90ea 100644 --- a/maths/jaccard_similarity.py +++ b/maths/jaccard_similarity.py @@ -14,7 +14,7 @@ Jaccard similarity is widely used with MinHashing. """ -def jaccard_similariy(setA, setB, alternativeUnion=False): +def jaccard_similariy(set_a, set_b, alternative_union=False): """ Finds the jaccard similarity between two sets. Essentially, its intersection over union. @@ -24,8 +24,8 @@ def jaccard_similariy(setA, setB, alternativeUnion=False): of a set with itself be 1/2 instead of 1. [MMDS 2nd Edition, Page 77] Parameters: - :setA (set,list,tuple): A non-empty set/list - :setB (set,list,tuple): A non-empty set/list + :set_a (set,list,tuple): A non-empty set/list + :set_b (set,list,tuple): A non-empty set/list :alternativeUnion (boolean): If True, use sum of number of items as union @@ -33,48 +33,48 @@ def jaccard_similariy(setA, setB, alternativeUnion=False): (float) The jaccard similarity between the two sets. Examples: - >>> setA = {'a', 'b', 'c', 'd', 'e'} - >>> setB = {'c', 'd', 'e', 'f', 'h', 'i'} - >>> jaccard_similariy(setA,setB) + >>> set_a = {'a', 'b', 'c', 'd', 'e'} + >>> set_b = {'c', 'd', 'e', 'f', 'h', 'i'} + >>> jaccard_similariy(set_a, set_b) 0.375 - >>> jaccard_similariy(setA,setA) + >>> jaccard_similariy(set_a, set_a) 1.0 - >>> jaccard_similariy(setA,setA,True) + >>> jaccard_similariy(set_a, set_a, True) 0.5 - >>> setA = ['a', 'b', 'c', 'd', 'e'] - >>> setB = ('c', 'd', 'e', 'f', 'h', 'i') - >>> jaccard_similariy(setA,setB) + >>> set_a = ['a', 'b', 'c', 'd', 'e'] + >>> set_b = ('c', 'd', 'e', 'f', 'h', 'i') + >>> jaccard_similariy(set_a, set_b) 0.375 """ - if isinstance(setA, set) and isinstance(setB, set): + if isinstance(set_a, set) and isinstance(set_b, set): - intersection = len(setA.intersection(setB)) + intersection = len(set_a.intersection(set_b)) - if alternativeUnion: - union = len(setA) + len(setB) + if alternative_union: + union = len(set_a) + len(set_b) else: - union = len(setA.union(setB)) + union = len(set_a.union(set_b)) return intersection / union - if isinstance(setA, (list, tuple)) and isinstance(setB, (list, tuple)): + if isinstance(set_a, (list, tuple)) and isinstance(set_b, (list, tuple)): - intersection = [element for element in setA if element in setB] + intersection = [element for element in set_a if element in set_b] - if alternativeUnion: - union = len(setA) + len(setB) + if alternative_union: + union = len(set_a) + len(set_b) else: - union = setA + [element for element in setB if element not in setA] + union = set_a + [element for element in set_b if element not in set_a] return len(intersection) / len(union) if __name__ == "__main__": - setA = {"a", "b", "c", "d", "e"} - setB = {"c", "d", "e", "f", "h", "i"} - print(jaccard_similariy(setA, setB)) + set_a = {"a", "b", "c", "d", "e"} + set_b = {"c", "d", "e", "f", "h", "i"} + print(jaccard_similariy(set_a, set_b)) diff --git a/maths/krishnamurthy_number.py b/maths/krishnamurthy_number.py index c88f68a07..c1d8a8fc5 100644 --- a/maths/krishnamurthy_number.py +++ b/maths/krishnamurthy_number.py @@ -33,12 +33,12 @@ def krishnamurthy(number: int) -> bool: True """ - factSum = 0 + fact_sum = 0 duplicate = number while duplicate > 0: duplicate, digit = divmod(duplicate, 10) - factSum += factorial(digit) - return factSum == number + fact_sum += factorial(digit) + return fact_sum == number if __name__ == "__main__": diff --git a/maths/kth_lexicographic_permutation.py b/maths/kth_lexicographic_permutation.py index 23eab626f..b85558aca 100644 --- a/maths/kth_lexicographic_permutation.py +++ b/maths/kth_lexicographic_permutation.py @@ -1,17 +1,17 @@ -def kthPermutation(k, n): +def kth_permutation(k, n): """ Finds k'th lexicographic permutation (in increasing order) of 0,1,2,...n-1 in O(n^2) time. Examples: First permutation is always 0,1,2,...n - >>> kthPermutation(0,5) + >>> kth_permutation(0,5) [0, 1, 2, 3, 4] The order of permutation of 0,1,2,3 is [0,1,2,3], [0,1,3,2], [0,2,1,3], [0,2,3,1], [0,3,1,2], [0,3,2,1], [1,0,2,3], [1,0,3,2], [1,2,0,3], [1,2,3,0], [1,3,0,2] - >>> kthPermutation(10,4) + >>> kth_permutation(10,4) [1, 3, 0, 2] """ # Factorails from 1! to (n-1)! diff --git a/maths/lucas_lehmer_primality_test.py b/maths/lucas_lehmer_primality_test.py index 15e25cbfe..916abfcc1 100644 --- a/maths/lucas_lehmer_primality_test.py +++ b/maths/lucas_lehmer_primality_test.py @@ -30,9 +30,9 @@ def lucas_lehmer_test(p: int) -> bool: return True s = 4 - M = (1 << p) - 1 + m = (1 << p) - 1 for i in range(p - 2): - s = ((s * s) - 2) % M + s = ((s * s) - 2) % m return s == 0 diff --git a/maths/primelib.py b/maths/primelib.py index 3da9c56f6..7d2a22f39 100644 --- a/maths/primelib.py +++ b/maths/primelib.py @@ -8,27 +8,27 @@ prime numbers and whole numbers. Overview: -isPrime(number) -sieveEr(N) -getPrimeNumbers(N) -primeFactorization(number) -greatestPrimeFactor(number) -smallestPrimeFactor(number) -getPrime(n) -getPrimesBetween(pNumber1, pNumber2) +is_prime(number) +sieve_er(N) +get_prime_numbers(N) +prime_factorization(number) +greatest_prime_factor(number) +smallest_prime_factor(number) +get_prime(n) +get_primes_between(pNumber1, pNumber2) ---- -isEven(number) -isOdd(number) +is_even(number) +is_odd(number) gcd(number1, number2) // greatest common divisor -kgV(number1, number2) // least common multiple -getDivisors(number) // all divisors of 'number' inclusive 1, number -isPerfectNumber(number) +kg_v(number1, number2) // least common multiple +get_divisors(number) // all divisors of 'number' inclusive 1, number +is_perfect_number(number) NEW-FUNCTIONS -simplifyFraction(numerator, denominator) +simplify_fraction(numerator, denominator) factorial (n) // n! fib (n) // calculate the n-th fibonacci term. @@ -75,7 +75,7 @@ def is_prime(number: int) -> bool: # ------------------------------------------ -def sieveEr(N): +def sieve_er(n): """ input: positive integer 'N' > 2 returns a list of prime numbers from 2 up to N. @@ -86,23 +86,23 @@ def sieveEr(N): """ # precondition - assert isinstance(N, int) and (N > 2), "'N' must been an int and > 2" + assert isinstance(n, int) and (n > 2), "'N' must been an int and > 2" # beginList: contains all natural numbers from 2 up to N - beginList = [x for x in range(2, N + 1)] + begin_list = [x for x in range(2, n + 1)] ans = [] # this list will be returns. # actual sieve of erathostenes - for i in range(len(beginList)): + for i in range(len(begin_list)): - for j in range(i + 1, len(beginList)): + for j in range(i + 1, len(begin_list)): - if (beginList[i] != 0) and (beginList[j] % beginList[i] == 0): - beginList[j] = 0 + if (begin_list[i] != 0) and (begin_list[j] % begin_list[i] == 0): + begin_list[j] = 0 # filters actual prime numbers. - ans = [x for x in beginList if x != 0] + ans = [x for x in begin_list if x != 0] # precondition assert isinstance(ans, list), "'ans' must been from type list" @@ -113,7 +113,7 @@ def sieveEr(N): # -------------------------------- -def getPrimeNumbers(N): +def get_prime_numbers(n): """ input: positive integer 'N' > 2 returns a list of prime numbers from 2 up to N (inclusive) @@ -121,13 +121,13 @@ def getPrimeNumbers(N): """ # precondition - assert isinstance(N, int) and (N > 2), "'N' must been an int and > 2" + assert isinstance(n, int) and (n > 2), "'N' must been an int and > 2" ans = [] # iterates over all numbers between 2 up to N+1 # if a number is prime then appends to list 'ans' - for number in range(2, N + 1): + for number in range(2, n + 1): if is_prime(number): @@ -142,7 +142,7 @@ def getPrimeNumbers(N): # ----------------------------------------- -def primeFactorization(number): +def prime_factorization(number): """ input: positive integer 'number' returns a list of the prime number factors of 'number' @@ -186,7 +186,7 @@ def primeFactorization(number): # ----------------------------------------- -def greatestPrimeFactor(number): +def greatest_prime_factor(number): """ input: positive integer 'number' >= 0 returns the greatest prime number factor of 'number' @@ -200,9 +200,9 @@ def greatestPrimeFactor(number): ans = 0 # prime factorization of 'number' - primeFactors = primeFactorization(number) + prime_factors = prime_factorization(number) - ans = max(primeFactors) + ans = max(prime_factors) # precondition assert isinstance(ans, int), "'ans' must been from type int" @@ -213,7 +213,7 @@ def greatestPrimeFactor(number): # ---------------------------------------------- -def smallestPrimeFactor(number): +def smallest_prime_factor(number): """ input: integer 'number' >= 0 returns the smallest prime number factor of 'number' @@ -227,9 +227,9 @@ def smallestPrimeFactor(number): ans = 0 # prime factorization of 'number' - primeFactors = primeFactorization(number) + prime_factors = prime_factorization(number) - ans = min(primeFactors) + ans = min(prime_factors) # precondition assert isinstance(ans, int), "'ans' must been from type int" @@ -240,7 +240,7 @@ def smallestPrimeFactor(number): # ---------------------- -def isEven(number): +def is_even(number): """ input: integer 'number' returns true if 'number' is even, otherwise false. @@ -256,7 +256,7 @@ def isEven(number): # ------------------------ -def isOdd(number): +def is_odd(number): """ input: integer 'number' returns true if 'number' is odd, otherwise false. @@ -281,14 +281,14 @@ def goldbach(number): # precondition assert ( - isinstance(number, int) and (number > 2) and isEven(number) + isinstance(number, int) and (number > 2) and is_even(number) ), "'number' must been an int, even and > 2" ans = [] # this list will returned # creates a list of prime numbers between 2 up to 'number' - primeNumbers = getPrimeNumbers(number) - lenPN = len(primeNumbers) + prime_numbers = get_prime_numbers(number) + len_pn = len(prime_numbers) # run variable for while-loops. i = 0 @@ -297,16 +297,16 @@ def goldbach(number): # exit variable. for break up the loops loop = True - while i < lenPN and loop: + while i < len_pn and loop: j = i + 1 - while j < lenPN and loop: + while j < len_pn and loop: - if primeNumbers[i] + primeNumbers[j] == number: + if prime_numbers[i] + prime_numbers[j] == number: loop = False - ans.append(primeNumbers[i]) - ans.append(primeNumbers[j]) + ans.append(prime_numbers[i]) + ans.append(prime_numbers[j]) j += 1 @@ -361,7 +361,7 @@ def gcd(number1, number2): # ---------------------------------------------------- -def kgV(number1, number2): +def kg_v(number1, number2): """ Least common multiple input: two positive integer 'number1' and 'number2' @@ -382,13 +382,13 @@ def kgV(number1, number2): if number1 > 1 and number2 > 1: # builds the prime factorization of 'number1' and 'number2' - primeFac1 = primeFactorization(number1) - primeFac2 = primeFactorization(number2) + prime_fac_1 = prime_factorization(number1) + prime_fac_2 = prime_factorization(number2) elif number1 == 1 or number2 == 1: - primeFac1 = [] - primeFac2 = [] + prime_fac_1 = [] + prime_fac_2 = [] ans = max(number1, number2) count1 = 0 @@ -397,21 +397,21 @@ def kgV(number1, number2): done = [] # captured numbers int both 'primeFac1' and 'primeFac2' # iterates through primeFac1 - for n in primeFac1: + for n in prime_fac_1: if n not in done: - if n in primeFac2: + if n in prime_fac_2: - count1 = primeFac1.count(n) - count2 = primeFac2.count(n) + count1 = prime_fac_1.count(n) + count2 = prime_fac_2.count(n) for i in range(max(count1, count2)): ans *= n else: - count1 = primeFac1.count(n) + count1 = prime_fac_1.count(n) for i in range(count1): ans *= n @@ -419,11 +419,11 @@ def kgV(number1, number2): done.append(n) # iterates through primeFac2 - for n in primeFac2: + for n in prime_fac_2: if n not in done: - count2 = primeFac2.count(n) + count2 = prime_fac_2.count(n) for i in range(count2): ans *= n @@ -441,7 +441,7 @@ def kgV(number1, number2): # ---------------------------------- -def getPrime(n): +def get_prime(n): """ Gets the n-th prime number. input: positive integer 'n' >= 0 @@ -476,7 +476,7 @@ def getPrime(n): # --------------------------------------------------- -def getPrimesBetween(pNumber1, pNumber2): +def get_primes_between(p_number_1, p_number_2): """ input: prime numbers 'pNumber1' and 'pNumber2' pNumber1 < pNumber2 @@ -486,10 +486,10 @@ def getPrimesBetween(pNumber1, pNumber2): # precondition assert ( - is_prime(pNumber1) and is_prime(pNumber2) and (pNumber1 < pNumber2) + is_prime(p_number_1) and is_prime(p_number_2) and (p_number_1 < p_number_2) ), "The arguments must been prime numbers and 'pNumber1' < 'pNumber2'" - number = pNumber1 + 1 # jump to the next number + number = p_number_1 + 1 # jump to the next number ans = [] # this list will be returns. @@ -498,7 +498,7 @@ def getPrimesBetween(pNumber1, pNumber2): while not is_prime(number): number += 1 - while number < pNumber2: + while number < p_number_2: ans.append(number) @@ -510,7 +510,9 @@ def getPrimesBetween(pNumber1, pNumber2): # precondition assert ( - isinstance(ans, list) and ans[0] != pNumber1 and ans[len(ans) - 1] != pNumber2 + isinstance(ans, list) + and ans[0] != p_number_1 + and ans[len(ans) - 1] != p_number_2 ), "'ans' must been a list without the arguments" # 'ans' contains not 'pNumber1' and 'pNumber2' ! @@ -520,7 +522,7 @@ def getPrimesBetween(pNumber1, pNumber2): # ---------------------------------------------------- -def getDivisors(n): +def get_divisors(n): """ input: positive integer 'n' >= 1 returns all divisors of n (inclusive 1 and 'n') @@ -545,7 +547,7 @@ def getDivisors(n): # ---------------------------------------------------- -def isPerfectNumber(number): +def is_perfect_number(number): """ input: positive integer 'number' > 1 returns true if 'number' is a perfect number otherwise false. @@ -556,7 +558,7 @@ def isPerfectNumber(number): number > 1 ), "'number' must been an int and >= 1" - divisors = getDivisors(number) + divisors = get_divisors(number) # precondition assert ( @@ -572,7 +574,7 @@ def isPerfectNumber(number): # ------------------------------------------------------------ -def simplifyFraction(numerator, denominator): +def simplify_fraction(numerator, denominator): """ input: two integer 'numerator' and 'denominator' assumes: 'denominator' != 0 @@ -587,16 +589,16 @@ def simplifyFraction(numerator, denominator): ), "The arguments must been from type int and 'denominator' != 0" # build the greatest common divisor of numerator and denominator. - gcdOfFraction = gcd(abs(numerator), abs(denominator)) + gcd_of_fraction = gcd(abs(numerator), abs(denominator)) # precondition assert ( - isinstance(gcdOfFraction, int) - and (numerator % gcdOfFraction == 0) - and (denominator % gcdOfFraction == 0) + isinstance(gcd_of_fraction, int) + and (numerator % gcd_of_fraction == 0) + and (denominator % gcd_of_fraction == 0) ), "Error in function gcd(...,...)" - return (numerator // gcdOfFraction, denominator // gcdOfFraction) + return (numerator // gcd_of_fraction, denominator // gcd_of_fraction) # ----------------------------------------------------------------- diff --git a/maths/qr_decomposition.py b/maths/qr_decomposition.py index 5e15fede4..a8414fbec 100644 --- a/maths/qr_decomposition.py +++ b/maths/qr_decomposition.py @@ -1,7 +1,7 @@ import numpy as np -def qr_householder(A): +def qr_householder(a): """Return a QR-decomposition of the matrix A using Householder reflection. The QR-decomposition decomposes the matrix A of shape (m, n) into an @@ -37,14 +37,14 @@ def qr_householder(A): >>> np.allclose(np.triu(R), R) True """ - m, n = A.shape + m, n = a.shape t = min(m, n) - Q = np.eye(m) - R = A.copy() + q = np.eye(m) + r = a.copy() for k in range(t - 1): # select a column of modified matrix A': - x = R[k:, [k]] + x = r[k:, [k]] # construct first basis vector e1 = np.zeros_like(x) e1[0] = 1.0 @@ -55,14 +55,14 @@ def qr_householder(A): v /= np.linalg.norm(v) # construct the Householder matrix - Q_k = np.eye(m - k) - 2.0 * v @ v.T + q_k = np.eye(m - k) - 2.0 * v @ v.T # pad with ones and zeros as necessary - Q_k = np.block([[np.eye(k), np.zeros((k, m - k))], [np.zeros((m - k, k)), Q_k]]) + q_k = np.block([[np.eye(k), np.zeros((k, m - k))], [np.zeros((m - k, k)), q_k]]) - Q = Q @ Q_k.T - R = Q_k @ R + q = q @ q_k.T + r = q_k @ r - return Q, R + return q, r if __name__ == "__main__": diff --git a/maths/radix2_fft.py b/maths/radix2_fft.py index 0a431a115..52442134d 100644 --- a/maths/radix2_fft.py +++ b/maths/radix2_fft.py @@ -49,10 +49,10 @@ class FFT: A*B = 0*x^(-0+0j) + 1*x^(2+0j) + 2*x^(3+0j) + 3*x^(8+0j) + 4*x^(6+0j) + 5*x^(8+0j) """ - def __init__(self, polyA=None, polyB=None): + def __init__(self, poly_a=None, poly_b=None): # Input as list - self.polyA = list(polyA or [0])[:] - self.polyB = list(polyB or [0])[:] + self.polyA = list(poly_a or [0])[:] + self.polyB = list(poly_b or [0])[:] # Remove leading zero coefficients while self.polyA[-1] == 0: @@ -64,22 +64,22 @@ class FFT: self.len_B = len(self.polyB) # Add 0 to make lengths equal a power of 2 - self.C_max_length = int( + self.c_max_length = int( 2 ** np.ceil(np.log2(len(self.polyA) + len(self.polyB) - 1)) ) - while len(self.polyA) < self.C_max_length: + while len(self.polyA) < self.c_max_length: self.polyA.append(0) - while len(self.polyB) < self.C_max_length: + while len(self.polyB) < self.c_max_length: self.polyB.append(0) # A complex root used for the fourier transform - self.root = complex(mpmath.root(x=1, n=self.C_max_length, k=1)) + self.root = complex(mpmath.root(x=1, n=self.c_max_length, k=1)) # The product self.product = self.__multiply() # Discrete fourier transform of A and B - def __DFT(self, which): + def __dft(self, which): if which == "A": dft = [[x] for x in self.polyA] else: @@ -88,20 +88,20 @@ class FFT: if len(dft) <= 1: return dft[0] # - next_ncol = self.C_max_length // 2 + next_ncol = self.c_max_length // 2 while next_ncol > 0: new_dft = [[] for i in range(next_ncol)] root = self.root**next_ncol # First half of next step current_root = 1 - for j in range(self.C_max_length // (next_ncol * 2)): + for j in range(self.c_max_length // (next_ncol * 2)): for i in range(next_ncol): new_dft[i].append(dft[i][j] + current_root * dft[i + next_ncol][j]) current_root *= root # Second half of next step current_root = 1 - for j in range(self.C_max_length // (next_ncol * 2)): + for j in range(self.c_max_length // (next_ncol * 2)): for i in range(next_ncol): new_dft[i].append(dft[i][j] - current_root * dft[i + next_ncol][j]) current_root *= root @@ -112,65 +112,65 @@ class FFT: # multiply the DFTs of A and B and find A*B def __multiply(self): - dftA = self.__DFT("A") - dftB = self.__DFT("B") - inverseC = [[dftA[i] * dftB[i] for i in range(self.C_max_length)]] - del dftA - del dftB + dft_a = self.__dft("A") + dft_b = self.__dft("B") + inverce_c = [[dft_a[i] * dft_b[i] for i in range(self.c_max_length)]] + del dft_a + del dft_b # Corner Case - if len(inverseC[0]) <= 1: - return inverseC[0] + if len(inverce_c[0]) <= 1: + return inverce_c[0] # Inverse DFT next_ncol = 2 - while next_ncol <= self.C_max_length: - new_inverseC = [[] for i in range(next_ncol)] + while next_ncol <= self.c_max_length: + new_inverse_c = [[] for i in range(next_ncol)] root = self.root ** (next_ncol // 2) current_root = 1 # First half of next step - for j in range(self.C_max_length // next_ncol): + for j in range(self.c_max_length // next_ncol): for i in range(next_ncol // 2): # Even positions - new_inverseC[i].append( + new_inverse_c[i].append( ( - inverseC[i][j] - + inverseC[i][j + self.C_max_length // next_ncol] + inverce_c[i][j] + + inverce_c[i][j + self.c_max_length // next_ncol] ) / 2 ) # Odd positions - new_inverseC[i + next_ncol // 2].append( + new_inverse_c[i + next_ncol // 2].append( ( - inverseC[i][j] - - inverseC[i][j + self.C_max_length // next_ncol] + inverce_c[i][j] + - inverce_c[i][j + self.c_max_length // next_ncol] ) / (2 * current_root) ) current_root *= root # Update - inverseC = new_inverseC + inverce_c = new_inverse_c next_ncol *= 2 # Unpack - inverseC = [round(x[0].real, 8) + round(x[0].imag, 8) * 1j for x in inverseC] + inverce_c = [round(x[0].real, 8) + round(x[0].imag, 8) * 1j for x in inverce_c] # Remove leading 0's - while inverseC[-1] == 0: - inverseC.pop() - return inverseC + while inverce_c[-1] == 0: + inverce_c.pop() + return inverce_c # Overwrite __str__ for print(); Shows A, B and A*B def __str__(self): - A = "A = " + " + ".join( + a = "A = " + " + ".join( f"{coef}*x^{i}" for coef, i in enumerate(self.polyA[: self.len_A]) ) - B = "B = " + " + ".join( + b = "B = " + " + ".join( f"{coef}*x^{i}" for coef, i in enumerate(self.polyB[: self.len_B]) ) - C = "A*B = " + " + ".join( + c = "A*B = " + " + ".join( f"{coef}*x^{i}" for coef, i in enumerate(self.product) ) - return "\n".join((A, B, C)) + return "\n".join((a, b, c)) # Unit tests diff --git a/maths/runge_kutta.py b/maths/runge_kutta.py index 383797daa..4cac017ee 100644 --- a/maths/runge_kutta.py +++ b/maths/runge_kutta.py @@ -22,12 +22,12 @@ def runge_kutta(f, y0, x0, h, x_end): >>> y[-1] 148.41315904125113 """ - N = int(np.ceil((x_end - x0) / h)) - y = np.zeros((N + 1,)) + n = int(np.ceil((x_end - x0) / h)) + y = np.zeros((n + 1,)) y[0] = y0 x = x0 - for k in range(N): + for k in range(n): k1 = f(x, y[k]) k2 = f(x + 0.5 * h, y[k] + 0.5 * h * k1) k3 = f(x + 0.5 * h, y[k] + 0.5 * h * k2) diff --git a/maths/softmax.py b/maths/softmax.py index e021a7f8a..04cf77525 100644 --- a/maths/softmax.py +++ b/maths/softmax.py @@ -41,13 +41,13 @@ def softmax(vector): # Calculate e^x for each x in your vector where e is Euler's # number (approximately 2.718) - exponentVector = np.exp(vector) + exponent_vector = np.exp(vector) # Add up the all the exponentials - sumOfExponents = np.sum(exponentVector) + sum_of_exponents = np.sum(exponent_vector) # Divide every exponent by the sum of all exponents - softmax_vector = exponentVector / sumOfExponents + softmax_vector = exponent_vector / sum_of_exponents return softmax_vector diff --git a/matrix/count_islands_in_matrix.py b/matrix/count_islands_in_matrix.py index 00f9e1436..64c595e84 100644 --- a/matrix/count_islands_in_matrix.py +++ b/matrix/count_islands_in_matrix.py @@ -3,7 +3,7 @@ # connections. -class matrix: # Public class to implement a graph +class Matrix: # Public class to implement a graph def __init__(self, row: int, col: int, graph: list[list[bool]]) -> None: self.ROW = row self.COL = col @@ -19,12 +19,12 @@ class matrix: # Public class to implement a graph def diffs(self, i: int, j: int, visited: list[list[bool]]) -> None: # Checking all 8 elements surrounding nth element - rowNbr = [-1, -1, -1, 0, 0, 1, 1, 1] # Coordinate order - colNbr = [-1, 0, 1, -1, 1, -1, 0, 1] + row_nbr = [-1, -1, -1, 0, 0, 1, 1, 1] # Coordinate order + col_nbr = [-1, 0, 1, -1, 1, -1, 0, 1] visited[i][j] = True # Make those cells visited for k in range(8): - if self.is_safe(i + rowNbr[k], j + colNbr[k], visited): - self.diffs(i + rowNbr[k], j + colNbr[k], visited) + if self.is_safe(i + row_nbr[k], j + col_nbr[k], visited): + self.diffs(i + row_nbr[k], j + col_nbr[k], visited) def count_islands(self) -> int: # And finally, count all islands. visited = [[False for j in range(self.COL)] for i in range(self.ROW)] diff --git a/matrix/inverse_of_matrix.py b/matrix/inverse_of_matrix.py index 92780e656..770ce39b5 100644 --- a/matrix/inverse_of_matrix.py +++ b/matrix/inverse_of_matrix.py @@ -27,7 +27,7 @@ def inverse_of_matrix(matrix: list[list[float]]) -> list[list[float]]: [[0.25, -0.5], [-0.3, 1.0]] """ - D = Decimal # An abbreviation for conciseness + d = Decimal # An abbreviation for conciseness # Check if the provided matrix has 2 rows and 2 columns # since this implementation only works for 2x2 matrices @@ -35,7 +35,7 @@ def inverse_of_matrix(matrix: list[list[float]]) -> list[list[float]]: raise ValueError("Please provide a matrix of size 2x2.") # Calculate the determinant of the matrix - determinant = D(matrix[0][0]) * D(matrix[1][1]) - D(matrix[1][0]) * D(matrix[0][1]) + determinant = d(matrix[0][0]) * d(matrix[1][1]) - d(matrix[1][0]) * d(matrix[0][1]) if determinant == 0: raise ValueError("This matrix has no inverse.") @@ -45,4 +45,4 @@ def inverse_of_matrix(matrix: list[list[float]]) -> list[list[float]]: swapped_matrix[1][0], swapped_matrix[0][1] = -matrix[1][0], -matrix[0][1] # Calculate the inverse of the matrix - return [[float(D(n) / determinant) or 0.0 for n in row] for row in swapped_matrix] + return [[float(d(n) / determinant) or 0.0 for n in row] for row in swapped_matrix] diff --git a/matrix/sherman_morrison.py b/matrix/sherman_morrison.py index a0c93f115..29c9b3381 100644 --- a/matrix/sherman_morrison.py +++ b/matrix/sherman_morrison.py @@ -54,15 +54,15 @@ class Matrix: def __repr__(self) -> str: return str(self) - def validateIndices(self, loc: tuple[int, int]) -> bool: + def validate_indicies(self, loc: tuple[int, int]) -> bool: """ - + Check if given indices are valid to pick element from matrix. Example: >>> a = Matrix(2, 6, 0) - >>> a.validateIndices((2, 7)) + >>> a.validate_indicies((2, 7)) False - >>> a.validateIndices((0, 0)) + >>> a.validate_indicies((0, 0)) True """ if not (isinstance(loc, (list, tuple)) and len(loc) == 2): @@ -81,7 +81,7 @@ class Matrix: >>> a[1, 0] 7 """ - assert self.validateIndices(loc) + assert self.validate_indicies(loc) return self.array[loc[0]][loc[1]] def __setitem__(self, loc: tuple[int, int], value: float) -> None: @@ -96,7 +96,7 @@ class Matrix: [ 1, 1, 1] [ 1, 1, 51] """ - assert self.validateIndices(loc) + assert self.validate_indicies(loc) self.array[loc[0]][loc[1]] = value def __add__(self, another: Matrix) -> Matrix: @@ -198,9 +198,9 @@ class Matrix: result[c, r] = self[r, c] return result - def ShermanMorrison(self, u: Matrix, v: Matrix) -> Any: + def sherman_morrison(self, u: Matrix, v: Matrix) -> Any: """ - + Apply Sherman-Morrison formula in O(n^2). To learn this formula, please look this: https://en.wikipedia.org/wiki/Sherman%E2%80%93Morrison_formula @@ -216,7 +216,7 @@ class Matrix: >>> u[0,0], u[1,0], u[2,0] = 1, 2, -3 >>> v = Matrix(3, 1, 0) >>> v[0,0], v[1,0], v[2,0] = 4, -2, 5 - >>> ainv.ShermanMorrison(u, v) + >>> ainv.sherman_morrison(u, v) Matrix consist of 3 rows and 3 columns [ 1.2857142857142856, -0.14285714285714285, 0.3571428571428571] [ 0.5714285714285714, 0.7142857142857143, 0.7142857142857142] @@ -229,11 +229,11 @@ class Matrix: assert u.column == v.column == 1 # u, v should be column vector # Calculate - vT = v.transpose() - numerator_factor = (vT * self * u)[0, 0] + 1 + v_t = v.transpose() + numerator_factor = (v_t * self * u)[0, 0] + 1 if numerator_factor == 0: return None # It's not invertable - return self - ((self * u) * (vT * self) * (1.0 / numerator_factor)) + return self - ((self * u) * (v_t * self) * (1.0 / numerator_factor)) # Testing @@ -254,7 +254,7 @@ if __name__ == "__main__": print(f"v is {v}") print("uv^T is %s" % (u * v.transpose())) # Sherman Morrison - print(f"(a + uv^T)^(-1) is {ainv.ShermanMorrison(u, v)}") + print(f"(a + uv^T)^(-1) is {ainv.sherman_morrison(u, v)}") def test2() -> None: import doctest diff --git a/networking_flow/ford_fulkerson.py b/networking_flow/ford_fulkerson.py index 96b782649..370e38482 100644 --- a/networking_flow/ford_fulkerson.py +++ b/networking_flow/ford_fulkerson.py @@ -6,7 +6,7 @@ Description: """ -def BFS(graph, s, t, parent): +def bfs(graph, s, t, parent): # Return True if there is node that has not iterated. visited = [False] * len(graph) queue = [] @@ -24,11 +24,11 @@ def BFS(graph, s, t, parent): return True if visited[t] else False -def FordFulkerson(graph, source, sink): +def ford_fulkerson(graph, source, sink): # This array is filled by BFS and to store path parent = [-1] * (len(graph)) max_flow = 0 - while BFS(graph, source, sink, parent): + while bfs(graph, source, sink, parent): path_flow = float("Inf") s = sink @@ -58,4 +58,4 @@ graph = [ ] source, sink = 0, 5 -print(FordFulkerson(graph, source, sink)) +print(ford_fulkerson(graph, source, sink)) diff --git a/networking_flow/minimum_cut.py b/networking_flow/minimum_cut.py index d79f3619c..33131315f 100644 --- a/networking_flow/minimum_cut.py +++ b/networking_flow/minimum_cut.py @@ -10,7 +10,7 @@ test_graph = [ ] -def BFS(graph, s, t, parent): +def bfs(graph, s, t, parent): # Return True if there is node that has not iterated. visited = [False] * len(graph) queue = [s] @@ -36,7 +36,7 @@ def mincut(graph, source, sink): max_flow = 0 res = [] temp = [i[:] for i in graph] # Record original cut, copy. - while BFS(graph, source, sink, parent): + while bfs(graph, source, sink, parent): path_flow = float("Inf") s = sink diff --git a/neural_network/convolution_neural_network.py b/neural_network/convolution_neural_network.py index e3993efb4..bbade1c41 100644 --- a/neural_network/convolution_neural_network.py +++ b/neural_network/convolution_neural_network.py @@ -74,7 +74,7 @@ class CNN: print(f"Model saved: {save_path}") @classmethod - def ReadModel(cls, model_path): + def read_model(cls, model_path): # read saved model with open(model_path, "rb") as f: model_dic = pickle.load(f) @@ -119,7 +119,7 @@ class CNN: data_focus.append(focus) # calculate the feature map of every single kernel, and saved as list of matrix data_featuremap = [] - Size_FeatureMap = int((size_data - size_conv) / conv_step + 1) + size_feature_map = int((size_data - size_conv) / conv_step + 1) for i_map in range(num_conv): featuremap = [] for i_focus in range(len(data_focus)): @@ -129,7 +129,7 @@ class CNN: ) featuremap.append(self.sig(net_focus)) featuremap = np.asmatrix(featuremap).reshape( - Size_FeatureMap, Size_FeatureMap + size_feature_map, size_feature_map ) data_featuremap.append(featuremap) diff --git a/other/davisb_putnamb_logemannb_loveland.py b/other/davisb_putnamb_logemannb_loveland.py index 88aefabc8..03d60a9a1 100644 --- a/other/davisb_putnamb_logemannb_loveland.py +++ b/other/davisb_putnamb_logemannb_loveland.py @@ -255,14 +255,14 @@ def find_unit_clauses( if len(clause) == 1: unit_symbols.append(list(clause.literals.keys())[0]) else: - Fcount, Ncount = 0, 0 + f_count, n_count = 0, 0 for literal, value in clause.literals.items(): if value is False: - Fcount += 1 + f_count += 1 elif value is None: sym = literal - Ncount += 1 - if Fcount == len(clause) - 1 and Ncount == 1: + n_count += 1 + if f_count == len(clause) - 1 and n_count == 1: unit_symbols.append(sym) assignment: dict[str, bool | None] = dict() for i in unit_symbols: @@ -310,33 +310,33 @@ def dpll_algorithm( except RecursionError: print("raises a RecursionError and is") return None, {} - P = None + p = None if len(pure_symbols) > 0: - P, value = pure_symbols[0], assignment[pure_symbols[0]] + p, value = pure_symbols[0], assignment[pure_symbols[0]] - if P: + if p: tmp_model = model - tmp_model[P] = value + tmp_model[p] = value tmp_symbols = [i for i in symbols] - if P in tmp_symbols: - tmp_symbols.remove(P) + if p in tmp_symbols: + tmp_symbols.remove(p) return dpll_algorithm(clauses, tmp_symbols, tmp_model) unit_symbols, assignment = find_unit_clauses(clauses, model) - P = None + p = None if len(unit_symbols) > 0: - P, value = unit_symbols[0], assignment[unit_symbols[0]] - if P: + p, value = unit_symbols[0], assignment[unit_symbols[0]] + if p: tmp_model = model - tmp_model[P] = value + tmp_model[p] = value tmp_symbols = [i for i in symbols] - if P in tmp_symbols: - tmp_symbols.remove(P) + if p in tmp_symbols: + tmp_symbols.remove(p) return dpll_algorithm(clauses, tmp_symbols, tmp_model) - P = symbols[0] + p = symbols[0] rest = symbols[1:] tmp1, tmp2 = model, model - tmp1[P], tmp2[P] = True, False + tmp1[p], tmp2[p] = True, False return dpll_algorithm(clauses, rest, tmp1) or dpll_algorithm(clauses, rest, tmp2) diff --git a/other/greedy.py b/other/greedy.py index 4b78bf1c0..72e05f451 100644 --- a/other/greedy.py +++ b/other/greedy.py @@ -1,4 +1,4 @@ -class things: +class Things: def __init__(self, name, value, weight): self.name = name self.value = value @@ -16,27 +16,27 @@ class things: def get_weight(self): return self.weight - def value_Weight(self): + def value_weight(self): return self.value / self.weight def build_menu(name, value, weight): menu = [] for i in range(len(value)): - menu.append(things(name[i], value[i], weight[i])) + menu.append(Things(name[i], value[i], weight[i])) return menu -def greedy(item, maxCost, keyFunc): - itemsCopy = sorted(item, key=keyFunc, reverse=True) +def greedy(item, max_cost, key_func): + items_copy = sorted(item, key=key_func, reverse=True) result = [] - totalValue, total_cost = 0.0, 0.0 - for i in range(len(itemsCopy)): - if (total_cost + itemsCopy[i].get_weight()) <= maxCost: - result.append(itemsCopy[i]) - total_cost += itemsCopy[i].get_weight() - totalValue += itemsCopy[i].get_value() - return (result, totalValue) + total_value, total_cost = 0.0, 0.0 + for i in range(len(items_copy)): + if (total_cost + items_copy[i].get_weight()) <= max_cost: + result.append(items_copy[i]) + total_cost += items_copy[i].get_weight() + total_value += items_copy[i].get_value() + return (result, total_value) def test_greedy(): @@ -47,13 +47,13 @@ def test_greedy(): >>> weight = [40, 60, 40, 70, 100, 85, 55, 70] >>> foods = build_menu(food, value, weight) >>> foods # doctest: +NORMALIZE_WHITESPACE - [things(Burger, 80, 40), things(Pizza, 100, 60), things(Coca Cola, 60, 40), - things(Rice, 70, 70), things(Sambhar, 50, 100), things(Chicken, 110, 85), - things(Fries, 90, 55), things(Milk, 60, 70)] - >>> greedy(foods, 500, things.get_value) # doctest: +NORMALIZE_WHITESPACE - ([things(Chicken, 110, 85), things(Pizza, 100, 60), things(Fries, 90, 55), - things(Burger, 80, 40), things(Rice, 70, 70), things(Coca Cola, 60, 40), - things(Milk, 60, 70)], 570.0) + [Things(Burger, 80, 40), Things(Pizza, 100, 60), Things(Coca Cola, 60, 40), + Things(Rice, 70, 70), Things(Sambhar, 50, 100), Things(Chicken, 110, 85), + Things(Fries, 90, 55), Things(Milk, 60, 70)] + >>> greedy(foods, 500, Things.get_value) # doctest: +NORMALIZE_WHITESPACE + ([Things(Chicken, 110, 85), Things(Pizza, 100, 60), Things(Fries, 90, 55), + Things(Burger, 80, 40), Things(Rice, 70, 70), Things(Coca Cola, 60, 40), + Things(Milk, 60, 70)], 570.0) """ diff --git a/other/nested_brackets.py b/other/nested_brackets.py index 99e2f3a38..9dd9a0f04 100644 --- a/other/nested_brackets.py +++ b/other/nested_brackets.py @@ -14,21 +14,21 @@ brackets and returns true if S is nested and false otherwise. """ -def is_balanced(S): +def is_balanced(s): stack = [] open_brackets = set({"(", "[", "{"}) closed_brackets = set({")", "]", "}"}) open_to_closed = dict({"{": "}", "[": "]", "(": ")"}) - for i in range(len(S)): + for i in range(len(s)): - if S[i] in open_brackets: - stack.append(S[i]) + if s[i] in open_brackets: + stack.append(s[i]) - elif S[i] in closed_brackets: + elif s[i] in closed_brackets: if len(stack) == 0 or ( - len(stack) > 0 and open_to_closed[stack.pop()] != S[i] + len(stack) > 0 and open_to_closed[stack.pop()] != s[i] ): return False diff --git a/other/sdes.py b/other/sdes.py index cfc5a53df..695675000 100644 --- a/other/sdes.py +++ b/other/sdes.py @@ -19,9 +19,9 @@ def left_shift(data): return data[1:] + data[0] -def XOR(a, b): +def xor(a, b): """ - >>> XOR("01010101", "00001111") + >>> xor("01010101", "00001111") '01011010' """ res = "" @@ -43,13 +43,13 @@ def function(expansion, s0, s1, key, message): left = message[:4] right = message[4:] temp = apply_table(right, expansion) - temp = XOR(temp, key) + temp = xor(temp, key) l = apply_sbox(s0, temp[:4]) # noqa: E741 r = apply_sbox(s1, temp[4:]) l = "0" * (2 - len(l)) + l # noqa: E741 r = "0" * (2 - len(r)) + r temp = apply_table(l + r, p4_table) - temp = XOR(left, temp) + temp = xor(left, temp) return temp + right diff --git a/other/tower_of_hanoi.py b/other/tower_of_hanoi.py index 3cc0e40b3..1fff45039 100644 --- a/other/tower_of_hanoi.py +++ b/other/tower_of_hanoi.py @@ -1,6 +1,6 @@ -def moveTower(height, fromPole, toPole, withPole): +def move_tower(height, from_pole, to_pole, with_pole): """ - >>> moveTower(3, 'A', 'B', 'C') + >>> move_tower(3, 'A', 'B', 'C') moving disk from A to B moving disk from A to C moving disk from B to C @@ -10,18 +10,18 @@ def moveTower(height, fromPole, toPole, withPole): moving disk from A to B """ if height >= 1: - moveTower(height - 1, fromPole, withPole, toPole) - moveDisk(fromPole, toPole) - moveTower(height - 1, withPole, toPole, fromPole) + move_tower(height - 1, from_pole, with_pole, to_pole) + move_disk(from_pole, to_pole) + move_tower(height - 1, with_pole, to_pole, from_pole) -def moveDisk(fp, tp): +def move_disk(fp, tp): print("moving disk from", fp, "to", tp) def main(): height = int(input("Height of hanoi: ").strip()) - moveTower(height, "A", "B", "C") + move_tower(height, "A", "B", "C") if __name__ == "__main__": diff --git a/physics/n_body_simulation.py b/physics/n_body_simulation.py index 01083b9a2..7e9fc1642 100644 --- a/physics/n_body_simulation.py +++ b/physics/n_body_simulation.py @@ -219,9 +219,11 @@ def plot( Utility function to plot how the given body-system evolves over time. No doctest provided since this function does not have a return value. """ + # Frame rate of the animation + INTERVAL = 20 # noqa: N806 - INTERVAL = 20 # Frame rate of the animation - DELTA_TIME = INTERVAL / 1000 # Time between time steps in seconds + # Time between time steps in seconds + DELTA_TIME = INTERVAL / 1000 # noqa: N806 fig = plt.figure() fig.canvas.set_window_title(title) diff --git a/project_euler/problem_011/sol1.py b/project_euler/problem_011/sol1.py index 9dea73e8c..ad45f0983 100644 --- a/project_euler/problem_011/sol1.py +++ b/project_euler/problem_011/sol1.py @@ -28,23 +28,23 @@ import os def largest_product(grid): - nColumns = len(grid[0]) - nRows = len(grid) + n_columns = len(grid[0]) + n_rows = len(grid) largest = 0 - lrDiagProduct = 0 - rlDiagProduct = 0 + lr_diag_product = 0 + rl_diag_product = 0 # Check vertically, horizontally, diagonally at the same time (only works # for nxn grid) - for i in range(nColumns): - for j in range(nRows - 3): - vertProduct = grid[j][i] * grid[j + 1][i] * grid[j + 2][i] * grid[j + 3][i] - horzProduct = grid[i][j] * grid[i][j + 1] * grid[i][j + 2] * grid[i][j + 3] + for i in range(n_columns): + for j in range(n_rows - 3): + vert_product = grid[j][i] * grid[j + 1][i] * grid[j + 2][i] * grid[j + 3][i] + horz_product = grid[i][j] * grid[i][j + 1] * grid[i][j + 2] * grid[i][j + 3] # Left-to-right diagonal (\) product - if i < nColumns - 3: - lrDiagProduct = ( + if i < n_columns - 3: + lr_diag_product = ( grid[i][j] * grid[i + 1][j + 1] * grid[i + 2][j + 2] @@ -53,16 +53,18 @@ def largest_product(grid): # Right-to-left diagonal(/) product if i > 2: - rlDiagProduct = ( + rl_diag_product = ( grid[i][j] * grid[i - 1][j + 1] * grid[i - 2][j + 2] * grid[i - 3][j + 3] ) - maxProduct = max(vertProduct, horzProduct, lrDiagProduct, rlDiagProduct) - if maxProduct > largest: - largest = maxProduct + max_product = max( + vert_product, horz_product, lr_diag_product, rl_diag_product + ) + if max_product > largest: + largest = max_product return largest diff --git a/project_euler/problem_012/sol1.py b/project_euler/problem_012/sol1.py index 861d026ec..e42b03419 100644 --- a/project_euler/problem_012/sol1.py +++ b/project_euler/problem_012/sol1.py @@ -24,18 +24,18 @@ divisors? def count_divisors(n): - nDivisors = 1 + n_divisors = 1 i = 2 while i * i <= n: multiplicity = 0 while n % i == 0: n //= i multiplicity += 1 - nDivisors *= multiplicity + 1 + n_divisors *= multiplicity + 1 i += 1 if n > 1: - nDivisors *= 2 - return nDivisors + n_divisors *= 2 + return n_divisors def solution(): @@ -45,17 +45,17 @@ def solution(): >>> solution() 76576500 """ - tNum = 1 + t_num = 1 i = 1 while True: i += 1 - tNum += i + t_num += i - if count_divisors(tNum) > 500: + if count_divisors(t_num) > 500: break - return tNum + return t_num if __name__ == "__main__": diff --git a/project_euler/problem_023/sol1.py b/project_euler/problem_023/sol1.py index 83b85f3f7..9fdf7284a 100644 --- a/project_euler/problem_023/sol1.py +++ b/project_euler/problem_023/sol1.py @@ -28,18 +28,18 @@ def solution(limit=28123): >>> solution() 4179871 """ - sumDivs = [1] * (limit + 1) + sum_divs = [1] * (limit + 1) for i in range(2, int(limit**0.5) + 1): - sumDivs[i * i] += i + sum_divs[i * i] += i for k in range(i + 1, limit // i + 1): - sumDivs[k * i] += k + i + sum_divs[k * i] += k + i abundants = set() res = 0 for n in range(1, limit + 1): - if sumDivs[n] > n: + if sum_divs[n] > n: abundants.add(n) if not any((n - a in abundants) for a in abundants): diff --git a/project_euler/problem_029/sol1.py b/project_euler/problem_029/sol1.py index d3ab90ac7..d9a81e55c 100644 --- a/project_euler/problem_029/sol1.py +++ b/project_euler/problem_029/sol1.py @@ -33,17 +33,17 @@ def solution(n: int = 100) -> int: >>> solution(1) 0 """ - collectPowers = set() + collect_powers = set() - currentPow = 0 + current_pow = 0 - N = n + 1 # maximum limit + n = n + 1 # maximum limit - for a in range(2, N): - for b in range(2, N): - currentPow = a**b # calculates the current power - collectPowers.add(currentPow) # adds the result to the set - return len(collectPowers) + for a in range(2, n): + for b in range(2, n): + current_pow = a**b # calculates the current power + collect_powers.add(current_pow) # adds the result to the set + return len(collect_powers) if __name__ == "__main__": diff --git a/project_euler/problem_032/sol32.py b/project_euler/problem_032/sol32.py index 393218339..c4d11e86c 100644 --- a/project_euler/problem_032/sol32.py +++ b/project_euler/problem_032/sol32.py @@ -15,15 +15,15 @@ include it once in your sum. import itertools -def isCombinationValid(combination): +def is_combination_valid(combination): """ Checks if a combination (a tuple of 9 digits) is a valid product equation. - >>> isCombinationValid(('3', '9', '1', '8', '6', '7', '2', '5', '4')) + >>> is_combination_valid(('3', '9', '1', '8', '6', '7', '2', '5', '4')) True - >>> isCombinationValid(('1', '2', '3', '4', '5', '6', '7', '8', '9')) + >>> is_combination_valid(('1', '2', '3', '4', '5', '6', '7', '8', '9')) False """ @@ -49,7 +49,7 @@ def solution(): { int("".join(pandigital[5:9])) for pandigital in itertools.permutations("123456789") - if isCombinationValid(pandigital) + if is_combination_valid(pandigital) } ) diff --git a/project_euler/problem_042/solution42.py b/project_euler/problem_042/solution42.py index b3aecf4cf..6d22a8dfb 100644 --- a/project_euler/problem_042/solution42.py +++ b/project_euler/problem_042/solution42.py @@ -27,10 +27,10 @@ def solution(): 162 """ script_dir = os.path.dirname(os.path.realpath(__file__)) - wordsFilePath = os.path.join(script_dir, "words.txt") + words_file_path = os.path.join(script_dir, "words.txt") words = "" - with open(wordsFilePath) as f: + with open(words_file_path) as f: words = f.readline() words = list(map(lambda word: word.strip('"'), words.strip("\r\n").split(","))) diff --git a/project_euler/problem_054/test_poker_hand.py b/project_euler/problem_054/test_poker_hand.py index 96317fc7d..bf5a20a8e 100644 --- a/project_euler/problem_054/test_poker_hand.py +++ b/project_euler/problem_054/test_poker_hand.py @@ -185,7 +185,7 @@ def test_compare_random(hand, other, expected): def test_hand_sorted(): - POKER_HANDS = [PokerHand(hand) for hand in SORTED_HANDS] + POKER_HANDS = [PokerHand(hand) for hand in SORTED_HANDS] # noqa: N806 list_copy = POKER_HANDS.copy() shuffle(list_copy) user_sorted = chain(sorted(list_copy)) diff --git a/project_euler/problem_064/sol1.py b/project_euler/problem_064/sol1.py index 5df64a90a..9edd9a1e7 100644 --- a/project_euler/problem_064/sol1.py +++ b/project_euler/problem_064/sol1.py @@ -33,7 +33,7 @@ def continuous_fraction_period(n: int) -> int: """ numerator = 0.0 denominator = 1.0 - ROOT = int(sqrt(n)) + ROOT = int(sqrt(n)) # noqa: N806 integer_part = ROOT period = 0 while integer_part != 2 * ROOT: diff --git a/project_euler/problem_097/sol1.py b/project_euler/problem_097/sol1.py index da5e8120b..94a43894e 100644 --- a/project_euler/problem_097/sol1.py +++ b/project_euler/problem_097/sol1.py @@ -34,8 +34,8 @@ def solution(n: int = 10) -> str: """ if not isinstance(n, int) or n < 0: raise ValueError("Invalid input") - MODULUS = 10**n - NUMBER = 28433 * (pow(2, 7830457, MODULUS)) + 1 + MODULUS = 10**n # noqa: N806 + NUMBER = 28433 * (pow(2, 7830457, MODULUS)) + 1 # noqa: N806 return str(NUMBER % MODULUS) diff --git a/project_euler/problem_104/sol.py b/project_euler/problem_104/sol.py.FIXME similarity index 100% rename from project_euler/problem_104/sol.py rename to project_euler/problem_104/sol.py.FIXME diff --git a/project_euler/problem_125/sol1.py b/project_euler/problem_125/sol1.py index 7a8f908ed..1812df361 100644 --- a/project_euler/problem_125/sol1.py +++ b/project_euler/problem_125/sol1.py @@ -35,7 +35,7 @@ def solution() -> int: Returns the sum of all numbers less than 1e8 that are both palindromic and can be written as the sum of consecutive squares. """ - LIMIT = 10**8 + LIMIT = 10**8 # noqa: N806 answer = set() first_square = 1 sum_squares = 5 diff --git a/scheduling/non_preemptive_shortest_job_first.py b/scheduling/non_preemptive_shortest_job_first.py index 96e571230..69c974b00 100644 --- a/scheduling/non_preemptive_shortest_job_first.py +++ b/scheduling/non_preemptive_shortest_job_first.py @@ -102,9 +102,9 @@ if __name__ == "__main__": # Printing the Result print("PID\tBurst Time\tArrival Time\tWaiting Time\tTurnaround Time") - for i, process_ID in enumerate(list(range(1, 5))): + for i, process_id in enumerate(list(range(1, 5))): print( - f"{process_ID}\t{burst_time[i]}\t\t\t{arrival_time[i]}\t\t\t\t" + f"{process_id}\t{burst_time[i]}\t\t\t{arrival_time[i]}\t\t\t\t" f"{waiting_time[i]}\t\t\t\t{turn_around_time[i]}" ) print(f"\nAverage waiting time = {mean(waiting_time):.5f}") diff --git a/searches/tabu_search.py b/searches/tabu_search.py index 24d0dbf6f..45ce19d46 100644 --- a/searches/tabu_search.py +++ b/searches/tabu_search.py @@ -178,9 +178,9 @@ def find_neighborhood(solution, dict_of_neighbours): if _tmp not in neighborhood_of_solution: neighborhood_of_solution.append(_tmp) - indexOfLastItemInTheList = len(neighborhood_of_solution[0]) - 1 + index_of_last_item_in_the_list = len(neighborhood_of_solution[0]) - 1 - neighborhood_of_solution.sort(key=lambda x: x[indexOfLastItemInTheList]) + neighborhood_of_solution.sort(key=lambda x: x[index_of_last_item_in_the_list]) return neighborhood_of_solution diff --git a/sorts/odd_even_transposition_parallel.py b/sorts/odd_even_transposition_parallel.py index 5de7a016c..b656df3a3 100644 --- a/sorts/odd_even_transposition_parallel.py +++ b/sorts/odd_even_transposition_parallel.py @@ -13,7 +13,7 @@ synchronization could be used. from multiprocessing import Lock, Pipe, Process # lock used to ensure that two processes do not access a pipe at the same time -processLock = Lock() +process_lock = Lock() """ The function run by the processes that sorts the list @@ -27,42 +27,42 @@ resultPipe = the pipe used to send results back to main """ -def oeProcess(position, value, LSend, RSend, LRcv, RRcv, resultPipe): - global processLock +def oe_process(position, value, l_send, r_send, lr_cv, rr_cv, result_pipe): + global process_lock # we perform n swaps since after n swaps we know we are sorted # we *could* stop early if we are sorted already, but it takes as long to # find out we are sorted as it does to sort the list with this algorithm for i in range(0, 10): - if (i + position) % 2 == 0 and RSend is not None: + if (i + position) % 2 == 0 and r_send is not None: # send your value to your right neighbor - processLock.acquire() - RSend[1].send(value) - processLock.release() + process_lock.acquire() + r_send[1].send(value) + process_lock.release() # receive your right neighbor's value - processLock.acquire() - temp = RRcv[0].recv() - processLock.release() + process_lock.acquire() + temp = rr_cv[0].recv() + process_lock.release() # take the lower value since you are on the left value = min(value, temp) - elif (i + position) % 2 != 0 and LSend is not None: + elif (i + position) % 2 != 0 and l_send is not None: # send your value to your left neighbor - processLock.acquire() - LSend[1].send(value) - processLock.release() + process_lock.acquire() + l_send[1].send(value) + process_lock.release() # receive your left neighbor's value - processLock.acquire() - temp = LRcv[0].recv() - processLock.release() + process_lock.acquire() + temp = lr_cv[0].recv() + process_lock.release() # take the higher value since you are on the right value = max(value, temp) # after all swaps are performed, send the values back to main - resultPipe[1].send(value) + result_pipe[1].send(value) """ @@ -72,61 +72,61 @@ arr = the list to be sorted """ -def OddEvenTransposition(arr): - processArray = [] - resultPipe = [] +def odd_even_transposition(arr): + process_array_ = [] + result_pipe = [] # initialize the list of pipes where the values will be retrieved for _ in arr: - resultPipe.append(Pipe()) + result_pipe.append(Pipe()) # creates the processes # the first and last process only have one neighbor so they are made outside # of the loop - tempRs = Pipe() - tempRr = Pipe() - processArray.append( + temp_rs = Pipe() + temp_rr = Pipe() + process_array_.append( Process( - target=oeProcess, - args=(0, arr[0], None, tempRs, None, tempRr, resultPipe[0]), + target=oe_process, + args=(0, arr[0], None, temp_rs, None, temp_rr, result_pipe[0]), ) ) - tempLr = tempRs - tempLs = tempRr + temp_lr = temp_rs + temp_ls = temp_rr for i in range(1, len(arr) - 1): - tempRs = Pipe() - tempRr = Pipe() - processArray.append( + temp_rs = Pipe() + temp_rr = Pipe() + process_array_.append( Process( - target=oeProcess, - args=(i, arr[i], tempLs, tempRs, tempLr, tempRr, resultPipe[i]), + target=oe_process, + args=(i, arr[i], temp_ls, temp_rs, temp_lr, temp_rr, result_pipe[i]), ) ) - tempLr = tempRs - tempLs = tempRr + temp_lr = temp_rs + temp_ls = temp_rr - processArray.append( + process_array_.append( Process( - target=oeProcess, + target=oe_process, args=( len(arr) - 1, arr[len(arr) - 1], - tempLs, + temp_ls, None, - tempLr, + temp_lr, None, - resultPipe[len(arr) - 1], + result_pipe[len(arr) - 1], ), ) ) # start the processes - for p in processArray: + for p in process_array_: p.start() # wait for the processes to end and write their values to the list - for p in range(0, len(resultPipe)): - arr[p] = resultPipe[p][0].recv() - processArray[p].join() + for p in range(0, len(result_pipe)): + arr[p] = result_pipe[p][0].recv() + process_array_[p].join() return arr @@ -135,7 +135,7 @@ def main(): arr = list(range(10, 0, -1)) print("Initial List") print(*arr) - arr = OddEvenTransposition(arr) + arr = odd_even_transposition(arr) print("Sorted List\n") print(*arr) diff --git a/sorts/radix_sort.py b/sorts/radix_sort.py index c3ff04f3d..afe62bc7e 100644 --- a/sorts/radix_sort.py +++ b/sorts/radix_sort.py @@ -19,7 +19,7 @@ def radix_sort(list_of_ints: list[int]) -> list[int]: >>> radix_sort([1,100,10,1000]) == sorted([1,100,10,1000]) True """ - RADIX = 10 + RADIX = 10 # noqa: N806 placement = 1 max_digit = max(list_of_ints) while placement <= max_digit: diff --git a/sorts/random_normal_distribution_quicksort.py b/sorts/random_normal_distribution_quicksort.py index 73eb70bea..5777d5cb2 100644 --- a/sorts/random_normal_distribution_quicksort.py +++ b/sorts/random_normal_distribution_quicksort.py @@ -4,41 +4,41 @@ from tempfile import TemporaryFile import numpy as np -def _inPlaceQuickSort(A, start, end): +def _in_place_quick_sort(a, start, end): count = 0 if start < end: pivot = randint(start, end) - temp = A[end] - A[end] = A[pivot] - A[pivot] = temp + temp = a[end] + a[end] = a[pivot] + a[pivot] = temp - p, count = _inPlacePartition(A, start, end) - count += _inPlaceQuickSort(A, start, p - 1) - count += _inPlaceQuickSort(A, p + 1, end) + p, count = _in_place_partition(a, start, end) + count += _in_place_quick_sort(a, start, p - 1) + count += _in_place_quick_sort(a, p + 1, end) return count -def _inPlacePartition(A, start, end): +def _in_place_partition(a, start, end): count = 0 pivot = randint(start, end) - temp = A[end] - A[end] = A[pivot] - A[pivot] = temp - newPivotIndex = start - 1 + temp = a[end] + a[end] = a[pivot] + a[pivot] = temp + new_pivot_index = start - 1 for index in range(start, end): count += 1 - if A[index] < A[end]: # check if current val is less than pivot value - newPivotIndex = newPivotIndex + 1 - temp = A[newPivotIndex] - A[newPivotIndex] = A[index] - A[index] = temp + if a[index] < a[end]: # check if current val is less than pivot value + new_pivot_index = new_pivot_index + 1 + temp = a[new_pivot_index] + a[new_pivot_index] = a[index] + a[index] = temp - temp = A[newPivotIndex + 1] - A[newPivotIndex + 1] = A[end] - A[end] = temp - return newPivotIndex + 1, count + temp = a[new_pivot_index + 1] + a[new_pivot_index + 1] = a[end] + a[end] = temp + return new_pivot_index + 1, count outfile = TemporaryFile() @@ -55,7 +55,7 @@ print(X) outfile.seek(0) # using the same array M = np.load(outfile) r = len(M) - 1 -z = _inPlaceQuickSort(M, 0, r) +z = _in_place_quick_sort(M, 0, r) print( "No of Comparisons for 100 elements selected from a standard normal distribution" diff --git a/sorts/random_pivot_quick_sort.py b/sorts/random_pivot_quick_sort.py index d9cf4e981..748b67410 100644 --- a/sorts/random_pivot_quick_sort.py +++ b/sorts/random_pivot_quick_sort.py @@ -4,30 +4,30 @@ Picks the random index as the pivot import random -def partition(A, left_index, right_index): - pivot = A[left_index] +def partition(a, left_index, right_index): + pivot = a[left_index] i = left_index + 1 for j in range(left_index + 1, right_index): - if A[j] < pivot: - A[j], A[i] = A[i], A[j] + if a[j] < pivot: + a[j], a[i] = a[i], a[j] i += 1 - A[left_index], A[i - 1] = A[i - 1], A[left_index] + a[left_index], a[i - 1] = a[i - 1], a[left_index] return i - 1 -def quick_sort_random(A, left, right): +def quick_sort_random(a, left, right): if left < right: pivot = random.randint(left, right - 1) - A[pivot], A[left] = ( - A[left], - A[pivot], + a[pivot], a[left] = ( + a[left], + a[pivot], ) # switches the pivot with the left most bound - pivot_index = partition(A, left, right) + pivot_index = partition(a, left, right) quick_sort_random( - A, left, pivot_index + a, left, pivot_index ) # recursive quicksort to the left of the pivot point quick_sort_random( - A, pivot_index + 1, right + a, pivot_index + 1, right ) # recursive quicksort to the right of the pivot point diff --git a/sorts/tree_sort.py b/sorts/tree_sort.py index e445fb452..78c3e893e 100644 --- a/sorts/tree_sort.py +++ b/sorts/tree_sort.py @@ -5,7 +5,7 @@ Build a BST and in order traverse. """ -class node: +class Node: # BST data structure def __init__(self, val): self.val = val @@ -16,12 +16,12 @@ class node: if self.val: if val < self.val: if self.left is None: - self.left = node(val) + self.left = Node(val) else: self.left.insert(val) elif val > self.val: if self.right is None: - self.right = node(val) + self.right = Node(val) else: self.right.insert(val) else: @@ -40,7 +40,7 @@ def tree_sort(arr): # Build BST if len(arr) == 0: return arr - root = node(arr[0]) + root = Node(arr[0]) for i in range(1, len(arr)): root.insert(arr[i]) # Traverse BST in order. diff --git a/strings/boyer_moore_search.py b/strings/boyer_moore_search.py index 8d8ff22f6..117305d32 100644 --- a/strings/boyer_moore_search.py +++ b/strings/boyer_moore_search.py @@ -41,13 +41,13 @@ class BoyerMooreSearch: return i return -1 - def mismatch_in_text(self, currentPos: int) -> int: + def mismatch_in_text(self, current_pos: int) -> int: """ find the index of mis-matched character in text when compared with pattern from last Parameters : - currentPos (int): current index position of text + current_pos (int): current index position of text Returns : i (int): index of mismatched char from last in text @@ -55,8 +55,8 @@ class BoyerMooreSearch: """ for i in range(self.patLen - 1, -1, -1): - if self.pattern[i] != self.text[currentPos + i]: - return currentPos + i + if self.pattern[i] != self.text[current_pos + i]: + return current_pos + i return -1 def bad_character_heuristic(self) -> list[int]: diff --git a/strings/can_string_be_rearranged_as_palindrome.py b/strings/can_string_be_rearranged_as_palindrome.py index ddc4828c7..21d653db1 100644 --- a/strings/can_string_be_rearranged_as_palindrome.py +++ b/strings/can_string_be_rearranged_as_palindrome.py @@ -67,12 +67,12 @@ def can_string_be_rearranged_as_palindrome(input_str: str = "") -> bool: Step 2:If we find more than 1 character that appears odd number of times, It is not possible to rearrange as a palindrome """ - oddChar = 0 + odd_char = 0 for character_count in character_freq_dict.values(): if character_count % 2: - oddChar += 1 - if oddChar > 1: + odd_char += 1 + if odd_char > 1: return False return True diff --git a/strings/check_anagrams.py b/strings/check_anagrams.py index f652e2294..0d2f8091a 100644 --- a/strings/check_anagrams.py +++ b/strings/check_anagrams.py @@ -48,8 +48,8 @@ if __name__ == "__main__": from doctest import testmod testmod() - input_A = input("Enter the first string ").strip() - input_B = input("Enter the second string ").strip() + input_a = input("Enter the first string ").strip() + input_b = input("Enter the second string ").strip() - status = check_anagrams(input_A, input_B) - print(f"{input_A} and {input_B} are {'' if status else 'not '}anagrams.") + status = check_anagrams(input_a, input_b) + print(f"{input_a} and {input_b} are {'' if status else 'not '}anagrams.") diff --git a/strings/word_patterns.py b/strings/word_patterns.py index 90b092a20..d12d267e7 100644 --- a/strings/word_patterns.py +++ b/strings/word_patterns.py @@ -26,10 +26,10 @@ if __name__ == "__main__": start_time = time.time() with open("dictionary.txt") as in_file: - wordList = in_file.read().splitlines() + word_list = in_file.read().splitlines() all_patterns: dict = {} - for word in wordList: + for word in word_list: pattern = get_word_pattern(word) if pattern in all_patterns: all_patterns[pattern].append(word) @@ -39,6 +39,6 @@ if __name__ == "__main__": with open("word_patterns.txt", "w") as out_file: out_file.write(pprint.pformat(all_patterns)) - totalTime = round(time.time() - start_time, 2) - print(f"Done! {len(all_patterns):,} word patterns found in {totalTime} seconds.") + total_time = round(time.time() - start_time, 2) + print(f"Done! {len(all_patterns):,} word patterns found in {total_time} seconds.") # Done! 9,581 word patterns found in 0.58 seconds. diff --git a/web_programming/fetch_quotes.py b/web_programming/fetch_quotes.py index 4a3b002e5..a45f6ea0e 100644 --- a/web_programming/fetch_quotes.py +++ b/web_programming/fetch_quotes.py @@ -12,12 +12,12 @@ import requests def quote_of_the_day() -> list: - API_ENDPOINT_URL = "https://zenquotes.io/api/today/" + API_ENDPOINT_URL = "https://zenquotes.io/api/today/" # noqa: N806 return requests.get(API_ENDPOINT_URL).json() def random_quotes() -> list: - API_ENDPOINT_URL = "https://zenquotes.io/api/random/" + API_ENDPOINT_URL = "https://zenquotes.io/api/random/" # noqa: N806 return requests.get(API_ENDPOINT_URL).json() From 1aa7bd96164bf9f17acd770f4c6992d35c468541 Mon Sep 17 00:00:00 2001 From: Abinash Satapathy Date: Thu, 13 Oct 2022 00:56:10 +0200 Subject: [PATCH 351/726] Added barcode_validator.py (#6771) * Update README.md Added Google Cirq references * Create barcode_validator.py Barcode/EAN validator * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update barcode_validator.py Included docstring and updated variables to snake_case * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update barcode_validator.py Included docset and updated bugs * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update barcode_validator.py Implemented the changes asked in review. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update barcode_validator.py Updated with f-string format * Update barcode_validator.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- quantum/README.md | 8 ++++ strings/barcode_validator.py | 88 ++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 strings/barcode_validator.py diff --git a/quantum/README.md b/quantum/README.md index 423d34fa3..3ce364574 100644 --- a/quantum/README.md +++ b/quantum/README.md @@ -6,6 +6,7 @@ Started at https://github.com/TheAlgorithms/Python/issues/1831 * Google: https://research.google/teams/applied-science/quantum * IBM: https://qiskit.org and https://github.com/Qiskit * Rigetti: https://rigetti.com and https://github.com/rigetti +* Zapata: https://www.zapatacomputing.com and https://github.com/zapatacomputing ## IBM Qiskit - Start using by installing `pip install qiskit`, refer the [docs](https://qiskit.org/documentation/install.html) for more info. @@ -13,3 +14,10 @@ Started at https://github.com/TheAlgorithms/Python/issues/1831 - https://github.com/Qiskit/qiskit-tutorials - https://quantum-computing.ibm.com/docs/iql/first-circuit - https://medium.com/qiskit/how-to-program-a-quantum-computer-982a9329ed02 + +## Google Cirq +- Start using by installing `python -m pip install cirq`, refer the [docs](https://quantumai.google/cirq/start/install) for more info. +- Tutorials & references + - https://github.com/quantumlib/cirq + - https://quantumai.google/cirq/experiments + - https://tanishabassan.medium.com/quantum-programming-with-google-cirq-3209805279bc diff --git a/strings/barcode_validator.py b/strings/barcode_validator.py new file mode 100644 index 000000000..056700076 --- /dev/null +++ b/strings/barcode_validator.py @@ -0,0 +1,88 @@ +""" +https://en.wikipedia.org/wiki/Check_digit#Algorithms +""" + + +def get_check_digit(barcode: int) -> int: + """ + Returns the last digit of barcode by excluding the last digit first + and then computing to reach the actual last digit from the remaining + 12 digits. + + >>> get_check_digit(8718452538119) + 9 + >>> get_check_digit(87184523) + 5 + >>> get_check_digit(87193425381086) + 9 + >>> [get_check_digit(x) for x in range(0, 100, 10)] + [0, 7, 4, 1, 8, 5, 2, 9, 6, 3] + """ + barcode //= 10 # exclude the last digit + checker = False + s = 0 + + # extract and check each digit + while barcode != 0: + mult = 1 if checker else 3 + s += mult * (barcode % 10) + barcode //= 10 + checker = not checker + + return (10 - (s % 10)) % 10 + + +def is_valid(barcode: int) -> bool: + """ + Checks for length of barcode and last-digit + Returns boolean value of validity of barcode + + >>> is_valid(8718452538119) + True + >>> is_valid(87184525) + False + >>> is_valid(87193425381089) + False + >>> is_valid(0) + False + >>> is_valid(dwefgiweuf) + Traceback (most recent call last): + ... + NameError: name 'dwefgiweuf' is not defined + """ + return len(str(barcode)) == 13 and get_check_digit(barcode) == barcode % 10 + + +def get_barcode(barcode: str) -> int: + """ + Returns the barcode as an integer + + >>> get_barcode("8718452538119") + 8718452538119 + >>> get_barcode("dwefgiweuf") + Traceback (most recent call last): + ... + ValueError: Barcode 'dwefgiweuf' has alphabetic characters. + """ + if str(barcode).isalpha(): + raise ValueError(f"Barcode '{barcode}' has alphabetic characters.") + elif int(barcode) < 0: + raise ValueError("The entered barcode has a negative value. Try again.") + else: + return int(barcode) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + """ + Enter a barcode. + + """ + barcode = get_barcode(input("Barcode: ").strip()) + + if is_valid(barcode): + print(f"'{barcode}' is a valid Barcode") + else: + print(f"'{barcode}' is NOT is valid Barcode.") From 6118b05f0efd1c2839eb8bc4de36723af1fcc364 Mon Sep 17 00:00:00 2001 From: Carlos Villar Date: Thu, 13 Oct 2022 08:24:53 +0200 Subject: [PATCH 352/726] Convert snake_case to camelCase or PascalCase (#7028) (#7034) * Added snake_case to Camel or Pascal case Fixes: #7028 * Added suggested changes * Add ending empty line from suggestion Co-authored-by: Caeden * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update strings/snake_case_to_camel_pascal_case.py Co-authored-by: Christian Clauss Co-authored-by: Caeden Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- strings/snake_case_to_camel_pascal_case.py | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 strings/snake_case_to_camel_pascal_case.py diff --git a/strings/snake_case_to_camel_pascal_case.py b/strings/snake_case_to_camel_pascal_case.py new file mode 100644 index 000000000..7b2b61d1d --- /dev/null +++ b/strings/snake_case_to_camel_pascal_case.py @@ -0,0 +1,52 @@ +def snake_to_camel_case(input: str, use_pascal: bool = False) -> str: + """ + Transforms a snake_case given string to camelCase (or PascalCase if indicated) + (defaults to not use Pascal) + + >>> snake_to_camel_case("some_random_string") + 'someRandomString' + + >>> snake_to_camel_case("some_random_string", use_pascal=True) + 'SomeRandomString' + + >>> snake_to_camel_case("some_random_string_with_numbers_123") + 'someRandomStringWithNumbers123' + + >>> snake_to_camel_case("some_random_string_with_numbers_123", use_pascal=True) + 'SomeRandomStringWithNumbers123' + + >>> snake_to_camel_case(123) + Traceback (most recent call last): + ... + ValueError: Expected string as input, found + + >>> snake_to_camel_case("some_string", use_pascal="True") + Traceback (most recent call last): + ... + ValueError: Expected boolean as use_pascal parameter, found + """ + + if not isinstance(input, str): + raise ValueError(f"Expected string as input, found {type(input)}") + if not isinstance(use_pascal, bool): + raise ValueError( + f"Expected boolean as use_pascal parameter, found {type(use_pascal)}" + ) + + words = input.split("_") + + start_index = 0 if use_pascal else 1 + + words_to_capitalize = words[start_index:] + + capitalized_words = [word[0].upper() + word[1:] for word in words_to_capitalize] + + initial_word = "" if use_pascal else words[0] + + return "".join([initial_word] + capitalized_words) + + +if __name__ == "__main__": + from doctest import testmod + + testmod() From 7ad6c6402945349fbca42cce5acad631b0930a1d Mon Sep 17 00:00:00 2001 From: Saksham Chawla <51916697+saksham-chawla@users.noreply.github.com> Date: Thu, 13 Oct 2022 15:15:20 +0530 Subject: [PATCH 353/726] Add typing to maths/add.py (#7064) * Add typing to maths/add.py https://stackoverflow.com/questions/50928592/mypy-type-hint-unionfloat-int-is-there-a-number-type * Update add.py * Update add.py --- maths/add.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths/add.py b/maths/add.py index 0bc7da969..c89252c64 100644 --- a/maths/add.py +++ b/maths/add.py @@ -3,7 +3,7 @@ Just to check """ -def add(a, b): +def add(a: float, b: float) -> float: """ >>> add(2, 2) 4 From 9b0909d6545df269dc2c943df2e470671f0d1bcf Mon Sep 17 00:00:00 2001 From: Saksham Chawla <51916697+saksham-chawla@users.noreply.github.com> Date: Thu, 13 Oct 2022 16:17:52 +0530 Subject: [PATCH 354/726] Add typing and snake casing to maths/decimal_isolate.py (#7066) --- maths/decimal_isolate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths/decimal_isolate.py b/maths/decimal_isolate.py index 1b8f6cbca..cdf43ea5d 100644 --- a/maths/decimal_isolate.py +++ b/maths/decimal_isolate.py @@ -4,7 +4,7 @@ https://stackoverflow.com/questions/3886402/how-to-get-numbers-after-decimal-poi """ -def decimal_isolate(number, digit_amount): +def decimal_isolate(number: float, digit_amount: int) -> float: """ Isolates the decimal part of a number. From c73cb7e3f7324ab2715ffc74ab18c32e3a90a065 Mon Sep 17 00:00:00 2001 From: Saksham Chawla <51916697+saksham-chawla@users.noreply.github.com> Date: Thu, 13 Oct 2022 16:18:28 +0530 Subject: [PATCH 355/726] Add typing to maths/sum_of_arithmetic_series.py (#7065) --- maths/sum_of_arithmetic_series.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths/sum_of_arithmetic_series.py b/maths/sum_of_arithmetic_series.py index 74eef0f18..e0e22760b 100644 --- a/maths/sum_of_arithmetic_series.py +++ b/maths/sum_of_arithmetic_series.py @@ -1,5 +1,5 @@ # DarkCoder -def sum_of_series(first_term, common_diff, num_of_terms): +def sum_of_series(first_term: int, common_diff: int, num_of_terms: int) -> float: """ Find the sum of n terms in an arithmetic progression. From e661b9882995718ed967e33c2c814866b26fa76d Mon Sep 17 00:00:00 2001 From: GURNEET SINGH <79376134+SinghGurneet21@users.noreply.github.com> Date: Thu, 13 Oct 2022 17:39:01 +0530 Subject: [PATCH 356/726] Binary Search Tree Inorder Traversal Algorithm (#6840) * Binary Search Tree Inorder Traversal * updating DIRECTORY.md * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Binary Search Tree Inorder Traversal v2 * Binary Search Tree Inorder Traversal * Binary Search Tree Inorder Traversal * Update inorder_tree_traversal_2022.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update inorder_tree_traversal_2022.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update inorder_tree_traversal_2022.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update data_structures/binary_tree/inorder_tree_traversal_2022.py * Update data_structures/binary_tree/inorder_tree_traversal_2022.py * Updated * Updated * Update inorder_tree_traversal_2022.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update inorder_tree_traversal_2022.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update data_structures/binary_tree/inorder_tree_traversal_2022.py Co-authored-by: Christian Clauss * Updated and removed print statement removed the print from inorder function * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- DIRECTORY.md | 1 + .../inorder_tree_traversal_2022.py | 83 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 data_structures/binary_tree/inorder_tree_traversal_2022.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 25272af4a..2786e1f82 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -153,6 +153,7 @@ * [Binary Tree Mirror](data_structures/binary_tree/binary_tree_mirror.py) * [Binary Tree Traversals](data_structures/binary_tree/binary_tree_traversals.py) * [Fenwick Tree](data_structures/binary_tree/fenwick_tree.py) + * [Inorder Tree Traversal 2022](data_structures/binary_tree/inorder_tree_traversal_2022.py) * [Lazy Segment Tree](data_structures/binary_tree/lazy_segment_tree.py) * [Lowest Common Ancestor](data_structures/binary_tree/lowest_common_ancestor.py) * [Maximum Fenwick Tree](data_structures/binary_tree/maximum_fenwick_tree.py) diff --git a/data_structures/binary_tree/inorder_tree_traversal_2022.py b/data_structures/binary_tree/inorder_tree_traversal_2022.py new file mode 100644 index 000000000..08001738f --- /dev/null +++ b/data_structures/binary_tree/inorder_tree_traversal_2022.py @@ -0,0 +1,83 @@ +""" +Illustrate how to implement inorder traversal in binary search tree. +Author: Gurneet Singh +https://www.geeksforgeeks.org/tree-traversals-inorder-preorder-and-postorder/ +""" + + +class BinaryTreeNode: + """Defining the structure of BinaryTreeNode""" + + def __init__(self, data: int) -> None: + self.data = data + self.left_child: BinaryTreeNode | None = None + self.right_child: BinaryTreeNode | None = None + + +def insert(node: BinaryTreeNode | None, new_value: int) -> BinaryTreeNode | None: + """ + If the binary search tree is empty, make a new node and declare it as root. + >>> node_a = BinaryTreeNode(12345) + >>> node_b = insert(node_a, 67890) + >>> node_a.left_child == node_b.left_child + True + >>> node_a.right_child == node_b.right_child + True + >>> node_a.data == node_b.data + True + """ + if node is None: + node = BinaryTreeNode(new_value) + return node + + # binary search tree is not empty, + # so we will insert it into the tree + # if new_value is less than value of data in node, + # add it to left subtree and proceed recursively + if new_value < node.data: + node.left_child = insert(node.left_child, new_value) + else: + # if new_value is greater than value of data in node, + # add it to right subtree and proceed recursively + node.right_child = insert(node.right_child, new_value) + return node + + +def inorder(node: None | BinaryTreeNode) -> list[int]: # if node is None,return + """ + >>> inorder(make_tree()) + [6, 10, 14, 15, 20, 25, 60] + """ + if node: + inorder_array = inorder(node.left_child) + inorder_array = inorder_array + [node.data] + inorder_array = inorder_array + inorder(node.right_child) + else: + inorder_array = [] + return inorder_array + + +def make_tree() -> BinaryTreeNode | None: + + root = insert(None, 15) + insert(root, 10) + insert(root, 25) + insert(root, 6) + insert(root, 14) + insert(root, 20) + insert(root, 60) + return root + + +def main() -> None: + # main function + root = make_tree() + print("Printing values of binary search tree in Inorder Traversal.") + inorder(root) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + main() From d5a9f649b8279858add6fe6dd5a84af2f40a4cc9 Mon Sep 17 00:00:00 2001 From: Caeden Date: Thu, 13 Oct 2022 15:23:59 +0100 Subject: [PATCH 357/726] Add flake8-builtins to pre-commit and fix errors (#7105) Ignore `A003` Co-authored-by: Christian Clauss Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Dhruv Manilawala --- .flake8 | 3 +++ .pre-commit-config.yaml | 2 +- arithmetic_analysis/gaussian_elimination.py | 6 +++--- arithmetic_analysis/jacobi_iteration_method.py | 6 +++--- audio_filters/show_response.py | 8 ++++---- backtracking/hamiltonian_cycle.py | 6 +++--- data_structures/binary_tree/avl_tree.py | 2 +- data_structures/linked_list/__init__.py | 2 +- .../linked_list/singly_linked_list.py | 4 ++-- data_structures/queue/double_ended_queue.py | 16 ++++++++-------- data_structures/stacks/next_greater_element.py | 12 ++++++------ digital_image_processing/index_calculation.py | 6 +++--- .../optimal_binary_search_tree.py | 6 +++--- graphs/a_star.py | 8 ++++---- graphs/dijkstra.py | 4 ++-- graphs/finding_bridges.py | 14 +++++++------- graphs/prim.py | 4 ++-- hashes/djb2.py | 6 +++--- hashes/sdbm.py | 8 +++++--- maths/armstrong_numbers.py | 12 ++++++------ maths/bailey_borwein_plouffe.py | 6 +++--- maths/kadanes.py | 8 ++++---- maths/prime_numbers.py | 14 +++++++------- maths/sum_of_arithmetic_series.py | 4 ++-- neural_network/2_hidden_layers_neural_network.py | 10 ++++++---- neural_network/convolution_neural_network.py | 10 +++++----- neural_network/perceptron.py | 4 ++-- project_euler/problem_065/sol1.py | 4 ++-- project_euler/problem_070/sol1.py | 6 +++--- sorts/odd_even_sort.py | 10 +++++----- strings/snake_case_to_camel_pascal_case.py | 8 ++++---- 31 files changed, 113 insertions(+), 106 deletions(-) create mode 100644 .flake8 diff --git a/.flake8 b/.flake8 new file mode 100644 index 000000000..9a5863c9c --- /dev/null +++ b/.flake8 @@ -0,0 +1,3 @@ +[flake8] +extend-ignore = + A003 # Class attribute is shadowing a python builtin diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2f6a92814..e0de70b01 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,7 +40,7 @@ repos: - --ignore=E203,W503 - --max-complexity=25 - --max-line-length=88 - additional_dependencies: [pep8-naming] + additional_dependencies: [flake8-builtins, pep8-naming] - repo: https://github.com/pre-commit/mirrors-mypy rev: v0.982 diff --git a/arithmetic_analysis/gaussian_elimination.py b/arithmetic_analysis/gaussian_elimination.py index 89ed3b323..f0f20af8e 100644 --- a/arithmetic_analysis/gaussian_elimination.py +++ b/arithmetic_analysis/gaussian_elimination.py @@ -33,11 +33,11 @@ def retroactive_resolution( x: NDArray[float64] = np.zeros((rows, 1), dtype=float) for row in reversed(range(rows)): - sum = 0 + total = 0 for col in range(row + 1, columns): - sum += coefficients[row, col] * x[col] + total += coefficients[row, col] * x[col] - x[row, 0] = (vector[row] - sum) / coefficients[row, row] + x[row, 0] = (vector[row] - total) / coefficients[row, row] return x diff --git a/arithmetic_analysis/jacobi_iteration_method.py b/arithmetic_analysis/jacobi_iteration_method.py index 4336aaa91..0aab4db20 100644 --- a/arithmetic_analysis/jacobi_iteration_method.py +++ b/arithmetic_analysis/jacobi_iteration_method.py @@ -147,14 +147,14 @@ def strictly_diagonally_dominant(table: NDArray[float64]) -> bool: is_diagonally_dominant = True for i in range(0, rows): - sum = 0 + total = 0 for j in range(0, cols - 1): if i == j: continue else: - sum += table[i][j] + total += table[i][j] - if table[i][i] <= sum: + if table[i][i] <= total: raise ValueError("Coefficient matrix is not strictly diagonally dominant") return is_diagonally_dominant diff --git a/audio_filters/show_response.py b/audio_filters/show_response.py index 6e2731a58..097b8152b 100644 --- a/audio_filters/show_response.py +++ b/audio_filters/show_response.py @@ -34,7 +34,7 @@ def get_bounds( return lowest, highest -def show_frequency_response(filter: FilterType, samplerate: int) -> None: +def show_frequency_response(filter_type: FilterType, samplerate: int) -> None: """ Show frequency response of a filter @@ -45,7 +45,7 @@ def show_frequency_response(filter: FilterType, samplerate: int) -> None: size = 512 inputs = [1] + [0] * (size - 1) - outputs = [filter.process(item) for item in inputs] + outputs = [filter_type.process(item) for item in inputs] filler = [0] * (samplerate - size) # zero-padding outputs += filler @@ -66,7 +66,7 @@ def show_frequency_response(filter: FilterType, samplerate: int) -> None: plt.show() -def show_phase_response(filter: FilterType, samplerate: int) -> None: +def show_phase_response(filter_type: FilterType, samplerate: int) -> None: """ Show phase response of a filter @@ -77,7 +77,7 @@ def show_phase_response(filter: FilterType, samplerate: int) -> None: size = 512 inputs = [1] + [0] * (size - 1) - outputs = [filter.process(item) for item in inputs] + outputs = [filter_type.process(item) for item in inputs] filler = [0] * (samplerate - size) # zero-padding outputs += filler diff --git a/backtracking/hamiltonian_cycle.py b/backtracking/hamiltonian_cycle.py index 500e993e5..4c6ae4679 100644 --- a/backtracking/hamiltonian_cycle.py +++ b/backtracking/hamiltonian_cycle.py @@ -95,10 +95,10 @@ def util_hamilton_cycle(graph: list[list[int]], path: list[int], curr_ind: int) return graph[path[curr_ind - 1]][path[0]] == 1 # Recursive Step - for next in range(0, len(graph)): - if valid_connection(graph, next, curr_ind, path): + for next_ver in range(0, len(graph)): + if valid_connection(graph, next_ver, curr_ind, path): # Insert current vertex into path as next transition - path[curr_ind] = next + path[curr_ind] = next_ver # Validate created path if util_hamilton_cycle(graph, path, curr_ind + 1): return True diff --git a/data_structures/binary_tree/avl_tree.py b/data_structures/binary_tree/avl_tree.py index 2f4bd60d9..320e7ed0d 100644 --- a/data_structures/binary_tree/avl_tree.py +++ b/data_structures/binary_tree/avl_tree.py @@ -33,7 +33,7 @@ class MyQueue: def count(self) -> int: return self.tail - self.head - def print(self) -> None: + def print_queue(self) -> None: print(self.data) print("**************") print(self.data[self.head : self.tail]) diff --git a/data_structures/linked_list/__init__.py b/data_structures/linked_list/__init__.py index 6ba660231..85660a6d2 100644 --- a/data_structures/linked_list/__init__.py +++ b/data_structures/linked_list/__init__.py @@ -11,7 +11,7 @@ from typing import Any class Node: - def __init__(self, item: Any, next: Any) -> None: + def __init__(self, item: Any, next: Any) -> None: # noqa: A002 self.item = item self.next = next diff --git a/data_structures/linked_list/singly_linked_list.py b/data_structures/linked_list/singly_linked_list.py index a4156b650..59d7c512b 100644 --- a/data_structures/linked_list/singly_linked_list.py +++ b/data_structures/linked_list/singly_linked_list.py @@ -392,7 +392,7 @@ def test_singly_linked_list_2() -> None: This section of the test used varying data types for input. >>> test_singly_linked_list_2() """ - input = [ + test_input = [ -9, 100, Node(77345112), @@ -410,7 +410,7 @@ def test_singly_linked_list_2() -> None: ] linked_list = LinkedList() - for i in input: + for i in test_input: linked_list.insert_tail(i) # Check if it's empty or not diff --git a/data_structures/queue/double_ended_queue.py b/data_structures/queue/double_ended_queue.py index f38874788..7053879d4 100644 --- a/data_structures/queue/double_ended_queue.py +++ b/data_structures/queue/double_ended_queue.py @@ -15,8 +15,8 @@ class Deque: ---------- append(val: Any) -> None appendleft(val: Any) -> None - extend(iter: Iterable) -> None - extendleft(iter: Iterable) -> None + extend(iterable: Iterable) -> None + extendleft(iterable: Iterable) -> None pop() -> Any popleft() -> Any Observers @@ -179,9 +179,9 @@ class Deque: # make sure there were no errors assert not self.is_empty(), "Error on appending value." - def extend(self, iter: Iterable[Any]) -> None: + def extend(self, iterable: Iterable[Any]) -> None: """ - Appends every value of iter to the end of the deque. + Appends every value of iterable to the end of the deque. Time complexity: O(n) >>> our_deque_1 = Deque([1, 2, 3]) >>> our_deque_1.extend([4, 5]) @@ -205,12 +205,12 @@ class Deque: >>> list(our_deque_2) == list(deque_collections_2) True """ - for val in iter: + for val in iterable: self.append(val) - def extendleft(self, iter: Iterable[Any]) -> None: + def extendleft(self, iterable: Iterable[Any]) -> None: """ - Appends every value of iter to the beginning of the deque. + Appends every value of iterable to the beginning of the deque. Time complexity: O(n) >>> our_deque_1 = Deque([1, 2, 3]) >>> our_deque_1.extendleft([0, -1]) @@ -234,7 +234,7 @@ class Deque: >>> list(our_deque_2) == list(deque_collections_2) True """ - for val in iter: + for val in iterable: self.appendleft(val) def pop(self) -> Any: diff --git a/data_structures/stacks/next_greater_element.py b/data_structures/stacks/next_greater_element.py index 5bab7c609..7d76d1f47 100644 --- a/data_structures/stacks/next_greater_element.py +++ b/data_structures/stacks/next_greater_element.py @@ -17,12 +17,12 @@ def next_greatest_element_slow(arr: list[float]) -> list[float]: arr_size = len(arr) for i in range(arr_size): - next: float = -1 + next_element: float = -1 for j in range(i + 1, arr_size): if arr[i] < arr[j]: - next = arr[j] + next_element = arr[j] break - result.append(next) + result.append(next_element) return result @@ -36,12 +36,12 @@ def next_greatest_element_fast(arr: list[float]) -> list[float]: """ result = [] for i, outer in enumerate(arr): - next: float = -1 + next_item: float = -1 for inner in arr[i + 1 :]: if outer < inner: - next = inner + next_item = inner break - result.append(next) + result.append(next_item) return result diff --git a/digital_image_processing/index_calculation.py b/digital_image_processing/index_calculation.py index 2f8fdc066..01cd79fc1 100644 --- a/digital_image_processing/index_calculation.py +++ b/digital_image_processing/index_calculation.py @@ -497,9 +497,9 @@ class IndexCalculation: https://www.indexdatabase.de/db/i-single.php?id=77 :return: index """ - max = np.max([np.max(self.red), np.max(self.green), np.max(self.blue)]) - min = np.min([np.min(self.red), np.min(self.green), np.min(self.blue)]) - return (max - min) / max + max_value = np.max([np.max(self.red), np.max(self.green), np.max(self.blue)]) + min_value = np.min([np.min(self.red), np.min(self.green), np.min(self.blue)]) + return (max_value - min_value) / max_value def _if(self): """ diff --git a/dynamic_programming/optimal_binary_search_tree.py b/dynamic_programming/optimal_binary_search_tree.py index 0d94c1b61..b4f1181ac 100644 --- a/dynamic_programming/optimal_binary_search_tree.py +++ b/dynamic_programming/optimal_binary_search_tree.py @@ -104,7 +104,7 @@ def find_optimal_binary_search_tree(nodes): dp = [[freqs[i] if i == j else 0 for j in range(n)] for i in range(n)] # sum[i][j] stores the sum of key frequencies between i and j inclusive in nodes # array - sum = [[freqs[i] if i == j else 0 for j in range(n)] for i in range(n)] + total = [[freqs[i] if i == j else 0 for j in range(n)] for i in range(n)] # stores tree roots that will be used later for constructing binary search tree root = [[i if i == j else 0 for j in range(n)] for i in range(n)] @@ -113,14 +113,14 @@ def find_optimal_binary_search_tree(nodes): j = i + interval_length - 1 dp[i][j] = sys.maxsize # set the value to "infinity" - sum[i][j] = sum[i][j - 1] + freqs[j] + total[i][j] = total[i][j - 1] + freqs[j] # Apply Knuth's optimization # Loop without optimization: for r in range(i, j + 1): for r in range(root[i][j - 1], root[i + 1][j] + 1): # r is a temporal root left = dp[i][r - 1] if r != i else 0 # optimal cost for left subtree right = dp[r + 1][j] if r != j else 0 # optimal cost for right subtree - cost = left + sum[i][j] + right + cost = left + total[i][j] + right if dp[i][j] > cost: dp[i][j] = cost diff --git a/graphs/a_star.py b/graphs/a_star.py index e0f24734a..793ba3bda 100644 --- a/graphs/a_star.py +++ b/graphs/a_star.py @@ -40,10 +40,10 @@ def search( else: # to choose the least costliest action so as to move closer to the goal cell.sort() cell.reverse() - next = cell.pop() - x = next[2] - y = next[3] - g = next[1] + next_cell = cell.pop() + x = next_cell[2] + y = next_cell[3] + g = next_cell[1] if x == goal[0] and y == goal[1]: found = True diff --git a/graphs/dijkstra.py b/graphs/dijkstra.py index 62c60f2c6..b0bdfab60 100644 --- a/graphs/dijkstra.py +++ b/graphs/dijkstra.py @@ -56,8 +56,8 @@ def dijkstra(graph, start, end): for v, c in graph[u]: if v in visited: continue - next = cost + c - heapq.heappush(heap, (next, v)) + next_item = cost + c + heapq.heappush(heap, (next_item, v)) return -1 diff --git a/graphs/finding_bridges.py b/graphs/finding_bridges.py index 3813c4ebb..c17606745 100644 --- a/graphs/finding_bridges.py +++ b/graphs/finding_bridges.py @@ -72,22 +72,22 @@ def compute_bridges(graph: dict[int, list[int]]) -> list[tuple[int, int]]: [] """ - id = 0 + id_ = 0 n = len(graph) # No of vertices in graph low = [0] * n visited = [False] * n - def dfs(at, parent, bridges, id): + def dfs(at, parent, bridges, id_): visited[at] = True - low[at] = id - id += 1 + low[at] = id_ + id_ += 1 for to in graph[at]: if to == parent: pass elif not visited[to]: - dfs(to, at, bridges, id) + dfs(to, at, bridges, id_) low[at] = min(low[at], low[to]) - if id <= low[to]: + if id_ <= low[to]: bridges.append((at, to) if at < to else (to, at)) else: # This edge is a back edge and cannot be a bridge @@ -96,7 +96,7 @@ def compute_bridges(graph: dict[int, list[int]]) -> list[tuple[int, int]]: bridges: list[tuple[int, int]] = [] for i in range(n): if not visited[i]: - dfs(i, -1, bridges, id) + dfs(i, -1, bridges, id_) return bridges diff --git a/graphs/prim.py b/graphs/prim.py index 55d0fbfa8..6cb1a6def 100644 --- a/graphs/prim.py +++ b/graphs/prim.py @@ -13,7 +13,7 @@ from collections.abc import Iterator class Vertex: """Class Vertex.""" - def __init__(self, id): + def __init__(self, id_): """ Arguments: id - input an id to identify the vertex @@ -21,7 +21,7 @@ class Vertex: neighbors - a list of the vertices it is linked to edges - a dict to store the edges's weight """ - self.id = str(id) + self.id = str(id_) self.key = None self.pi = None self.neighbors = [] diff --git a/hashes/djb2.py b/hashes/djb2.py index 2d1c9aabb..4c8463509 100644 --- a/hashes/djb2.py +++ b/hashes/djb2.py @@ -29,7 +29,7 @@ def djb2(s: str) -> int: >>> djb2('scramble bits') 1609059040 """ - hash = 5381 + hash_value = 5381 for x in s: - hash = ((hash << 5) + hash) + ord(x) - return hash & 0xFFFFFFFF + hash_value = ((hash_value << 5) + hash_value) + ord(x) + return hash_value & 0xFFFFFFFF diff --git a/hashes/sdbm.py b/hashes/sdbm.py index daf292717..a5432874b 100644 --- a/hashes/sdbm.py +++ b/hashes/sdbm.py @@ -31,7 +31,9 @@ def sdbm(plain_text: str) -> int: >>> sdbm('scramble bits') 730247649148944819640658295400555317318720608290373040936089 """ - hash = 0 + hash_value = 0 for plain_chr in plain_text: - hash = ord(plain_chr) + (hash << 6) + (hash << 16) - hash - return hash + hash_value = ( + ord(plain_chr) + (hash_value << 6) + (hash_value << 16) - hash_value + ) + return hash_value diff --git a/maths/armstrong_numbers.py b/maths/armstrong_numbers.py index 65aebe937..f62991b74 100644 --- a/maths/armstrong_numbers.py +++ b/maths/armstrong_numbers.py @@ -25,7 +25,7 @@ def armstrong_number(n: int) -> bool: return False # Initialization of sum and number of digits. - sum = 0 + total = 0 number_of_digits = 0 temp = n # Calculation of digits of the number @@ -36,9 +36,9 @@ def armstrong_number(n: int) -> bool: temp = n while temp > 0: rem = temp % 10 - sum += rem**number_of_digits + total += rem**number_of_digits temp //= 10 - return n == sum + return n == total def pluperfect_number(n: int) -> bool: @@ -55,7 +55,7 @@ def pluperfect_number(n: int) -> bool: # Init a "histogram" of the digits digit_histogram = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] digit_total = 0 - sum = 0 + total = 0 temp = n while temp > 0: temp, rem = divmod(temp, 10) @@ -63,9 +63,9 @@ def pluperfect_number(n: int) -> bool: digit_total += 1 for (cnt, i) in zip(digit_histogram, range(len(digit_histogram))): - sum += cnt * i**digit_total + total += cnt * i**digit_total - return n == sum + return n == total def narcissistic_number(n: int) -> bool: diff --git a/maths/bailey_borwein_plouffe.py b/maths/bailey_borwein_plouffe.py index b647ae56d..389b1566e 100644 --- a/maths/bailey_borwein_plouffe.py +++ b/maths/bailey_borwein_plouffe.py @@ -67,7 +67,7 @@ def _subsum( @param precision: same as precision in main function @return: floating-point number whose integer part is not important """ - sum = 0.0 + total = 0.0 for sum_index in range(digit_pos_to_extract + precision): denominator = 8 * sum_index + denominator_addend if sum_index < digit_pos_to_extract: @@ -79,8 +79,8 @@ def _subsum( ) else: exponential_term = pow(16, digit_pos_to_extract - 1 - sum_index) - sum += exponential_term / denominator - return sum + total += exponential_term / denominator + return total if __name__ == "__main__": diff --git a/maths/kadanes.py b/maths/kadanes.py index d239d4a25..b23409e2b 100644 --- a/maths/kadanes.py +++ b/maths/kadanes.py @@ -14,13 +14,13 @@ def negative_exist(arr: list) -> int: [-2, 0, 0, 0, 0] """ arr = arr or [0] - max = arr[0] + max_number = arr[0] for i in arr: if i >= 0: return 0 - elif max <= i: - max = i - return max + elif max_number <= i: + max_number = i + return max_number def kadanes(arr: list) -> int: diff --git a/maths/prime_numbers.py b/maths/prime_numbers.py index 7be4d3d95..4e076fe31 100644 --- a/maths/prime_numbers.py +++ b/maths/prime_numbers.py @@ -2,7 +2,7 @@ import math from collections.abc import Generator -def slow_primes(max: int) -> Generator[int, None, None]: +def slow_primes(max_n: int) -> Generator[int, None, None]: """ Return a list of all primes numbers up to max. >>> list(slow_primes(0)) @@ -20,7 +20,7 @@ def slow_primes(max: int) -> Generator[int, None, None]: >>> list(slow_primes(10000))[-1] 9973 """ - numbers: Generator = (i for i in range(1, (max + 1))) + numbers: Generator = (i for i in range(1, (max_n + 1))) for i in (n for n in numbers if n > 1): for j in range(2, i): if (i % j) == 0: @@ -29,7 +29,7 @@ def slow_primes(max: int) -> Generator[int, None, None]: yield i -def primes(max: int) -> Generator[int, None, None]: +def primes(max_n: int) -> Generator[int, None, None]: """ Return a list of all primes numbers up to max. >>> list(primes(0)) @@ -47,7 +47,7 @@ def primes(max: int) -> Generator[int, None, None]: >>> list(primes(10000))[-1] 9973 """ - numbers: Generator = (i for i in range(1, (max + 1))) + numbers: Generator = (i for i in range(1, (max_n + 1))) for i in (n for n in numbers if n > 1): # only need to check for factors up to sqrt(i) bound = int(math.sqrt(i)) + 1 @@ -58,7 +58,7 @@ def primes(max: int) -> Generator[int, None, None]: yield i -def fast_primes(max: int) -> Generator[int, None, None]: +def fast_primes(max_n: int) -> Generator[int, None, None]: """ Return a list of all primes numbers up to max. >>> list(fast_primes(0)) @@ -76,9 +76,9 @@ def fast_primes(max: int) -> Generator[int, None, None]: >>> list(fast_primes(10000))[-1] 9973 """ - numbers: Generator = (i for i in range(1, (max + 1), 2)) + numbers: Generator = (i for i in range(1, (max_n + 1), 2)) # It's useless to test even numbers as they will not be prime - if max > 2: + if max_n > 2: yield 2 # Because 2 will not be tested, it's necessary to yield it now for i in (n for n in numbers if n > 1): bound = int(math.sqrt(i)) + 1 diff --git a/maths/sum_of_arithmetic_series.py b/maths/sum_of_arithmetic_series.py index e0e22760b..3e381b8c2 100644 --- a/maths/sum_of_arithmetic_series.py +++ b/maths/sum_of_arithmetic_series.py @@ -8,9 +8,9 @@ def sum_of_series(first_term: int, common_diff: int, num_of_terms: int) -> float >>> sum_of_series(1, 10, 100) 49600.0 """ - sum = (num_of_terms / 2) * (2 * first_term + (num_of_terms - 1) * common_diff) + total = (num_of_terms / 2) * (2 * first_term + (num_of_terms - 1) * common_diff) # formula for sum of series - return sum + return total def main(): diff --git a/neural_network/2_hidden_layers_neural_network.py b/neural_network/2_hidden_layers_neural_network.py index 1cf78ec4c..9c5772326 100644 --- a/neural_network/2_hidden_layers_neural_network.py +++ b/neural_network/2_hidden_layers_neural_network.py @@ -182,7 +182,7 @@ class TwoHiddenLayerNeuralNetwork: loss = numpy.mean(numpy.square(output - self.feedforward())) print(f"Iteration {iteration} Loss: {loss}") - def predict(self, input: numpy.ndarray) -> int: + def predict(self, input_arr: numpy.ndarray) -> int: """ Predict's the output for the given input values using the trained neural network. @@ -201,7 +201,7 @@ class TwoHiddenLayerNeuralNetwork: """ # Input values for which the predictions are to be made. - self.array = input + self.array = input_arr self.layer_between_input_and_first_hidden_layer = sigmoid( numpy.dot(self.array, self.input_layer_and_first_hidden_layer_weights) @@ -264,7 +264,7 @@ def example() -> int: True """ # Input values. - input = numpy.array( + test_input = numpy.array( ( [0, 0, 0], [0, 0, 1], @@ -282,7 +282,9 @@ def example() -> int: output = numpy.array(([0], [1], [1], [0], [1], [0], [0], [1]), dtype=numpy.float64) # Calling neural network class. - neural_network = TwoHiddenLayerNeuralNetwork(input_array=input, output_array=output) + neural_network = TwoHiddenLayerNeuralNetwork( + input_array=test_input, output_array=output + ) # Calling training function. # Set give_loss to True if you want to see loss in every iteration. diff --git a/neural_network/convolution_neural_network.py b/neural_network/convolution_neural_network.py index bbade1c41..9dfb6d091 100644 --- a/neural_network/convolution_neural_network.py +++ b/neural_network/convolution_neural_network.py @@ -140,24 +140,24 @@ class CNN: focus_list = np.asarray(focus1_list) return focus_list, data_featuremap - def pooling(self, featuremaps, size_pooling, type="average_pool"): + def pooling(self, featuremaps, size_pooling, pooling_type="average_pool"): # pooling process size_map = len(featuremaps[0]) size_pooled = int(size_map / size_pooling) featuremap_pooled = [] for i_map in range(len(featuremaps)): - map = featuremaps[i_map] + feature_map = featuremaps[i_map] map_pooled = [] for i_focus in range(0, size_map, size_pooling): for j_focus in range(0, size_map, size_pooling): - focus = map[ + focus = feature_map[ i_focus : i_focus + size_pooling, j_focus : j_focus + size_pooling, ] - if type == "average_pool": + if pooling_type == "average_pool": # average pooling map_pooled.append(np.average(focus)) - elif type == "max_pooling": + elif pooling_type == "max_pooling": # max pooling map_pooled.append(np.max(focus)) map_pooled = np.asmatrix(map_pooled).reshape(size_pooled, size_pooled) diff --git a/neural_network/perceptron.py b/neural_network/perceptron.py index 063be5ea5..a2bfdb326 100644 --- a/neural_network/perceptron.py +++ b/neural_network/perceptron.py @@ -182,7 +182,7 @@ samples = [ [0.2012, 0.2611, 5.4631], ] -exit = [ +target = [ -1, -1, -1, @@ -222,7 +222,7 @@ if __name__ == "__main__": doctest.testmod() network = Perceptron( - sample=samples, target=exit, learning_rate=0.01, epoch_number=1000, bias=-1 + sample=samples, target=target, learning_rate=0.01, epoch_number=1000, bias=-1 ) network.training() print("Finished training perceptron") diff --git a/project_euler/problem_065/sol1.py b/project_euler/problem_065/sol1.py index 229769a77..0a00cf477 100644 --- a/project_euler/problem_065/sol1.py +++ b/project_euler/problem_065/sol1.py @@ -71,7 +71,7 @@ def sum_digits(num: int) -> int: return digit_sum -def solution(max: int = 100) -> int: +def solution(max_n: int = 100) -> int: """ Returns the sum of the digits in the numerator of the max-th convergent of the continued fraction for e. @@ -86,7 +86,7 @@ def solution(max: int = 100) -> int: pre_numerator = 1 cur_numerator = 2 - for i in range(2, max + 1): + for i in range(2, max_n + 1): temp = pre_numerator e_cont = 2 * i // 3 if i % 3 == 0 else 1 pre_numerator = cur_numerator diff --git a/project_euler/problem_070/sol1.py b/project_euler/problem_070/sol1.py index d42b017cc..273f37efc 100644 --- a/project_euler/problem_070/sol1.py +++ b/project_euler/problem_070/sol1.py @@ -72,7 +72,7 @@ def has_same_digits(num1: int, num2: int) -> bool: return sorted(str(num1)) == sorted(str(num2)) -def solution(max: int = 10000000) -> int: +def solution(max_n: int = 10000000) -> int: """ Finds the value of n from 1 to max such that n/φ(n) produces a minimum. @@ -85,9 +85,9 @@ def solution(max: int = 10000000) -> int: min_numerator = 1 # i min_denominator = 0 # φ(i) - totients = get_totients(max + 1) + totients = get_totients(max_n + 1) - for i in range(2, max + 1): + for i in range(2, max_n + 1): t = totients[i] if i * min_denominator < min_numerator * t and has_same_digits(i, t): diff --git a/sorts/odd_even_sort.py b/sorts/odd_even_sort.py index 557337ee7..532f82949 100644 --- a/sorts/odd_even_sort.py +++ b/sorts/odd_even_sort.py @@ -20,21 +20,21 @@ def odd_even_sort(input_list: list) -> list: >>> odd_even_sort([1 ,2 ,3 ,4]) [1, 2, 3, 4] """ - sorted = False - while sorted is False: # Until all the indices are traversed keep looping - sorted = True + is_sorted = False + while is_sorted is False: # Until all the indices are traversed keep looping + is_sorted = True for i in range(0, len(input_list) - 1, 2): # iterating over all even indices if input_list[i] > input_list[i + 1]: input_list[i], input_list[i + 1] = input_list[i + 1], input_list[i] # swapping if elements not in order - sorted = False + is_sorted = False for i in range(1, len(input_list) - 1, 2): # iterating over all odd indices if input_list[i] > input_list[i + 1]: input_list[i], input_list[i + 1] = input_list[i + 1], input_list[i] # swapping if elements not in order - sorted = False + is_sorted = False return input_list diff --git a/strings/snake_case_to_camel_pascal_case.py b/strings/snake_case_to_camel_pascal_case.py index 7b2b61d1d..eaabdcb87 100644 --- a/strings/snake_case_to_camel_pascal_case.py +++ b/strings/snake_case_to_camel_pascal_case.py @@ -1,4 +1,4 @@ -def snake_to_camel_case(input: str, use_pascal: bool = False) -> str: +def snake_to_camel_case(input_str: str, use_pascal: bool = False) -> str: """ Transforms a snake_case given string to camelCase (or PascalCase if indicated) (defaults to not use Pascal) @@ -26,14 +26,14 @@ def snake_to_camel_case(input: str, use_pascal: bool = False) -> str: ValueError: Expected boolean as use_pascal parameter, found """ - if not isinstance(input, str): - raise ValueError(f"Expected string as input, found {type(input)}") + if not isinstance(input_str, str): + raise ValueError(f"Expected string as input, found {type(input_str)}") if not isinstance(use_pascal, bool): raise ValueError( f"Expected boolean as use_pascal parameter, found {type(use_pascal)}" ) - words = input.split("_") + words = input_str.split("_") start_index = 0 if use_pascal else 1 From f176786d12ead5796644a9b37d96786cdaa55391 Mon Sep 17 00:00:00 2001 From: Praveen Date: Thu, 13 Oct 2022 21:04:52 +0530 Subject: [PATCH 358/726] Update open_google_results.py (#7085) * update crawl_google_results.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update and rename crawl_google_results.py to open_google_results.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Create crawl_google_results.py * Update web_programming/open_google_results.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update open_google_results.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- web_programming/open_google_results.py | 42 ++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 web_programming/open_google_results.py diff --git a/web_programming/open_google_results.py b/web_programming/open_google_results.py new file mode 100644 index 000000000..0e1dba8c5 --- /dev/null +++ b/web_programming/open_google_results.py @@ -0,0 +1,42 @@ +import webbrowser +from sys import argv +from urllib.parse import quote, parse_qs +from fake_useragent import UserAgent + +import requests +from bs4 import BeautifulSoup + +if __name__ == "__main__": + if len(argv) > 1: + query = "%20".join(argv[1:]) + else: + query = quote(str(input("Search: "))) + + print("Googling.....") + + url = f"https://www.google.com/search?q={query}&num=100" + + res = requests.get( + url, + headers={ + "User-Agent": str(UserAgent().random) + }, + ) + + try: + link = ( + BeautifulSoup(res.text, "html.parser") + .find("div", attrs={"class": "yuRUbf"}) + .find("a") + .get("href") + ) + + except AttributeError: + link = parse_qs( + BeautifulSoup(res.text, "html.parser") + .find("div", attrs={"class": "kCrYT"}) + .find("a") + .get("href") + )["url"][0] + + webbrowser.open(link) From 4d0c830d2c7a4a535501887a8eb97966a370ef57 Mon Sep 17 00:00:00 2001 From: Caeden Date: Thu, 13 Oct 2022 17:03:06 +0100 Subject: [PATCH 359/726] Add flake8 pluin flake8 bugbear to pre-commit (#7132) * ci(pre-commit): Add ``flake8-builtins`` additional dependency to ``pre-commit`` (#7104) * refactor: Fix ``flake8-builtins`` (#7104) * fix(lru_cache): Fix naming conventions in docstrings (#7104) * ci(pre-commit): Order additional dependencies alphabetically (#7104) * fix(lfu_cache): Correct function name in docstring (#7104) * Update strings/snake_case_to_camel_pascal_case.py Co-authored-by: Christian Clauss * Update data_structures/stacks/next_greater_element.py Co-authored-by: Christian Clauss * Update digital_image_processing/index_calculation.py Co-authored-by: Christian Clauss * Update graphs/prim.py Co-authored-by: Christian Clauss * Update hashes/djb2.py Co-authored-by: Christian Clauss * refactor: Rename `_builtin` to `builtin_` ( #7104) * fix: Rename all instances (#7104) * refactor: Update variable names (#7104) * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * ci: Create ``tox.ini`` and ignore ``A003`` (#7123) * revert: Remove function name changes (#7104) * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Rename tox.ini to .flake8 * Update data_structures/heap/heap.py Co-authored-by: Dhruv Manilawala * refactor: Rename `next_` to `next_item` (#7104) * ci(pre-commit): Add `flake8` plugin `flake8-bugbear` (#7127) * refactor: Follow `flake8-bugbear` plugin (#7127) * fix: Correct `knapsack` code (#7127) * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: Christian Clauss Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Dhruv Manilawala --- .pre-commit-config.yaml | 5 +++- .../jacobi_iteration_method.py | 2 +- .../newton_forward_interpolation.py | 2 +- arithmetic_analysis/secant_method.py | 2 +- audio_filters/butterworth_filter.py | 23 +++++++++++++------ backtracking/sum_of_subsets.py | 8 +++---- boolean_algebra/quine_mc_cluskey.py | 2 +- ciphers/mixed_keyword_cypher.py | 2 +- ciphers/rabin_miller.py | 2 +- compression/burrows_wheeler.py | 2 +- .../binary_search_tree_recursive.py | 8 +++---- .../linked_list/circular_linked_list.py | 8 +++---- .../linked_list/doubly_linked_list.py | 8 +++---- .../middle_element_of_linked_list.py | 2 +- .../linked_list/singly_linked_list.py | 6 ++--- data_structures/linked_list/skip_list.py | 4 ++-- data_structures/queue/queue_on_list.py | 2 +- .../queue/queue_on_pseudo_stack.py | 2 +- data_structures/stacks/stack.py | 6 ++--- divide_and_conquer/convex_hull.py | 8 +++---- .../strassen_matrix_multiplication.py | 6 ++--- dynamic_programming/all_construct.py | 2 +- dynamic_programming/knapsack.py | 10 ++++---- fractals/julia_sets.py | 2 +- fractals/koch_snowflake.py | 2 +- fractals/mandelbrot.py | 2 +- genetic_algorithm/basic_string.py | 7 ++++-- graphs/basic_graphs.py | 4 ++-- graphs/bellman_ford.py | 2 +- graphs/dijkstra_2.py | 18 +++++++-------- graphs/frequent_pattern_graph_miner.py | 2 +- graphs/kahns_algorithm_long.py | 2 +- graphs/kahns_algorithm_topo.py | 2 +- graphs/minimum_spanning_tree_prims.py | 2 +- graphs/page_rank.py | 2 +- graphs/scc_kosaraju.py | 4 ++-- greedy_methods/optimal_merge_pattern.py | 2 +- hashes/chaos_machine.py | 2 +- hashes/enigma_machine.py | 2 +- machine_learning/self_organizing_map.py | 2 +- maths/area_under_curve.py | 2 +- maths/line_length.py | 2 +- maths/lucas_lehmer_primality_test.py | 2 +- maths/lucas_series.py | 2 +- maths/miller_rabin.py | 2 +- maths/monte_carlo_dice.py | 2 +- maths/numerical_integration.py | 2 +- maths/pi_monte_carlo_estimation.py | 2 +- maths/pollard_rho.py | 2 +- maths/primelib.py | 8 +++---- maths/proth_number.py | 2 +- maths/square_root.py | 2 +- maths/ugly_numbers.py | 2 +- matrix/matrix_class.py | 2 +- ...h_fibonacci_using_matrix_exponentiation.py | 2 +- .../back_propagation_neural_network.py | 2 +- neural_network/perceptron.py | 2 +- other/lfu_cache.py | 2 +- other/lru_cache.py | 2 +- other/magicdiamondpattern.py | 8 +++---- other/scoring_algorithm.py | 2 +- physics/lorentz_transformation_four_vector.py | 2 +- physics/n_body_simulation.py | 2 +- project_euler/problem_011/sol2.py | 2 +- project_euler/problem_025/sol3.py | 2 +- project_euler/problem_026/sol1.py | 2 +- project_euler/problem_188/sol1.py | 2 +- project_euler/problem_203/sol1.py | 2 +- scheduling/multi_level_feedback_queue.py | 2 +- sorts/double_sort.py | 2 +- web_programming/open_google_results.py | 8 +++---- 71 files changed, 137 insertions(+), 124 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e0de70b01..d2558b90a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,7 +40,10 @@ repos: - --ignore=E203,W503 - --max-complexity=25 - --max-line-length=88 - additional_dependencies: [flake8-builtins, pep8-naming] + additional_dependencies: + - flake8-bugbear + - flake8-builtins + - pep8-naming - repo: https://github.com/pre-commit/mirrors-mypy rev: v0.982 diff --git a/arithmetic_analysis/jacobi_iteration_method.py b/arithmetic_analysis/jacobi_iteration_method.py index 0aab4db20..3087309e8 100644 --- a/arithmetic_analysis/jacobi_iteration_method.py +++ b/arithmetic_analysis/jacobi_iteration_method.py @@ -110,7 +110,7 @@ def jacobi_iteration_method( strictly_diagonally_dominant(table) # Iterates the whole matrix for given number of times - for i in range(iterations): + for _ in range(iterations): new_val = [] for row in range(rows): temp = 0 diff --git a/arithmetic_analysis/newton_forward_interpolation.py b/arithmetic_analysis/newton_forward_interpolation.py index 490e0687f..466f6c18c 100644 --- a/arithmetic_analysis/newton_forward_interpolation.py +++ b/arithmetic_analysis/newton_forward_interpolation.py @@ -23,7 +23,7 @@ def ucal(u: float, p: int) -> float: def main() -> None: n = int(input("enter the numbers of values: ")) y: list[list[float]] = [] - for i in range(n): + for _ in range(n): y.append([]) for i in range(n): for j in range(n): diff --git a/arithmetic_analysis/secant_method.py b/arithmetic_analysis/secant_method.py index 45bcb185f..d28a46206 100644 --- a/arithmetic_analysis/secant_method.py +++ b/arithmetic_analysis/secant_method.py @@ -20,7 +20,7 @@ def secant_method(lower_bound: float, upper_bound: float, repeats: int) -> float """ x0 = lower_bound x1 = upper_bound - for i in range(0, repeats): + for _ in range(0, repeats): x0, x1 = x1, x1 - (f(x1) * (x1 - x0)) / (f(x1) - f(x0)) return x1 diff --git a/audio_filters/butterworth_filter.py b/audio_filters/butterworth_filter.py index 409cfeb1d..cffedb7a6 100644 --- a/audio_filters/butterworth_filter.py +++ b/audio_filters/butterworth_filter.py @@ -11,7 +11,7 @@ Alternatively you can use scipy.signal.butter, which should yield the same resul def make_lowpass( - frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2) + frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2) # noqa: B008 ) -> IIRFilter: """ Creates a low-pass filter @@ -39,7 +39,7 @@ def make_lowpass( def make_highpass( - frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2) + frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2) # noqa: B008 ) -> IIRFilter: """ Creates a high-pass filter @@ -67,7 +67,7 @@ def make_highpass( def make_bandpass( - frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2) + frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2) # noqa: B008 ) -> IIRFilter: """ Creates a band-pass filter @@ -96,7 +96,7 @@ def make_bandpass( def make_allpass( - frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2) + frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2) # noqa: B008 ) -> IIRFilter: """ Creates an all-pass filter @@ -121,7 +121,10 @@ def make_allpass( def make_peak( - frequency: int, samplerate: int, gain_db: float, q_factor: float = 1 / sqrt(2) + frequency: int, + samplerate: int, + gain_db: float, + q_factor: float = 1 / sqrt(2), # noqa: B008 ) -> IIRFilter: """ Creates a peak filter @@ -150,7 +153,10 @@ def make_peak( def make_lowshelf( - frequency: int, samplerate: int, gain_db: float, q_factor: float = 1 / sqrt(2) + frequency: int, + samplerate: int, + gain_db: float, + q_factor: float = 1 / sqrt(2), # noqa: B008 ) -> IIRFilter: """ Creates a low-shelf filter @@ -184,7 +190,10 @@ def make_lowshelf( def make_highshelf( - frequency: int, samplerate: int, gain_db: float, q_factor: float = 1 / sqrt(2) + frequency: int, + samplerate: int, + gain_db: float, + q_factor: float = 1 / sqrt(2), # noqa: B008 ) -> IIRFilter: """ Creates a high-shelf filter diff --git a/backtracking/sum_of_subsets.py b/backtracking/sum_of_subsets.py index 8348544c0..128e29071 100644 --- a/backtracking/sum_of_subsets.py +++ b/backtracking/sum_of_subsets.py @@ -39,14 +39,14 @@ def create_state_space_tree( if sum(path) == max_sum: result.append(path) return - for num_index in range(num_index, len(nums)): + for index in range(num_index, len(nums)): create_state_space_tree( nums, max_sum, - num_index + 1, - path + [nums[num_index]], + index + 1, + path + [nums[index]], result, - remaining_nums_sum - nums[num_index], + remaining_nums_sum - nums[index], ) diff --git a/boolean_algebra/quine_mc_cluskey.py b/boolean_algebra/quine_mc_cluskey.py index 9aa9b10c8..5bd7117bb 100644 --- a/boolean_algebra/quine_mc_cluskey.py +++ b/boolean_algebra/quine_mc_cluskey.py @@ -56,7 +56,7 @@ def decimal_to_binary(no_of_variable: int, minterms: Sequence[float]) -> list[st temp = [] for minterm in minterms: string = "" - for i in range(no_of_variable): + for _ in range(no_of_variable): string = str(minterm % 2) + string minterm //= 2 temp.append(string) diff --git a/ciphers/mixed_keyword_cypher.py b/ciphers/mixed_keyword_cypher.py index 178902173..f55c9c428 100644 --- a/ciphers/mixed_keyword_cypher.py +++ b/ciphers/mixed_keyword_cypher.py @@ -40,7 +40,7 @@ def mixed_keyword(key: str = "college", pt: str = "UNIVERSITY") -> str: k = 0 for _ in range(r): s = [] - for j in range(len_temp): + for _ in range(len_temp): s.append(temp[k]) if not (k < 25): break diff --git a/ciphers/rabin_miller.py b/ciphers/rabin_miller.py index 0aab80eb9..410d559d4 100644 --- a/ciphers/rabin_miller.py +++ b/ciphers/rabin_miller.py @@ -11,7 +11,7 @@ def rabin_miller(num: int) -> bool: s = s // 2 t += 1 - for trials in range(5): + for _ in range(5): a = random.randrange(2, num - 1) v = pow(a, s, num) if v != 1: diff --git a/compression/burrows_wheeler.py b/compression/burrows_wheeler.py index 4ad99a642..0916b8a65 100644 --- a/compression/burrows_wheeler.py +++ b/compression/burrows_wheeler.py @@ -154,7 +154,7 @@ def reverse_bwt(bwt_string: str, idx_original_string: int) -> str: ) ordered_rotations = [""] * len(bwt_string) - for x in range(len(bwt_string)): + for _ in range(len(bwt_string)): for i in range(len(bwt_string)): ordered_rotations[i] = bwt_string[i] + ordered_rotations[i] ordered_rotations.sort() diff --git a/data_structures/binary_tree/binary_search_tree_recursive.py b/data_structures/binary_tree/binary_search_tree_recursive.py index 0d0ac8fd1..97eb8e25b 100644 --- a/data_structures/binary_tree/binary_search_tree_recursive.py +++ b/data_structures/binary_tree/binary_search_tree_recursive.py @@ -357,7 +357,7 @@ class BinarySearchTreeTest(unittest.TestCase): assert t.root.left.left.parent == t.root.left assert t.root.left.left.label == 1 - with self.assertRaises(Exception): + with self.assertRaises(Exception): # noqa: B017 t.put(1) def test_search(self) -> None: @@ -369,7 +369,7 @@ class BinarySearchTreeTest(unittest.TestCase): node = t.search(13) assert node.label == 13 - with self.assertRaises(Exception): + with self.assertRaises(Exception): # noqa: B017 t.search(2) def test_remove(self) -> None: @@ -515,7 +515,7 @@ class BinarySearchTreeTest(unittest.TestCase): assert t.get_max_label() == 14 t.empty() - with self.assertRaises(Exception): + with self.assertRaises(Exception): # noqa: B017 t.get_max_label() def test_get_min_label(self) -> None: @@ -524,7 +524,7 @@ class BinarySearchTreeTest(unittest.TestCase): assert t.get_min_label() == 1 t.empty() - with self.assertRaises(Exception): + with self.assertRaises(Exception): # noqa: B017 t.get_min_label() def test_inorder_traversal(self) -> None: diff --git a/data_structures/linked_list/circular_linked_list.py b/data_structures/linked_list/circular_linked_list.py index 6fec0a125..67a63cd55 100644 --- a/data_structures/linked_list/circular_linked_list.py +++ b/data_structures/linked_list/circular_linked_list.py @@ -94,25 +94,25 @@ def test_circular_linked_list() -> None: try: circular_linked_list.delete_front() - assert False # This should not happen + raise AssertionError() # This should not happen except IndexError: assert True # This should happen try: circular_linked_list.delete_tail() - assert False # This should not happen + raise AssertionError() # This should not happen except IndexError: assert True # This should happen try: circular_linked_list.delete_nth(-1) - assert False + raise AssertionError() except IndexError: assert True try: circular_linked_list.delete_nth(0) - assert False + raise AssertionError() except IndexError: assert True diff --git a/data_structures/linked_list/doubly_linked_list.py b/data_structures/linked_list/doubly_linked_list.py index 0eb3cf101..9e996ef0f 100644 --- a/data_structures/linked_list/doubly_linked_list.py +++ b/data_structures/linked_list/doubly_linked_list.py @@ -96,7 +96,7 @@ class DoublyLinkedList: self.tail = new_node else: temp = self.head - for i in range(0, index): + for _ in range(0, index): temp = temp.next temp.previous.next = new_node new_node.previous = temp.previous @@ -145,7 +145,7 @@ class DoublyLinkedList: self.tail.next = None else: temp = self.head - for i in range(0, index): + for _ in range(0, index): temp = temp.next delete_node = temp temp.next.previous = temp.previous @@ -194,13 +194,13 @@ def test_doubly_linked_list() -> None: try: linked_list.delete_head() - assert False # This should not happen. + raise AssertionError() # This should not happen. except IndexError: assert True # This should happen. try: linked_list.delete_tail() - assert False # This should not happen. + raise AssertionError() # This should not happen. except IndexError: assert True # This should happen. diff --git a/data_structures/linked_list/middle_element_of_linked_list.py b/data_structures/linked_list/middle_element_of_linked_list.py index 0c6250f3b..86dad6b41 100644 --- a/data_structures/linked_list/middle_element_of_linked_list.py +++ b/data_structures/linked_list/middle_element_of_linked_list.py @@ -62,7 +62,7 @@ class LinkedList: if __name__ == "__main__": link = LinkedList() - for i in range(int(input().strip())): + for _ in range(int(input().strip())): data = int(input().strip()) link.push(data) print(link.middle_element()) diff --git a/data_structures/linked_list/singly_linked_list.py b/data_structures/linked_list/singly_linked_list.py index 59d7c512b..89a05ae81 100644 --- a/data_structures/linked_list/singly_linked_list.py +++ b/data_structures/linked_list/singly_linked_list.py @@ -132,7 +132,7 @@ class LinkedList: if not 0 <= index < len(self): raise ValueError("list index out of range.") current = self.head - for i in range(index): + for _ in range(index): current = current.next current.data = data @@ -352,13 +352,13 @@ def test_singly_linked_list() -> None: try: linked_list.delete_head() - assert False # This should not happen. + raise AssertionError() # This should not happen. except IndexError: assert True # This should happen. try: linked_list.delete_tail() - assert False # This should not happen. + raise AssertionError() # This should not happen. except IndexError: assert True # This should happen. diff --git a/data_structures/linked_list/skip_list.py b/data_structures/linked_list/skip_list.py index 176049120..a667e3e9b 100644 --- a/data_structures/linked_list/skip_list.py +++ b/data_structures/linked_list/skip_list.py @@ -205,7 +205,7 @@ class SkipList(Generic[KT, VT]): if level > self.level: # After level increase we have to add additional nodes to head. - for i in range(self.level - 1, level): + for _ in range(self.level - 1, level): update_vector.append(self.head) self.level = level @@ -407,7 +407,7 @@ def test_iter_always_yields_sorted_values(): def pytests(): - for i in range(100): + for _ in range(100): # Repeat test 100 times due to the probabilistic nature of skip list # random values == random bugs test_insert() diff --git a/data_structures/queue/queue_on_list.py b/data_structures/queue/queue_on_list.py index 485cf0b6f..71fca6b2f 100644 --- a/data_structures/queue/queue_on_list.py +++ b/data_structures/queue/queue_on_list.py @@ -37,7 +37,7 @@ class Queue: number of times to rotate queue""" def rotate(self, rotation): - for i in range(rotation): + for _ in range(rotation): self.put(self.get()) """Enqueues {@code item} diff --git a/data_structures/queue/queue_on_pseudo_stack.py b/data_structures/queue/queue_on_pseudo_stack.py index 9a0c16f61..d98451000 100644 --- a/data_structures/queue/queue_on_pseudo_stack.py +++ b/data_structures/queue/queue_on_pseudo_stack.py @@ -37,7 +37,7 @@ class Queue: number of times to rotate queue""" def rotate(self, rotation: int) -> None: - for i in range(rotation): + for _ in range(rotation): temp = self.stack[0] self.stack = self.stack[1:] self.put(temp) diff --git a/data_structures/stacks/stack.py b/data_structures/stacks/stack.py index d1c73df43..55d424d50 100644 --- a/data_structures/stacks/stack.py +++ b/data_structures/stacks/stack.py @@ -92,13 +92,13 @@ def test_stack() -> None: try: _ = stack.pop() - assert False # This should not happen + raise AssertionError() # This should not happen except StackUnderflowError: assert True # This should happen try: _ = stack.peek() - assert False # This should not happen + raise AssertionError() # This should not happen except StackUnderflowError: assert True # This should happen @@ -118,7 +118,7 @@ def test_stack() -> None: try: stack.push(200) - assert False # This should not happen + raise AssertionError() # This should not happen except StackOverflowError: assert True # This should happen diff --git a/divide_and_conquer/convex_hull.py b/divide_and_conquer/convex_hull.py index 72da11639..39e78be04 100644 --- a/divide_and_conquer/convex_hull.py +++ b/divide_and_conquer/convex_hull.py @@ -458,16 +458,16 @@ def convex_hull_melkman(points: list[Point]) -> list[Point]: convex_hull[1] = points[i] i += 1 - for i in range(i, n): + for j in range(i, n): if ( - _det(convex_hull[0], convex_hull[-1], points[i]) > 0 + _det(convex_hull[0], convex_hull[-1], points[j]) > 0 and _det(convex_hull[-1], convex_hull[0], points[1]) < 0 ): # The point lies within the convex hull continue - convex_hull.insert(0, points[i]) - convex_hull.append(points[i]) + convex_hull.insert(0, points[j]) + convex_hull.append(points[j]) while _det(convex_hull[0], convex_hull[1], convex_hull[2]) >= 0: del convex_hull[1] while _det(convex_hull[-1], convex_hull[-2], convex_hull[-3]) <= 0: diff --git a/divide_and_conquer/strassen_matrix_multiplication.py b/divide_and_conquer/strassen_matrix_multiplication.py index 17efcfc7c..0ee426e4b 100644 --- a/divide_and_conquer/strassen_matrix_multiplication.py +++ b/divide_and_conquer/strassen_matrix_multiplication.py @@ -132,12 +132,12 @@ def strassen(matrix1: list, matrix2: list) -> list: # power of 2 for i in range(0, maxim): if i < dimension1[0]: - for j in range(dimension1[1], maxim): + for _ in range(dimension1[1], maxim): new_matrix1[i].append(0) else: new_matrix1.append([0] * maxim) if i < dimension2[0]: - for j in range(dimension2[1], maxim): + for _ in range(dimension2[1], maxim): new_matrix2[i].append(0) else: new_matrix2.append([0] * maxim) @@ -147,7 +147,7 @@ def strassen(matrix1: list, matrix2: list) -> list: # Removing the additional zeros for i in range(0, maxim): if i < dimension1[0]: - for j in range(dimension2[1], maxim): + for _ in range(dimension2[1], maxim): final_matrix[i].pop() else: final_matrix.pop() diff --git a/dynamic_programming/all_construct.py b/dynamic_programming/all_construct.py index 5ffed2caa..3839d01e6 100644 --- a/dynamic_programming/all_construct.py +++ b/dynamic_programming/all_construct.py @@ -21,7 +21,7 @@ def all_construct(target: str, word_bank: list[str] | None = None) -> list[list[ table_size: int = len(target) + 1 table: list[list[list[str]]] = [] - for i in range(table_size): + for _ in range(table_size): table.append([]) # seed value table[0] = [[]] # because empty string has empty combination diff --git a/dynamic_programming/knapsack.py b/dynamic_programming/knapsack.py index 9efb60bab..093e15f49 100644 --- a/dynamic_programming/knapsack.py +++ b/dynamic_programming/knapsack.py @@ -30,13 +30,13 @@ def knapsack(w, wt, val, n): dp = [[0 for i in range(w + 1)] for j in range(n + 1)] for i in range(1, n + 1): - for w in range(1, w + 1): - if wt[i - 1] <= w: - dp[i][w] = max(val[i - 1] + dp[i - 1][w - wt[i - 1]], dp[i - 1][w]) + for w_ in range(1, w + 1): + if wt[i - 1] <= w_: + dp[i][w_] = max(val[i - 1] + dp[i - 1][w_ - wt[i - 1]], dp[i - 1][w_]) else: - dp[i][w] = dp[i - 1][w] + dp[i][w_] = dp[i - 1][w_] - return dp[n][w], dp + return dp[n][w_], dp def knapsack_with_example_solution(w: int, wt: list, val: list): diff --git a/fractals/julia_sets.py b/fractals/julia_sets.py index f27394385..28c675c75 100644 --- a/fractals/julia_sets.py +++ b/fractals/julia_sets.py @@ -118,7 +118,7 @@ def iterate_function( """ z_n = z_0.astype("complex64") - for i in range(nb_iterations): + for _ in range(nb_iterations): z_n = eval_function(function_params, z_n) if infinity is not None: numpy.nan_to_num(z_n, copy=False, nan=infinity) diff --git a/fractals/koch_snowflake.py b/fractals/koch_snowflake.py index 07c1835b4..b0aaa86b1 100644 --- a/fractals/koch_snowflake.py +++ b/fractals/koch_snowflake.py @@ -46,7 +46,7 @@ def iterate(initial_vectors: list[numpy.ndarray], steps: int) -> list[numpy.ndar 0.28867513]), array([0.66666667, 0. ]), array([1, 0])] """ vectors = initial_vectors - for i in range(steps): + for _ in range(steps): vectors = iteration_step(vectors) return vectors diff --git a/fractals/mandelbrot.py b/fractals/mandelbrot.py index 5d61b72e1..f97bcd170 100644 --- a/fractals/mandelbrot.py +++ b/fractals/mandelbrot.py @@ -36,7 +36,7 @@ def get_distance(x: float, y: float, max_step: int) -> float: """ a = x b = y - for step in range(max_step): + for step in range(max_step): # noqa: B007 a_new = a * a - b * b + x b = 2 * a * b + y a = a_new diff --git a/genetic_algorithm/basic_string.py b/genetic_algorithm/basic_string.py index 97dbe182b..bd7d80268 100644 --- a/genetic_algorithm/basic_string.py +++ b/genetic_algorithm/basic_string.py @@ -80,7 +80,7 @@ def basic(target: str, genes: list[str], debug: bool = True) -> tuple[int, int, score = len( [g for position, g in enumerate(item) if g == main_target[position]] ) - return (item, float(score)) + return (item, float(score)) # noqa: B023 # Adding a bit of concurrency can make everything faster, # @@ -129,7 +129,10 @@ def basic(target: str, genes: list[str], debug: bool = True) -> tuple[int, int, child_n = int(parent_1[1] * 100) + 1 child_n = 10 if child_n >= 10 else child_n for _ in range(child_n): - parent_2 = population_score[random.randint(0, N_SELECTED)][0] + parent_2 = population_score[ # noqa: B023 + random.randint(0, N_SELECTED) + ][0] + child_1, child_2 = crossover(parent_1[0], parent_2) # Append new string to the population list pop.append(mutate(child_1)) diff --git a/graphs/basic_graphs.py b/graphs/basic_graphs.py index b02e9af65..298a97bf0 100644 --- a/graphs/basic_graphs.py +++ b/graphs/basic_graphs.py @@ -188,7 +188,7 @@ def topo(g, ind=None, q=None): def adjm(): n = input().strip() a = [] - for i in range(n): + for _ in range(n): a.append(map(int, input().strip().split())) return a, n @@ -264,7 +264,7 @@ def prim(g, s): def edglist(): n, m = map(int, input().split(" ")) edges = [] - for i in range(m): + for _ in range(m): edges.append(map(int, input().split(" "))) return edges, n diff --git a/graphs/bellman_ford.py b/graphs/bellman_ford.py index 0f654a510..eb2cd25bf 100644 --- a/graphs/bellman_ford.py +++ b/graphs/bellman_ford.py @@ -36,7 +36,7 @@ def bellman_ford( distance = [float("inf")] * vertex_count distance[src] = 0.0 - for i in range(vertex_count - 1): + for _ in range(vertex_count - 1): for j in range(edge_count): u, v, w = (graph[j][k] for k in ["src", "dst", "weight"]) diff --git a/graphs/dijkstra_2.py b/graphs/dijkstra_2.py index 3170765bc..f548463ff 100644 --- a/graphs/dijkstra_2.py +++ b/graphs/dijkstra_2.py @@ -19,23 +19,23 @@ def min_dist(mdist, vset, v): def dijkstra(graph, v, src): - mdist = [float("inf") for i in range(v)] - vset = [False for i in range(v)] + mdist = [float("inf") for _ in range(v)] + vset = [False for _ in range(v)] mdist[src] = 0.0 - for i in range(v - 1): + for _ in range(v - 1): u = min_dist(mdist, vset, v) vset[u] = True - for v in range(v): + for i in range(v): if ( - (not vset[v]) - and graph[u][v] != float("inf") - and mdist[u] + graph[u][v] < mdist[v] + (not vset[i]) + and graph[u][i] != float("inf") + and mdist[u] + graph[u][i] < mdist[i] ): - mdist[v] = mdist[u] + graph[u][v] + mdist[i] = mdist[u] + graph[u][i] - print_dist(mdist, v) + print_dist(mdist, i) if __name__ == "__main__": diff --git a/graphs/frequent_pattern_graph_miner.py b/graphs/frequent_pattern_graph_miner.py index 50081afa6..a5ecbe6e8 100644 --- a/graphs/frequent_pattern_graph_miner.py +++ b/graphs/frequent_pattern_graph_miner.py @@ -79,7 +79,7 @@ def get_nodes(frequency_table): {'11111': ['ab', 'ac', 'df', 'bd', 'bc']} """ nodes = {} - for i, item in enumerate(frequency_table): + for _, item in enumerate(frequency_table): nodes.setdefault(item[2], []).append(item[0]) return nodes diff --git a/graphs/kahns_algorithm_long.py b/graphs/kahns_algorithm_long.py index 776ae3a2f..63cbeb909 100644 --- a/graphs/kahns_algorithm_long.py +++ b/graphs/kahns_algorithm_long.py @@ -4,7 +4,7 @@ def longest_distance(graph): queue = [] long_dist = [1] * len(graph) - for key, values in graph.items(): + for values in graph.values(): for i in values: indegree[i] += 1 diff --git a/graphs/kahns_algorithm_topo.py b/graphs/kahns_algorithm_topo.py index 6879b047f..b1260bd5b 100644 --- a/graphs/kahns_algorithm_topo.py +++ b/graphs/kahns_algorithm_topo.py @@ -8,7 +8,7 @@ def topological_sort(graph): topo = [] cnt = 0 - for key, values in graph.items(): + for values in graph.values(): for i in values: indegree[i] += 1 diff --git a/graphs/minimum_spanning_tree_prims.py b/graphs/minimum_spanning_tree_prims.py index 9b2c645f1..5b2eaa4bf 100644 --- a/graphs/minimum_spanning_tree_prims.py +++ b/graphs/minimum_spanning_tree_prims.py @@ -91,7 +91,7 @@ def prisms_algorithm(l): # noqa: E741 distance_tv[x[0]] = x[1] heapify(distance_tv, positions) - for i in range(1, len(l)): + for _ in range(1, len(l)): vertex = delete_minimum(distance_tv, positions) if visited[vertex] == 0: tree_edges.append((nbr_tv[vertex], vertex)) diff --git a/graphs/page_rank.py b/graphs/page_rank.py index 672405b73..e1af35b34 100644 --- a/graphs/page_rank.py +++ b/graphs/page_rank.py @@ -41,7 +41,7 @@ def page_rank(nodes, limit=3, d=0.85): for i in range(limit): print(f"======= Iteration {i + 1} =======") - for j, node in enumerate(nodes): + for _, node in enumerate(nodes): ranks[node.name] = (1 - d) + d * sum( ranks[ib] / outbounds[ib] for ib in node.inbound ) diff --git a/graphs/scc_kosaraju.py b/graphs/scc_kosaraju.py index ea9d35282..39211c64b 100644 --- a/graphs/scc_kosaraju.py +++ b/graphs/scc_kosaraju.py @@ -39,10 +39,10 @@ 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 + graph: list[list[int]] = [[] for _ in range(n)] # graph reversed_graph: list[list[int]] = [[] for i in range(n)] # reversed graph # input graph data (edges) - for i in range(m): + for _ in range(m): u, v = list(map(int, input().strip().split())) graph[u].append(v) reversed_graph[v].append(u) diff --git a/greedy_methods/optimal_merge_pattern.py b/greedy_methods/optimal_merge_pattern.py index 911e1966f..a1c934f84 100644 --- a/greedy_methods/optimal_merge_pattern.py +++ b/greedy_methods/optimal_merge_pattern.py @@ -41,7 +41,7 @@ def optimal_merge_pattern(files: list) -> float: while len(files) > 1: temp = 0 # Consider two files with minimum cost to be merged - for i in range(2): + for _ in range(2): min_index = files.index(min(files)) temp += files[min_index] files.pop(min_index) diff --git a/hashes/chaos_machine.py b/hashes/chaos_machine.py index 69313fbb2..238fdb1c0 100644 --- a/hashes/chaos_machine.py +++ b/hashes/chaos_machine.py @@ -53,7 +53,7 @@ def pull(): key = machine_time % m # Evolution (Time Length) - for i in range(0, t): + for _ in range(0, t): # Variables (Position + Parameters) r = params_space[key] value = buffer_space[key] diff --git a/hashes/enigma_machine.py b/hashes/enigma_machine.py index b0d45718e..0194f7da7 100644 --- a/hashes/enigma_machine.py +++ b/hashes/enigma_machine.py @@ -48,7 +48,7 @@ if __name__ == "__main__": break except Exception as error: print(error) - for i in range(token): + for _ in range(token): rotator() for j in decode: engine(j) diff --git a/machine_learning/self_organizing_map.py b/machine_learning/self_organizing_map.py index bd3d388f9..057c2a76b 100644 --- a/machine_learning/self_organizing_map.py +++ b/machine_learning/self_organizing_map.py @@ -47,7 +47,7 @@ def main() -> None: epochs = 3 alpha = 0.5 - for i in range(epochs): + for _ in range(epochs): for j in range(len(training_samples)): # training sample diff --git a/maths/area_under_curve.py b/maths/area_under_curve.py index d345398b4..b557b2029 100644 --- a/maths/area_under_curve.py +++ b/maths/area_under_curve.py @@ -35,7 +35,7 @@ def trapezoidal_area( x1 = x_start fx1 = fnc(x_start) area = 0.0 - for i in range(steps): + for _ in range(steps): # Approximates small segments of curve as linear and solve # for trapezoidal area x2 = (x_end - x_start) / steps + x1 diff --git a/maths/line_length.py b/maths/line_length.py index ad12a816b..ea27ee904 100644 --- a/maths/line_length.py +++ b/maths/line_length.py @@ -40,7 +40,7 @@ def line_length( fx1 = fnc(x_start) length = 0.0 - for i in range(steps): + for _ in range(steps): # Approximates curve as a sequence of linear lines and sums their length x2 = (x_end - x_start) / steps + x1 diff --git a/maths/lucas_lehmer_primality_test.py b/maths/lucas_lehmer_primality_test.py index 916abfcc1..0a5621aac 100644 --- a/maths/lucas_lehmer_primality_test.py +++ b/maths/lucas_lehmer_primality_test.py @@ -31,7 +31,7 @@ def lucas_lehmer_test(p: int) -> bool: s = 4 m = (1 << p) - 1 - for i in range(p - 2): + for _ in range(p - 2): s = ((s * s) - 2) % m return s == 0 diff --git a/maths/lucas_series.py b/maths/lucas_series.py index 6b32c2022..cae6c2815 100644 --- a/maths/lucas_series.py +++ b/maths/lucas_series.py @@ -50,7 +50,7 @@ def dynamic_lucas_number(n_th_number: int) -> int: if not isinstance(n_th_number, int): raise TypeError("dynamic_lucas_number accepts only integer arguments.") a, b = 2, 1 - for i in range(n_th_number): + for _ in range(n_th_number): a, b = b, a + b return a diff --git a/maths/miller_rabin.py b/maths/miller_rabin.py index b4dfed129..9f2668dba 100644 --- a/maths/miller_rabin.py +++ b/maths/miller_rabin.py @@ -33,7 +33,7 @@ def is_prime_big(n, prec=1000): b = bin_exp_mod(a, d, n) if b != 1: flag = True - for i in range(exp): + for _ in range(exp): if b == n - 1: flag = False break diff --git a/maths/monte_carlo_dice.py b/maths/monte_carlo_dice.py index 17cedbdbc..c4150b88f 100644 --- a/maths/monte_carlo_dice.py +++ b/maths/monte_carlo_dice.py @@ -35,7 +35,7 @@ def throw_dice(num_throws: int, num_dice: int = 2) -> list[float]: """ dices = [Dice() for i in range(num_dice)] count_of_sum = [0] * (len(dices) * Dice.NUM_SIDES + 1) - for i in range(num_throws): + for _ in range(num_throws): count_of_sum[sum(dice.roll() for dice in dices)] += 1 probability = [round((count * 100) / num_throws, 2) for count in count_of_sum] return probability[num_dice:] # remove probability of sums that never appear diff --git a/maths/numerical_integration.py b/maths/numerical_integration.py index a2bfce5b9..8f32fd356 100644 --- a/maths/numerical_integration.py +++ b/maths/numerical_integration.py @@ -39,7 +39,7 @@ def trapezoidal_area( fx1 = fnc(x_start) area = 0.0 - for i in range(steps): + for _ in range(steps): # Approximates small segments of curve as linear and solve # for trapezoidal area diff --git a/maths/pi_monte_carlo_estimation.py b/maths/pi_monte_carlo_estimation.py index 81be08378..29b679907 100644 --- a/maths/pi_monte_carlo_estimation.py +++ b/maths/pi_monte_carlo_estimation.py @@ -47,7 +47,7 @@ def estimate_pi(number_of_simulations: int) -> float: raise ValueError("At least one simulation is necessary to estimate PI.") number_in_unit_circle = 0 - for simulation_index in range(number_of_simulations): + for _ in range(number_of_simulations): random_point = Point.random_unit_square() if random_point.is_in_unit_circle(): diff --git a/maths/pollard_rho.py b/maths/pollard_rho.py index 0fc80cd42..5082f54f7 100644 --- a/maths/pollard_rho.py +++ b/maths/pollard_rho.py @@ -73,7 +73,7 @@ def pollard_rho( """ return (pow(value, 2) + step) % modulus - for attempt in range(attempts): + for _ in range(attempts): # These track the position within the cycle detection logic. tortoise = seed hare = seed diff --git a/maths/primelib.py b/maths/primelib.py index 7d2a22f39..eb72a9f8a 100644 --- a/maths/primelib.py +++ b/maths/primelib.py @@ -406,14 +406,14 @@ def kg_v(number1, number2): count1 = prime_fac_1.count(n) count2 = prime_fac_2.count(n) - for i in range(max(count1, count2)): + for _ in range(max(count1, count2)): ans *= n else: count1 = prime_fac_1.count(n) - for i in range(count1): + for _ in range(count1): ans *= n done.append(n) @@ -425,7 +425,7 @@ def kg_v(number1, number2): count2 = prime_fac_2.count(n) - for i in range(count2): + for _ in range(count2): ans *= n done.append(n) @@ -637,7 +637,7 @@ def fib(n): fib1 = 1 ans = 1 # this will be return - for i in range(n - 1): + for _ in range(n - 1): tmp = ans ans += fib1 diff --git a/maths/proth_number.py b/maths/proth_number.py index e17503143..6b1519024 100644 --- a/maths/proth_number.py +++ b/maths/proth_number.py @@ -49,7 +49,7 @@ def proth(number: int) -> int: proth_index = 2 increment = 3 for block in range(1, block_index): - for move in range(increment): + for _ in range(increment): proth_list.append(2 ** (block + 1) + proth_list[proth_index - 1]) proth_index += 1 increment *= 2 diff --git a/maths/square_root.py b/maths/square_root.py index b324c7230..2cbf14bea 100644 --- a/maths/square_root.py +++ b/maths/square_root.py @@ -49,7 +49,7 @@ def square_root_iterative( value = get_initial_point(a) - for i in range(max_iter): + for _ in range(max_iter): prev_value = value value = value - fx(value, a) / fx_derivative(value) if abs(prev_value - value) < tolerance: diff --git a/maths/ugly_numbers.py b/maths/ugly_numbers.py index 4451a68cd..81bd928c6 100644 --- a/maths/ugly_numbers.py +++ b/maths/ugly_numbers.py @@ -32,7 +32,7 @@ def ugly_numbers(n: int) -> int: next_3 = ugly_nums[i3] * 3 next_5 = ugly_nums[i5] * 5 - for i in range(1, n): + for _ in range(1, n): next_num = min(next_2, next_3, next_5) ugly_nums.append(next_num) if next_num == next_2: diff --git a/matrix/matrix_class.py b/matrix/matrix_class.py index 305cad0a5..6495bd8fc 100644 --- a/matrix/matrix_class.py +++ b/matrix/matrix_class.py @@ -351,7 +351,7 @@ class Matrix: "Only invertable matrices can be raised to a negative power" ) result = self - for i in range(other - 1): + for _ in range(other - 1): result *= self return result diff --git a/matrix/nth_fibonacci_using_matrix_exponentiation.py b/matrix/nth_fibonacci_using_matrix_exponentiation.py index 7c964d884..65f10c90d 100644 --- a/matrix/nth_fibonacci_using_matrix_exponentiation.py +++ b/matrix/nth_fibonacci_using_matrix_exponentiation.py @@ -65,7 +65,7 @@ def nth_fibonacci_bruteforce(n: int) -> int: return n fib0 = 0 fib1 = 1 - for i in range(2, n + 1): + for _ in range(2, n + 1): fib0, fib1 = fib1, fib0 + fib1 return fib1 diff --git a/neural_network/back_propagation_neural_network.py b/neural_network/back_propagation_neural_network.py index 43e796e77..23b818b0f 100644 --- a/neural_network/back_propagation_neural_network.py +++ b/neural_network/back_propagation_neural_network.py @@ -128,7 +128,7 @@ class BPNN: self.ax_loss.hlines(self.accuracy, 0, self.train_round * 1.1) x_shape = np.shape(xdata) - for round_i in range(train_round): + for _ in range(train_round): all_loss = 0 for row in range(x_shape[0]): _xdata = np.asmatrix(xdata[row, :]).T diff --git a/neural_network/perceptron.py b/neural_network/perceptron.py index a2bfdb326..f04c81424 100644 --- a/neural_network/perceptron.py +++ b/neural_network/perceptron.py @@ -69,7 +69,7 @@ class Perceptron: for sample in self.sample: sample.insert(0, self.bias) - for i in range(self.col_sample): + for _ in range(self.col_sample): self.weight.append(random.random()) self.weight.insert(0, self.bias) diff --git a/other/lfu_cache.py b/other/lfu_cache.py index 072d00ab5..2f26bb6cc 100644 --- a/other/lfu_cache.py +++ b/other/lfu_cache.py @@ -303,7 +303,7 @@ class LFUCache(Generic[T, U]): def cache_info() -> LFUCache[T, U]: return cls.decorator_function_to_instance_map[func] - setattr(cache_decorator_wrapper, "cache_info", cache_info) + setattr(cache_decorator_wrapper, "cache_info", cache_info) # noqa: B010 return cache_decorator_wrapper diff --git a/other/lru_cache.py b/other/lru_cache.py index b68ae0a8e..aa910e487 100644 --- a/other/lru_cache.py +++ b/other/lru_cache.py @@ -321,7 +321,7 @@ class LRUCache(Generic[T, U]): def cache_info() -> LRUCache[T, U]: return cls.decorator_function_to_instance_map[func] - setattr(cache_decorator_wrapper, "cache_info", cache_info) + setattr(cache_decorator_wrapper, "cache_info", cache_info) # noqa: B010 return cache_decorator_wrapper diff --git a/other/magicdiamondpattern.py b/other/magicdiamondpattern.py index 71bc50b51..0fc41d7a2 100644 --- a/other/magicdiamondpattern.py +++ b/other/magicdiamondpattern.py @@ -8,9 +8,9 @@ def floyd(n): n : size of pattern """ for i in range(0, n): - for j in range(0, n - i - 1): # printing spaces + for _ in range(0, n - i - 1): # printing spaces print(" ", end="") - for k in range(0, i + 1): # printing stars + for _ in range(0, i + 1): # printing stars print("* ", end="") print() @@ -22,10 +22,10 @@ def reverse_floyd(n): n : size of pattern """ for i in range(n, 0, -1): - for j in range(i, 0, -1): # printing stars + for _ in range(i, 0, -1): # printing stars print("* ", end="") print() - for k in range(n - i + 1, 0, -1): # printing spaces + for _ in range(n - i + 1, 0, -1): # printing spaces print(" ", end="") diff --git a/other/scoring_algorithm.py b/other/scoring_algorithm.py index aecd19c55..1e6293f84 100644 --- a/other/scoring_algorithm.py +++ b/other/scoring_algorithm.py @@ -77,7 +77,7 @@ def procentual_proximity( final_scores: list[float] = [0 for i in range(len(score_lists[0]))] # generate final scores - for i, slist in enumerate(score_lists): + for slist in score_lists: for j, ele in enumerate(slist): final_scores[j] = final_scores[j] + ele diff --git a/physics/lorentz_transformation_four_vector.py b/physics/lorentz_transformation_four_vector.py index bda852c25..f58b40e59 100644 --- a/physics/lorentz_transformation_four_vector.py +++ b/physics/lorentz_transformation_four_vector.py @@ -145,7 +145,7 @@ def transformation_matrix(velocity: float) -> np.array: def transform( - velocity: float, event: np.array = np.zeros(4), symbolic: bool = True + velocity: float, event: np.array = np.zeros(4), symbolic: bool = True # noqa: B008 ) -> np.array: """ >>> transform(29979245,np.array([1,2,3,4]), False) diff --git a/physics/n_body_simulation.py b/physics/n_body_simulation.py index 7e9fc1642..2f8153782 100644 --- a/physics/n_body_simulation.py +++ b/physics/n_body_simulation.py @@ -310,7 +310,7 @@ def example_3() -> BodySystem: """ bodies = [] - for i in range(10): + for _ in range(10): velocity_x = random.uniform(-0.5, 0.5) velocity_y = random.uniform(-0.5, 0.5) diff --git a/project_euler/problem_011/sol2.py b/project_euler/problem_011/sol2.py index 839ca6717..9ea0db991 100644 --- a/project_euler/problem_011/sol2.py +++ b/project_euler/problem_011/sol2.py @@ -36,7 +36,7 @@ def solution(): """ with open(os.path.dirname(__file__) + "/grid.txt") as f: l = [] # noqa: E741 - for i in range(20): + for _ in range(20): l.append([int(x) for x in f.readline().split()]) maximum = 0 diff --git a/project_euler/problem_025/sol3.py b/project_euler/problem_025/sol3.py index c66411dc5..0b9f3a0c8 100644 --- a/project_euler/problem_025/sol3.py +++ b/project_euler/problem_025/sol3.py @@ -45,7 +45,7 @@ def solution(n: int = 1000) -> int: f = f1 + f2 f1, f2 = f2, f index += 1 - for j in str(f): + for _ in str(f): i += 1 if i == n: break diff --git a/project_euler/problem_026/sol1.py b/project_euler/problem_026/sol1.py index 75d48df79..ccf2c111d 100644 --- a/project_euler/problem_026/sol1.py +++ b/project_euler/problem_026/sol1.py @@ -41,7 +41,7 @@ def solution(numerator: int = 1, digit: int = 1000) -> int: for divide_by_number in range(numerator, digit + 1): has_been_divided: list[int] = [] now_divide = numerator - for division_cycle in range(1, digit + 1): + for _ in range(1, digit + 1): if now_divide in has_been_divided: if longest_list_length < len(has_been_divided): longest_list_length = len(has_been_divided) diff --git a/project_euler/problem_188/sol1.py b/project_euler/problem_188/sol1.py index dd4360adb..88bd1327e 100644 --- a/project_euler/problem_188/sol1.py +++ b/project_euler/problem_188/sol1.py @@ -58,7 +58,7 @@ def solution(base: int = 1777, height: int = 1855, digits: int = 8) -> int: # calculate base↑↑height by right-assiciative repeated modular # exponentiation result = base - for i in range(1, height): + for _ in range(1, height): result = _modexpt(base, result, 10**digits) return result diff --git a/project_euler/problem_203/sol1.py b/project_euler/problem_203/sol1.py index dc93683da..713b530b6 100644 --- a/project_euler/problem_203/sol1.py +++ b/project_euler/problem_203/sol1.py @@ -49,7 +49,7 @@ def get_pascal_triangle_unique_coefficients(depth: int) -> set[int]: """ coefficients = {1} previous_coefficients = [1] - for step in range(2, depth + 1): + for _ in range(2, depth + 1): coefficients_begins_one = previous_coefficients + [0] coefficients_ends_one = [0] + previous_coefficients previous_coefficients = [] diff --git a/scheduling/multi_level_feedback_queue.py b/scheduling/multi_level_feedback_queue.py index b54cc8719..a3ba1b340 100644 --- a/scheduling/multi_level_feedback_queue.py +++ b/scheduling/multi_level_feedback_queue.py @@ -205,7 +205,7 @@ class MLFQ: """ finished: deque[Process] = deque() # sequence deque of terminated process # just for 1 cycle and unfinished processes will go back to queue - for i in range(len(ready_queue)): + for _ in range(len(ready_queue)): cp = ready_queue.popleft() # current process # if process's arrival time is later than current time, update current time diff --git a/sorts/double_sort.py b/sorts/double_sort.py index 4e08e27b3..5ca88a674 100644 --- a/sorts/double_sort.py +++ b/sorts/double_sort.py @@ -15,7 +15,7 @@ def double_sort(lst): True """ no_of_elements = len(lst) - for i in range( + for _ in range( 0, int(((no_of_elements - 1) / 2) + 1) ): # we don't need to traverse to end of list as for j in range(0, no_of_elements - 1): diff --git a/web_programming/open_google_results.py b/web_programming/open_google_results.py index 0e1dba8c5..2685bf621 100644 --- a/web_programming/open_google_results.py +++ b/web_programming/open_google_results.py @@ -1,10 +1,10 @@ import webbrowser from sys import argv -from urllib.parse import quote, parse_qs -from fake_useragent import UserAgent +from urllib.parse import parse_qs, quote import requests from bs4 import BeautifulSoup +from fake_useragent import UserAgent if __name__ == "__main__": if len(argv) > 1: @@ -18,9 +18,7 @@ if __name__ == "__main__": res = requests.get( url, - headers={ - "User-Agent": str(UserAgent().random) - }, + headers={"User-Agent": str(UserAgent().random)}, ) try: From 71353ed79787cbbe3800ee32a1fb3d82c1335d19 Mon Sep 17 00:00:00 2001 From: Advik Sharma <70201060+advik-student-dev@users.noreply.github.com> Date: Thu, 13 Oct 2022 10:09:48 -0700 Subject: [PATCH 360/726] refined readme.md (#7081) * refined readme.md added some refinements to readme.md * Update README.md Co-authored-by: Christian Clauss --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c499c14e1..da80c012b 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@

All algorithms implemented in Python - for education

-Implementations are for learning purposes only. As they may be less efficient than the implementations in the Python standard library, use them at your discretion. +Implementations are for learning purposes only. They may be less efficient than the implementations in the Python standard library. Use them at your discretion. ## Getting Started @@ -42,8 +42,8 @@ Read through our [Contribution Guidelines](CONTRIBUTING.md) before you contribut ## Community Channels -We're on [Discord](https://discord.gg/c7MnfGFGa6) and [Gitter](https://gitter.im/TheAlgorithms)! Community channels are great for you to ask questions and get help. Please join us! +We are on [Discord](https://discord.gg/c7MnfGFGa6) and [Gitter](https://gitter.im/TheAlgorithms)! Community channels are a great way for you to ask questions and get help. Please join us! ## List of Algorithms -See our [directory](DIRECTORY.md) for easier navigation and better overview of the project. +See our [directory](DIRECTORY.md) for easier navigation and a better overview of the project. From 3deb4a3042438007df7373c07c6280e55d3511da Mon Sep 17 00:00:00 2001 From: Anurag Shukla <76862299+anuragshuklajec@users.noreply.github.com> Date: Fri, 14 Oct 2022 01:33:15 +0530 Subject: [PATCH 361/726] Create binary_search_matrix.py (#6995) * Create binary_search_matrix.py Added an algorithm to search in matrix * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update binary_search_matrix.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix Indentation * Update matrix/binary_search_matrix.py Co-authored-by: Christian Clauss Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- matrix/binary_search_matrix.py | 57 ++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 matrix/binary_search_matrix.py diff --git a/matrix/binary_search_matrix.py b/matrix/binary_search_matrix.py new file mode 100644 index 000000000..6f203b7a3 --- /dev/null +++ b/matrix/binary_search_matrix.py @@ -0,0 +1,57 @@ +def binary_search(array: list, lower_bound: int, upper_bound: int, value: int) -> int: + """ + This function carries out Binary search on a 1d array and + return -1 if it do not exist + array: A 1d sorted array + value : the value meant to be searched + >>> matrix = [1, 4, 7, 11, 15] + >>> binary_search(matrix, 0, len(matrix) - 1, 1) + 0 + >>> binary_search(matrix, 0, len(matrix) - 1, 23) + -1 + """ + + r = int((lower_bound + upper_bound) // 2) + if array[r] == value: + return r + if lower_bound >= upper_bound: + return -1 + if array[r] < value: + return binary_search(array, r + 1, upper_bound, value) + else: + return binary_search(array, lower_bound, r - 1, value) + + +def mat_bin_search(value: int, matrix: list) -> list: + """ + This function loops over a 2d matrix and calls binarySearch on + the selected 1d array and returns [-1, -1] is it do not exist + value : value meant to be searched + matrix = a sorted 2d matrix + >>> matrix = [[1, 4, 7, 11, 15], + ... [2, 5, 8, 12, 19], + ... [3, 6, 9, 16, 22], + ... [10, 13, 14, 17, 24], + ... [18, 21, 23, 26, 30]] + >>> target = 1 + >>> mat_bin_search(target, matrix) + [0, 0] + >>> target = 34 + >>> mat_bin_search(target, matrix) + [-1, -1] + """ + index = 0 + if matrix[index][0] == value: + return [index, 0] + while index < len(matrix) and matrix[index][0] < value: + r = binary_search(matrix[index], 0, len(matrix[index]) - 1, value) + if r != -1: + return [index, r] + index += 1 + return [-1, -1] + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 05e19128f7fd1bee9c8d037b3f84cd42374aad0d Mon Sep 17 00:00:00 2001 From: AkshajV1309 <79909101+AkshajV1309@users.noreply.github.com> Date: Fri, 14 Oct 2022 01:54:31 +0530 Subject: [PATCH 362/726] Create norgate.py (#7133) * Create norgate.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Create norgate.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update boolean_algebra/norgate.py * Update boolean_algebra/norgate.py * Update boolean_algebra/norgate.py * Update boolean_algebra/norgate.py * Update boolean_algebra/norgate.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- boolean_algebra/norgate.py | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 boolean_algebra/norgate.py diff --git a/boolean_algebra/norgate.py b/boolean_algebra/norgate.py new file mode 100644 index 000000000..82a1fb2e3 --- /dev/null +++ b/boolean_algebra/norgate.py @@ -0,0 +1,46 @@ +""" A NOR Gate is a logic gate in boolean algebra which results to false(0) + if any of the input is 1, and True(1) if both the inputs are 0. + Following is the truth table of an NOR Gate: + | Input 1 | Input 2 | Output | + | 0 | 0 | 1 | + | 0 | 1 | 0 | + | 1 | 0 | 0 | + | 1 | 1 | 0 | +""" +"""Following is the code implementation of the NOR Gate""" + + +def nor_gate(input_1: int, input_2: int) -> int: + """ + >>> nor_gate(0, 0) + 1 + >>> nor_gate(0, 1) + 0 + >>> nor_gate(1, 0) + 0 + >>> nor_gate(1, 1) + 0 + >>> nor_gate(0.0, 0.0) + 1 + >>> nor_gate(0, -7) + 0 + """ + return int(bool(input_1 == input_2 == 0)) + + +def main() -> None: + print("Truth Table of NOR Gate:") + print("| Input 1 |", " Input 2 |", " Output |") + print("| 0 |", " 0 | ", nor_gate(0, 0), " |") + print("| 0 |", " 1 | ", nor_gate(0, 1), " |") + print("| 1 |", " 0 | ", nor_gate(1, 0), " |") + print("| 1 |", " 1 | ", nor_gate(1, 1), " |") + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + main() +"""Code provided by Akshaj Vishwanathan""" +"""Reference: https://www.geeksforgeeks.org/logic-gates-in-python/""" From 26fe4c65390b7a2bfe2722b674943b64820d8442 Mon Sep 17 00:00:00 2001 From: Md Mahiuddin <68785084+mahiuddin-dev@users.noreply.github.com> Date: Fri, 14 Oct 2022 13:20:40 +0600 Subject: [PATCH 363/726] Remove extra Semicolon (#7152) --- data_structures/queue/linked_queue.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/queue/linked_queue.py b/data_structures/queue/linked_queue.py index c6e9f5390..3675da7db 100644 --- a/data_structures/queue/linked_queue.py +++ b/data_structures/queue/linked_queue.py @@ -22,7 +22,7 @@ class LinkedQueue: >>> queue.put(5) >>> queue.put(9) >>> queue.put('python') - >>> queue.is_empty(); + >>> queue.is_empty() False >>> queue.get() 5 From e40c7b4bf1794c94993715c99e2a97b9d8f5e590 Mon Sep 17 00:00:00 2001 From: Dhruv Manilawala Date: Fri, 14 Oct 2022 20:04:44 +0530 Subject: [PATCH 364/726] refactor: move flake8 config (#7167) * refactor: move flake8 config * Update .pre-commit-config.yaml Co-authored-by: Christian Clauss --- .flake8 | 5 +++++ .pre-commit-config.yaml | 8 ++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.flake8 b/.flake8 index 9a5863c9c..0d9ef18d1 100644 --- a/.flake8 +++ b/.flake8 @@ -1,3 +1,8 @@ [flake8] +max-line-length = 88 +max-complexity = 25 extend-ignore = A003 # Class attribute is shadowing a python builtin + # Formatting style for `black` + E203 # Whitespace before ':' + W503 # Line break occurred before a binary operator diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d2558b90a..d3ea9722f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,11 +35,7 @@ repos: - repo: https://github.com/PyCQA/flake8 rev: 5.0.4 hooks: - - id: flake8 - args: - - --ignore=E203,W503 - - --max-complexity=25 - - --max-line-length=88 + - id: flake8 # See .flake8 for args additional_dependencies: - flake8-bugbear - flake8-builtins @@ -51,7 +47,7 @@ repos: - id: mypy args: - --ignore-missing-imports - - --install-types # See mirrors-mypy README.md + - --install-types # See mirrors-mypy README.md - --non-interactive additional_dependencies: [types-requests] From fd5ab454921b687af94927015d4ab06d3a84886b Mon Sep 17 00:00:00 2001 From: Abinash Satapathy Date: Fri, 14 Oct 2022 17:47:39 +0200 Subject: [PATCH 365/726] Doctest output simpler version (#7116) * Update README.md Added Google Cirq references * Create barcode_validator.py Barcode/EAN validator * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update barcode_validator.py Included docstring and updated variables to snake_case * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update barcode_validator.py Included docset and updated bugs * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update barcode_validator.py Implemented the changes asked in review. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update barcode_validator.py Updated with f-string format * Update barcode_validator.py * Update volume_conversions.py Simpler doctest output * Update volume_conversions.py Fixed indentation Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- conversions/volume_conversions.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/conversions/volume_conversions.py b/conversions/volume_conversions.py index de2290196..44d290091 100644 --- a/conversions/volume_conversions.py +++ b/conversions/volume_conversions.py @@ -52,11 +52,7 @@ def volume_conversion(value: float, from_type: str, to_type: str) -> float: 0.000236588 >>> volume_conversion(4, "wrongUnit", "litre") Traceback (most recent call last): - File "/usr/lib/python3.8/doctest.py", line 1336, in __run - exec(compile(example.source, filename, "single", - File "", line 1, in - volume_conversion(4, "wrongUnit", "litre") - File "", line 62, in volume_conversion + ... ValueError: Invalid 'from_type' value: 'wrongUnit' Supported values are: cubicmeter, litre, kilolitre, gallon, cubicyard, cubicfoot, cup """ From 0c06b255822905512b9fa9c12cb09dabf8fa405f Mon Sep 17 00:00:00 2001 From: Abinash Satapathy Date: Fri, 14 Oct 2022 23:42:41 +0200 Subject: [PATCH 366/726] Create speed_conversions.py (#7128) * Update README.md Added Google Cirq references * Create barcode_validator.py Barcode/EAN validator * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update barcode_validator.py Included docstring and updated variables to snake_case * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update barcode_validator.py Included docset and updated bugs * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update barcode_validator.py Implemented the changes asked in review. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update barcode_validator.py Updated with f-string format * Update barcode_validator.py * Update volume_conversions.py Simpler doctest output * Create speed_conversions.py Conversion of speed units * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update speed_conversions.py Doctests updated, dictionary implemented. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update speed_conversions.py Reduced LOC * Update volume_conversions.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- conversions/speed_conversions.py | 70 ++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 conversions/speed_conversions.py diff --git a/conversions/speed_conversions.py b/conversions/speed_conversions.py new file mode 100644 index 000000000..62da9e137 --- /dev/null +++ b/conversions/speed_conversions.py @@ -0,0 +1,70 @@ +""" +Convert speed units + +https://en.wikipedia.org/wiki/Kilometres_per_hour +https://en.wikipedia.org/wiki/Miles_per_hour +https://en.wikipedia.org/wiki/Knot_(unit) +https://en.wikipedia.org/wiki/Metre_per_second +""" + +speed_chart: dict[str, float] = { + "km/h": 1.0, + "m/s": 3.6, + "mph": 1.609344, + "knot": 1.852, +} + +speed_chart_inverse: dict[str, float] = { + "km/h": 1.0, + "m/s": 0.277777778, + "mph": 0.621371192, + "knot": 0.539956803, +} + + +def convert_speed(speed: float, unit_from: str, unit_to: str) -> float: + """ + Convert speed from one unit to another using the speed_chart above. + + "km/h": 1.0, + "m/s": 3.6, + "mph": 1.609344, + "knot": 1.852, + + >>> convert_speed(100, "km/h", "m/s") + 27.778 + >>> convert_speed(100, "km/h", "mph") + 62.137 + >>> convert_speed(100, "km/h", "knot") + 53.996 + >>> convert_speed(100, "m/s", "km/h") + 360.0 + >>> convert_speed(100, "m/s", "mph") + 223.694 + >>> convert_speed(100, "m/s", "knot") + 194.384 + >>> convert_speed(100, "mph", "km/h") + 160.934 + >>> convert_speed(100, "mph", "m/s") + 44.704 + >>> convert_speed(100, "mph", "knot") + 86.898 + >>> convert_speed(100, "knot", "km/h") + 185.2 + >>> convert_speed(100, "knot", "m/s") + 51.444 + >>> convert_speed(100, "knot", "mph") + 115.078 + """ + if unit_to not in speed_chart or unit_from not in speed_chart_inverse: + raise ValueError( + f"Incorrect 'from_type' or 'to_type' value: {unit_from!r}, {unit_to!r}\n" + f"Valid values are: {', '.join(speed_chart_inverse)}" + ) + return round(speed * speed_chart[unit_from] * speed_chart_inverse[unit_to], 3) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 20587750051c3699b051579d7e97e5508958ea5a Mon Sep 17 00:00:00 2001 From: Caeden Date: Fri, 14 Oct 2022 23:25:15 +0100 Subject: [PATCH 367/726] refactor: Make code more understandable (#7196) * refactor: Make code more understandable * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .../binary_tree/binary_tree_traversals.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/data_structures/binary_tree/binary_tree_traversals.py b/data_structures/binary_tree/binary_tree_traversals.py index 378598bb0..54b1dc536 100644 --- a/data_structures/binary_tree/binary_tree_traversals.py +++ b/data_structures/binary_tree/binary_tree_traversals.py @@ -15,7 +15,20 @@ class Node: def make_tree() -> Node | None: - return Node(1, Node(2, Node(4), Node(5)), Node(3)) + r""" + The below tree + 1 + / \ + 2 3 + / \ + 4 5 + """ + tree = Node(1) + tree.left = Node(2) + tree.right = Node(3) + tree.left.left = Node(4) + tree.left.right = Node(5) + return tree def preorder(root: Node | None) -> list[int]: From 5dc0dc4d23eb1efa4564c0531402af3d2419012d Mon Sep 17 00:00:00 2001 From: Lukas Esc <55601315+Luk-ESC@users.noreply.github.com> Date: Fri, 14 Oct 2022 17:37:15 -0500 Subject: [PATCH 368/726] remove useless bool() call (#7189) --- boolean_algebra/norgate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boolean_algebra/norgate.py b/boolean_algebra/norgate.py index 82a1fb2e3..1c341e8a7 100644 --- a/boolean_algebra/norgate.py +++ b/boolean_algebra/norgate.py @@ -25,7 +25,7 @@ def nor_gate(input_1: int, input_2: int) -> int: >>> nor_gate(0, -7) 0 """ - return int(bool(input_1 == input_2 == 0)) + return int(input_1 == input_2 == 0) def main() -> None: From dcca5351c9185bf8c568615782ffb28319a6539d Mon Sep 17 00:00:00 2001 From: Claudio Lucisano <43884655+Claudiocli@users.noreply.github.com> Date: Sat, 15 Oct 2022 00:45:12 +0200 Subject: [PATCH 369/726] Added astronomical_length_scale_conversion.py (#7183) --- .../astronomical_length_scale_conversion.py | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 conversions/astronomical_length_scale_conversion.py diff --git a/conversions/astronomical_length_scale_conversion.py b/conversions/astronomical_length_scale_conversion.py new file mode 100644 index 000000000..804d82487 --- /dev/null +++ b/conversions/astronomical_length_scale_conversion.py @@ -0,0 +1,104 @@ +""" +Conversion of length units. +Available Units: +Metre, Kilometre, Megametre, Gigametre, +Terametre, Petametre, Exametre, Zettametre, Yottametre + +USAGE : +-> Import this file into their respective project. +-> Use the function length_conversion() for conversion of length units. +-> Parameters : + -> value : The number of from units you want to convert + -> from_type : From which type you want to convert + -> to_type : To which type you want to convert + +REFERENCES : +-> Wikipedia reference: https://en.wikipedia.org/wiki/Meter +-> Wikipedia reference: https://en.wikipedia.org/wiki/Kilometer +-> Wikipedia reference: https://en.wikipedia.org/wiki/Orders_of_magnitude_(length) +""" + +UNIT_SYMBOL = { + "meter": "m", + "kilometer": "km", + "megametre": "Mm", + "gigametre": "Gm", + "terametre": "Tm", + "petametre": "Pm", + "exametre": "Em", + "zettametre": "Zm", + "yottametre": "Ym", +} +# Exponent of the factor(meter) +METRIC_CONVERSION = { + "m": 0, + "km": 3, + "Mm": 6, + "Gm": 9, + "Tm": 12, + "Pm": 15, + "Em": 18, + "Zm": 21, + "Ym": 24, +} + + +def length_conversion(value: float, from_type: str, to_type: str) -> float: + """ + Conversion between astronomical length units. + + >>> length_conversion(1, "meter", "kilometer") + 0.001 + >>> length_conversion(1, "meter", "megametre") + 1e-06 + >>> length_conversion(1, "gigametre", "meter") + 1000000000 + >>> length_conversion(1, "gigametre", "terametre") + 0.001 + >>> length_conversion(1, "petametre", "terametre") + 1000 + >>> length_conversion(1, "petametre", "exametre") + 0.001 + >>> length_conversion(1, "terametre", "zettametre") + 1e-09 + >>> length_conversion(1, "yottametre", "zettametre") + 1000 + >>> length_conversion(4, "wrongUnit", "inch") + Traceback (most recent call last): + ... + ValueError: Invalid 'from_type' value: 'wrongUnit'. + Conversion abbreviations are: m, km, Mm, Gm, Tm, Pm, Em, Zm, Ym + """ + + from_sanitized = from_type.lower().strip("s") + to_sanitized = to_type.lower().strip("s") + + from_sanitized = UNIT_SYMBOL.get(from_sanitized, from_sanitized) + to_sanitized = UNIT_SYMBOL.get(to_sanitized, to_sanitized) + + if from_sanitized not in METRIC_CONVERSION: + raise ValueError( + f"Invalid 'from_type' value: {from_type!r}.\n" + f"Conversion abbreviations are: {', '.join(METRIC_CONVERSION)}" + ) + if to_sanitized not in METRIC_CONVERSION: + raise ValueError( + f"Invalid 'to_type' value: {to_type!r}.\n" + f"Conversion abbreviations are: {', '.join(METRIC_CONVERSION)}" + ) + from_exponent = METRIC_CONVERSION[from_sanitized] + to_exponent = METRIC_CONVERSION[to_sanitized] + exponent = 1 + + if from_exponent > to_exponent: + exponent = from_exponent - to_exponent + else: + exponent = -(to_exponent - from_exponent) + + return value * pow(10, exponent) + + +if __name__ == "__main__": + from doctest import testmod + + testmod() From 6e69181d1f592a08806717058720bf63e241eef2 Mon Sep 17 00:00:00 2001 From: Caeden Date: Sat, 15 Oct 2022 02:07:03 +0100 Subject: [PATCH 370/726] refactor: Replace `list()` and `dict()` calls with literals (#7198) --- data_structures/binary_tree/binary_search_tree.py | 2 +- data_structures/heap/heap_generic.py | 2 +- data_structures/trie/trie.py | 2 +- graphs/frequent_pattern_graph_miner.py | 2 +- maths/greedy_coin_change.py | 2 +- other/davisb_putnamb_logemannb_loveland.py | 4 ++-- project_euler/problem_107/sol1.py | 2 +- searches/tabu_search.py | 6 +++--- sorts/msd_radix_sort.py | 4 ++-- strings/aho_corasick.py | 2 +- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/data_structures/binary_tree/binary_search_tree.py b/data_structures/binary_tree/binary_search_tree.py index b9af23dc8..51a651be0 100644 --- a/data_structures/binary_tree/binary_search_tree.py +++ b/data_structures/binary_tree/binary_search_tree.py @@ -160,7 +160,7 @@ def postorder(curr_node): """ postOrder (left, right, self) """ - node_list = list() + node_list = [] if curr_node is not None: node_list = postorder(curr_node.left) + postorder(curr_node.right) + [curr_node] return node_list diff --git a/data_structures/heap/heap_generic.py b/data_structures/heap/heap_generic.py index e7831cd45..b4d7019f4 100644 --- a/data_structures/heap/heap_generic.py +++ b/data_structures/heap/heap_generic.py @@ -9,7 +9,7 @@ class Heap: def __init__(self, key: Callable | None = None) -> None: # Stores actual heap items. - self.arr: list = list() + self.arr: list = [] # Stores indexes of each item for supporting updates and deletion. self.pos_map: dict = {} # Stores current size of heap. diff --git a/data_structures/trie/trie.py b/data_structures/trie/trie.py index 162d08d1d..46b93a499 100644 --- a/data_structures/trie/trie.py +++ b/data_structures/trie/trie.py @@ -8,7 +8,7 @@ longest word)) lookup time making it an optimal approach when space is not an is class TrieNode: def __init__(self) -> None: - self.nodes: dict[str, TrieNode] = dict() # Mapping from char to TrieNode + self.nodes: dict[str, TrieNode] = {} # Mapping from char to TrieNode self.is_leaf = False def insert_many(self, words: list[str]) -> None: diff --git a/graphs/frequent_pattern_graph_miner.py b/graphs/frequent_pattern_graph_miner.py index a5ecbe6e8..1d26702a4 100644 --- a/graphs/frequent_pattern_graph_miner.py +++ b/graphs/frequent_pattern_graph_miner.py @@ -54,7 +54,7 @@ def get_frequency_table(edge_array): Returns Frequency Table """ distinct_edge = get_distinct_edge(edge_array) - frequency_table = dict() + frequency_table = {} for item in distinct_edge: bit = get_bitcode(edge_array, item) diff --git a/maths/greedy_coin_change.py b/maths/greedy_coin_change.py index 5233ee1cb..29c2f1803 100644 --- a/maths/greedy_coin_change.py +++ b/maths/greedy_coin_change.py @@ -74,7 +74,7 @@ def find_minimum_change(denominations: list[int], value: str) -> list[int]: # Driver Code if __name__ == "__main__": - denominations = list() + denominations = [] value = "0" if ( diff --git a/other/davisb_putnamb_logemannb_loveland.py b/other/davisb_putnamb_logemannb_loveland.py index 03d60a9a1..3110515d5 100644 --- a/other/davisb_putnamb_logemannb_loveland.py +++ b/other/davisb_putnamb_logemannb_loveland.py @@ -199,7 +199,7 @@ def find_pure_symbols( {'A1': True, 'A2': False, 'A3': True, 'A5': False} """ pure_symbols = [] - assignment: dict[str, bool | None] = dict() + assignment: dict[str, bool | None] = {} literals = [] for clause in clauses: @@ -264,7 +264,7 @@ def find_unit_clauses( n_count += 1 if f_count == len(clause) - 1 and n_count == 1: unit_symbols.append(sym) - assignment: dict[str, bool | None] = dict() + assignment: dict[str, bool | None] = {} for i in unit_symbols: symbol = i[:2] assignment[symbol] = len(i) == 2 diff --git a/project_euler/problem_107/sol1.py b/project_euler/problem_107/sol1.py index 048cf033d..b3f5685b9 100644 --- a/project_euler/problem_107/sol1.py +++ b/project_euler/problem_107/sol1.py @@ -100,7 +100,7 @@ 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() + edges: dict[EdgeT, int] = {} data: list[str] edge1: int edge2: int diff --git a/searches/tabu_search.py b/searches/tabu_search.py index 45ce19d46..3e1728286 100644 --- a/searches/tabu_search.py +++ b/searches/tabu_search.py @@ -51,7 +51,7 @@ def generate_neighbours(path): with open(path) as f: for line in f: if line.split()[0] not in dict_of_neighbours: - _list = list() + _list = [] _list.append([line.split()[1], line.split()[2]]) dict_of_neighbours[line.split()[0]] = _list else: @@ -59,7 +59,7 @@ def generate_neighbours(path): [line.split()[1], line.split()[2]] ) if line.split()[1] not in dict_of_neighbours: - _list = list() + _list = [] _list.append([line.split()[0], line.split()[2]]) dict_of_neighbours[line.split()[1]] = _list else: @@ -206,7 +206,7 @@ def tabu_search( """ count = 1 solution = first_solution - tabu_list = list() + tabu_list = [] best_cost = distance_of_first_solution best_solution_ever = solution diff --git a/sorts/msd_radix_sort.py b/sorts/msd_radix_sort.py index 3cdec4bd0..7430fc5a6 100644 --- a/sorts/msd_radix_sort.py +++ b/sorts/msd_radix_sort.py @@ -52,8 +52,8 @@ def _msd_radix_sort(list_of_ints: list[int], bit_position: int) -> list[int]: if bit_position == 0 or len(list_of_ints) in [0, 1]: return list_of_ints - zeros = list() - ones = list() + zeros = [] + ones = [] # Split numbers based on bit at bit_position from the right for number in list_of_ints: if (number >> (bit_position - 1)) & 1: diff --git a/strings/aho_corasick.py b/strings/aho_corasick.py index b9a6a8072..2d2f562df 100644 --- a/strings/aho_corasick.py +++ b/strings/aho_corasick.py @@ -5,7 +5,7 @@ from collections import deque class Automaton: def __init__(self, keywords: list[str]): - self.adlist: list[dict] = list() + self.adlist: list[dict] = [] self.adlist.append( {"value": "", "next_states": [], "fail_state": 0, "output": []} ) From 70b60dc3231e1df72622db64f9b97fef772181e5 Mon Sep 17 00:00:00 2001 From: Dhruv Manilawala Date: Sat, 15 Oct 2022 12:07:59 +0530 Subject: [PATCH 371/726] chore: remove inactive user from CODEOWNERS (#7205) * chore: remove inactive user from CODEOWNERS * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .github/CODEOWNERS | 6 +++--- DIRECTORY.md | 11 +++++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index fdce879f8..abf99ab22 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -35,7 +35,7 @@ # /divide_and_conquer/ -/dynamic_programming/ @Kush1101 +# /dynamic_programming/ # /file_transfer/ @@ -59,7 +59,7 @@ # /machine_learning/ -/maths/ @Kush1101 +# /maths/ # /matrix/ @@ -69,7 +69,7 @@ # /other/ @cclauss # TODO: Uncomment this line after Hacktoberfest -/project_euler/ @dhruvmanila @Kush1101 +/project_euler/ @dhruvmanila # /quantum/ diff --git a/DIRECTORY.md b/DIRECTORY.md index 2786e1f82..239dafa65 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -52,6 +52,7 @@ * [Modular Division](blockchain/modular_division.py) ## Boolean Algebra + * [Norgate](boolean_algebra/norgate.py) * [Quine Mc Cluskey](boolean_algebra/quine_mc_cluskey.py) ## Cellular Automata @@ -121,6 +122,7 @@ * [Pooling Functions](computer_vision/pooling_functions.py) ## Conversions + * [Astronomical Length Scale Conversion](conversions/astronomical_length_scale_conversion.py) * [Binary To Decimal](conversions/binary_to_decimal.py) * [Binary To Hexadecimal](conversions/binary_to_hexadecimal.py) * [Binary To Octal](conversions/binary_to_octal.py) @@ -140,6 +142,7 @@ * [Pressure Conversions](conversions/pressure_conversions.py) * [Rgb Hsv Conversion](conversions/rgb_hsv_conversion.py) * [Roman Numerals](conversions/roman_numerals.py) + * [Speed Conversions](conversions/speed_conversions.py) * [Temperature Conversions](conversions/temperature_conversions.py) * [Volume Conversions](conversions/volume_conversions.py) * [Weight Conversion](conversions/weight_conversion.py) @@ -448,6 +451,7 @@ * [Random Forest Classifier](machine_learning/random_forest_classifier.py) * [Random Forest Regressor](machine_learning/random_forest_regressor.py) * [Scoring Functions](machine_learning/scoring_functions.py) + * [Self Organizing Map](machine_learning/self_organizing_map.py) * [Sequential Minimum Optimization](machine_learning/sequential_minimum_optimization.py) * [Similarity Search](machine_learning/similarity_search.py) * [Support Vector Machines](machine_learning/support_vector_machines.py) @@ -586,9 +590,11 @@ * [Two Sum](maths/two_sum.py) * [Ugly Numbers](maths/ugly_numbers.py) * [Volume](maths/volume.py) + * [Weird Number](maths/weird_number.py) * [Zellers Congruence](maths/zellers_congruence.py) ## Matrix + * [Binary Search Matrix](matrix/binary_search_matrix.py) * [Count Islands In Matrix](matrix/count_islands_in_matrix.py) * [Inverse Of Matrix](matrix/inverse_of_matrix.py) * [Matrix Class](matrix/matrix_class.py) @@ -854,8 +860,6 @@ * [Sol1](project_euler/problem_101/sol1.py) * Problem 102 * [Sol1](project_euler/problem_102/sol1.py) - * Problem 104 - * [Sol](project_euler/problem_104/sol.py) * Problem 107 * [Sol1](project_euler/problem_107/sol1.py) * Problem 109 @@ -1010,6 +1014,7 @@ * [Alternative String Arrange](strings/alternative_string_arrange.py) * [Anagrams](strings/anagrams.py) * [Autocomplete Using Trie](strings/autocomplete_using_trie.py) + * [Barcode Validator](strings/barcode_validator.py) * [Boyer Moore Search](strings/boyer_moore_search.py) * [Can String Be Rearranged As Palindrome](strings/can_string_be_rearranged_as_palindrome.py) * [Capitalize](strings/capitalize.py) @@ -1039,6 +1044,7 @@ * [Reverse Letters](strings/reverse_letters.py) * [Reverse Long Words](strings/reverse_long_words.py) * [Reverse Words](strings/reverse_words.py) + * [Snake Case To Camel Pascal Case](strings/snake_case_to_camel_pascal_case.py) * [Split](strings/split.py) * [Upper](strings/upper.py) * [Wave](strings/wave.py) @@ -1073,6 +1079,7 @@ * [Instagram Pic](web_programming/instagram_pic.py) * [Instagram Video](web_programming/instagram_video.py) * [Nasa Data](web_programming/nasa_data.py) + * [Open Google Results](web_programming/open_google_results.py) * [Random Anime Character](web_programming/random_anime_character.py) * [Recaptcha Verification](web_programming/recaptcha_verification.py) * [Reddit](web_programming/reddit.py) From 6be9500b2fb5d2e51432f9966e76a107dd604a41 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 15 Oct 2022 09:02:07 +0200 Subject: [PATCH 372/726] chore: remove checkbox in feature issue template (#7212) We do not assign issues in this repo Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .github/ISSUE_TEMPLATE/feature_request.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index bed3e8ab5..09a159b21 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -17,10 +17,3 @@ body: implementations. validations: required: true - - - type: checkboxes - attributes: - label: Would you like to work on this feature? - options: - - label: Yes, I want to work on this feature! - required: false From 98a4c2487814cdfe0822526e05c4e63ff6aef7d0 Mon Sep 17 00:00:00 2001 From: Caeden Date: Sat, 15 Oct 2022 13:58:09 +0100 Subject: [PATCH 373/726] feat: Binary tree node sum (#7020) (#7162) * feat: Binary tree node sum (#7020) * feat: Sum of all nodes in binary tree explanation (#7020) * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update data_structures/binary_tree/binary_tree_node_sum.py Co-authored-by: Christian Clauss * refactor: Change replace method with `__iter__` overriding (#7020) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- DIRECTORY.md | 1 + .../binary_tree/binary_tree_node_sum.py | 76 +++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 data_structures/binary_tree/binary_tree_node_sum.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 239dafa65..92bed9cb4 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -154,6 +154,7 @@ * [Binary Search Tree](data_structures/binary_tree/binary_search_tree.py) * [Binary Search Tree Recursive](data_structures/binary_tree/binary_search_tree_recursive.py) * [Binary Tree Mirror](data_structures/binary_tree/binary_tree_mirror.py) + * [Binary Tree Node Sum](data_structures/binary_tree/binary_tree_node_sum.py) * [Binary Tree Traversals](data_structures/binary_tree/binary_tree_traversals.py) * [Fenwick Tree](data_structures/binary_tree/fenwick_tree.py) * [Inorder Tree Traversal 2022](data_structures/binary_tree/inorder_tree_traversal_2022.py) diff --git a/data_structures/binary_tree/binary_tree_node_sum.py b/data_structures/binary_tree/binary_tree_node_sum.py new file mode 100644 index 000000000..5a13e74e3 --- /dev/null +++ b/data_structures/binary_tree/binary_tree_node_sum.py @@ -0,0 +1,76 @@ +""" +Sum of all nodes in a binary tree. + +Python implementation: + O(n) time complexity - Recurses through :meth:`depth_first_search` + with each element. + O(n) space complexity - At any point in time maximum number of stack + frames that could be in memory is `n` +""" + + +from __future__ import annotations + +from collections.abc import Iterator + + +class Node: + """ + A Node has a value variable and pointers to Nodes to its left and right. + """ + + def __init__(self, value: int) -> None: + self.value = value + self.left: Node | None = None + self.right: Node | None = None + + +class BinaryTreeNodeSum: + r""" + The below tree looks like this + 10 + / \ + 5 -3 + / / \ + 12 8 0 + + >>> tree = Node(10) + >>> sum(BinaryTreeNodeSum(tree)) + 10 + + >>> tree.left = Node(5) + >>> sum(BinaryTreeNodeSum(tree)) + 15 + + >>> tree.right = Node(-3) + >>> sum(BinaryTreeNodeSum(tree)) + 12 + + >>> tree.left.left = Node(12) + >>> sum(BinaryTreeNodeSum(tree)) + 24 + + >>> tree.right.left = Node(8) + >>> tree.right.right = Node(0) + >>> sum(BinaryTreeNodeSum(tree)) + 32 + """ + + def __init__(self, tree: Node) -> None: + self.tree = tree + + def depth_first_search(self, node: Node | None) -> int: + if node is None: + return 0 + return node.value + ( + self.depth_first_search(node.left) + self.depth_first_search(node.right) + ) + + def __iter__(self) -> Iterator[int]: + yield self.depth_first_search(self.tree) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From a652905b605ddcc43626072366d1130315801dc9 Mon Sep 17 00:00:00 2001 From: Caeden Date: Sat, 15 Oct 2022 18:29:42 +0100 Subject: [PATCH 374/726] Add Flake8 comprehensions to pre-commit (#7235) * ci(pre-commit): Add ``flake8-comprehensions`` to ``pre-commit`` (#7233) * refactor: Fix ``flake8-comprehensions`` errors * fix: Replace `map` with generator (#7233) * fix: Cast `range` objects to `list` --- .pre-commit-config.yaml | 1 + ciphers/onepad_cipher.py | 2 +- ciphers/rail_fence_cipher.py | 2 +- data_structures/hashing/hash_table.py | 2 +- data_structures/linked_list/merge_two_lists.py | 2 +- dynamic_programming/fractional_knapsack.py | 2 +- graphs/bellman_ford.py | 2 +- graphs/frequent_pattern_graph_miner.py | 10 +++++----- hashes/enigma_machine.py | 8 ++++---- maths/primelib.py | 2 +- matrix/spiral_print.py | 4 ++-- other/davisb_putnamb_logemannb_loveland.py | 4 ++-- project_euler/problem_042/solution42.py | 4 ++-- project_euler/problem_052/sol1.py | 12 ++++++------ project_euler/problem_062/sol1.py | 2 +- project_euler/problem_067/sol1.py | 4 ++-- project_euler/problem_109/sol1.py | 2 +- project_euler/problem_551/sol1.py | 2 +- sorts/radix_sort.py | 2 +- strings/aho_corasick.py | 4 +--- 20 files changed, 36 insertions(+), 37 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d3ea9722f..345513565 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -39,6 +39,7 @@ repos: additional_dependencies: - flake8-bugbear - flake8-builtins + - flake8-comprehensions - pep8-naming - repo: https://github.com/pre-commit/mirrors-mypy diff --git a/ciphers/onepad_cipher.py b/ciphers/onepad_cipher.py index 3ace9b098..4bfe35b71 100644 --- a/ciphers/onepad_cipher.py +++ b/ciphers/onepad_cipher.py @@ -22,7 +22,7 @@ class Onepad: for i in range(len(key)): p = int((cipher[i] - (key[i]) ** 2) / key[i]) plain.append(chr(p)) - return "".join([i for i in plain]) + return "".join(plain) if __name__ == "__main__": diff --git a/ciphers/rail_fence_cipher.py b/ciphers/rail_fence_cipher.py index cba593ca7..47ee7db89 100644 --- a/ciphers/rail_fence_cipher.py +++ b/ciphers/rail_fence_cipher.py @@ -72,7 +72,7 @@ def decrypt(input_string: str, key: int) -> str: counter = 0 for row in temp_grid: # fills in the characters splice = input_string[counter : counter + len(row)] - grid.append([character for character in splice]) + grid.append(list(splice)) counter += len(row) output_string = "" # reads as zigzag diff --git a/data_structures/hashing/hash_table.py b/data_structures/hashing/hash_table.py index 1cd71cc4b..607454c82 100644 --- a/data_structures/hashing/hash_table.py +++ b/data_structures/hashing/hash_table.py @@ -34,7 +34,7 @@ class HashTable: def _step_by_step(self, step_ord): print(f"step {step_ord}") - print([i for i in range(len(self.values))]) + print(list(range(len(self.values)))) print(self.values) def bulk_insert(self, values): diff --git a/data_structures/linked_list/merge_two_lists.py b/data_structures/linked_list/merge_two_lists.py index 43dd46186..93cf7a7e1 100644 --- a/data_structures/linked_list/merge_two_lists.py +++ b/data_structures/linked_list/merge_two_lists.py @@ -19,7 +19,7 @@ class Node: class SortedLinkedList: def __init__(self, ints: Iterable[int]) -> None: self.head: Node | None = None - for i in reversed(sorted(ints)): + for i in sorted(ints, reverse=True): self.head = Node(i, self.head) def __iter__(self) -> Iterator[int]: diff --git a/dynamic_programming/fractional_knapsack.py b/dynamic_programming/fractional_knapsack.py index 6f7a2a08c..58976d40c 100644 --- a/dynamic_programming/fractional_knapsack.py +++ b/dynamic_programming/fractional_knapsack.py @@ -8,7 +8,7 @@ def frac_knapsack(vl, wt, w, n): 240.0 """ - r = list(sorted(zip(vl, wt), key=lambda x: x[0] / x[1], reverse=True)) + r = sorted(zip(vl, wt), key=lambda x: x[0] / x[1], reverse=True) vl, wt = [i[0] for i in r], [i[1] for i in r] acc = list(accumulate(wt)) k = bisect(acc, w) diff --git a/graphs/bellman_ford.py b/graphs/bellman_ford.py index eb2cd25bf..9ac8bae85 100644 --- a/graphs/bellman_ford.py +++ b/graphs/bellman_ford.py @@ -58,7 +58,7 @@ if __name__ == "__main__": V = int(input("Enter number of vertices: ").strip()) E = int(input("Enter number of edges: ").strip()) - graph: list[dict[str, int]] = [dict() for j in range(E)] + graph: list[dict[str, int]] = [{} for _ in range(E)] for i in range(E): print("Edge ", i + 1) diff --git a/graphs/frequent_pattern_graph_miner.py b/graphs/frequent_pattern_graph_miner.py index 1d26702a4..87d5605a0 100644 --- a/graphs/frequent_pattern_graph_miner.py +++ b/graphs/frequent_pattern_graph_miner.py @@ -155,12 +155,12 @@ def construct_graph(cluster, nodes): cluster[max(cluster.keys()) + 1] = "Header" graph = {} for i in x: - if tuple(["Header"]) in graph: - graph[tuple(["Header"])].append(x[i]) + if (["Header"],) in graph: + graph[(["Header"],)].append(x[i]) else: - graph[tuple(["Header"])] = [x[i]] + graph[(["Header"],)] = [x[i]] for i in x: - graph[tuple(x[i])] = [["Header"]] + graph[(x[i],)] = [["Header"]] i = 1 while i < max(cluster) - 1: create_edge(nodes, graph, cluster, i) @@ -186,7 +186,7 @@ def find_freq_subgraph_given_support(s, cluster, graph): """ k = int(s / 100 * (len(cluster) - 1)) for i in cluster[k].keys(): - my_dfs(graph, tuple(cluster[k][i]), tuple(["Header"])) + my_dfs(graph, tuple(cluster[k][i]), (["Header"],)) def freq_subgraphs_edge_list(paths): diff --git a/hashes/enigma_machine.py b/hashes/enigma_machine.py index 0194f7da7..d95437d12 100644 --- a/hashes/enigma_machine.py +++ b/hashes/enigma_machine.py @@ -1,8 +1,8 @@ alphabets = [chr(i) for i in range(32, 126)] -gear_one = [i for i in range(len(alphabets))] -gear_two = [i for i in range(len(alphabets))] -gear_three = [i for i in range(len(alphabets))] -reflector = [i for i in reversed(range(len(alphabets)))] +gear_one = list(range(len(alphabets))) +gear_two = list(range(len(alphabets))) +gear_three = list(range(len(alphabets))) +reflector = list(reversed(range(len(alphabets)))) code = [] gear_one_pos = gear_two_pos = gear_three_pos = 0 diff --git a/maths/primelib.py b/maths/primelib.py index eb72a9f8a..9586227ea 100644 --- a/maths/primelib.py +++ b/maths/primelib.py @@ -89,7 +89,7 @@ def sieve_er(n): assert isinstance(n, int) and (n > 2), "'N' must been an int and > 2" # beginList: contains all natural numbers from 2 up to N - begin_list = [x for x in range(2, n + 1)] + begin_list = list(range(2, n + 1)) ans = [] # this list will be returns. diff --git a/matrix/spiral_print.py b/matrix/spiral_print.py index 2441f05d1..0cf732d60 100644 --- a/matrix/spiral_print.py +++ b/matrix/spiral_print.py @@ -9,7 +9,7 @@ This problem has been solved through recursive way. def check_matrix(matrix: list[list[int]]) -> bool: # must be - matrix = list(list(row) for row in matrix) + matrix = [list(row) for row in matrix] if matrix and isinstance(matrix, list): if isinstance(matrix[0], list): prev_len = 0 @@ -44,7 +44,7 @@ def spiral_print_clockwise(a: list[list[int]]) -> None: 7 """ if check_matrix(a) and len(a) > 0: - a = list(list(row) for row in a) + a = [list(row) for row in a] mat_row = len(a) if isinstance(a[0], list): mat_col = len(a[0]) diff --git a/other/davisb_putnamb_logemannb_loveland.py b/other/davisb_putnamb_logemannb_loveland.py index 3110515d5..a1bea5b39 100644 --- a/other/davisb_putnamb_logemannb_loveland.py +++ b/other/davisb_putnamb_logemannb_loveland.py @@ -317,7 +317,7 @@ def dpll_algorithm( if p: tmp_model = model tmp_model[p] = value - tmp_symbols = [i for i in symbols] + tmp_symbols = list(symbols) if p in tmp_symbols: tmp_symbols.remove(p) return dpll_algorithm(clauses, tmp_symbols, tmp_model) @@ -329,7 +329,7 @@ def dpll_algorithm( if p: tmp_model = model tmp_model[p] = value - tmp_symbols = [i for i in symbols] + tmp_symbols = list(symbols) if p in tmp_symbols: tmp_symbols.remove(p) return dpll_algorithm(clauses, tmp_symbols, tmp_model) diff --git a/project_euler/problem_042/solution42.py b/project_euler/problem_042/solution42.py index 6d22a8dfb..c0fb2ad50 100644 --- a/project_euler/problem_042/solution42.py +++ b/project_euler/problem_042/solution42.py @@ -33,11 +33,11 @@ def solution(): with open(words_file_path) as f: words = f.readline() - words = list(map(lambda word: word.strip('"'), words.strip("\r\n").split(","))) + words = [word.strip('"') for word in words.strip("\r\n").split(",")] words = list( filter( lambda word: word in TRIANGULAR_NUMBERS, - map(lambda word: sum(map(lambda x: ord(x) - 64, word)), words), + (sum(ord(x) - 64 for x in word) for word in words), ) ) return len(words) diff --git a/project_euler/problem_052/sol1.py b/project_euler/problem_052/sol1.py index df5c46ae0..21acfb633 100644 --- a/project_euler/problem_052/sol1.py +++ b/project_euler/problem_052/sol1.py @@ -21,12 +21,12 @@ def solution(): while True: if ( - sorted(list(str(i))) - == sorted(list(str(2 * i))) - == sorted(list(str(3 * i))) - == sorted(list(str(4 * i))) - == sorted(list(str(5 * i))) - == sorted(list(str(6 * i))) + sorted(str(i)) + == sorted(str(2 * i)) + == sorted(str(3 * i)) + == sorted(str(4 * i)) + == sorted(str(5 * i)) + == sorted(str(6 * i)) ): return i diff --git a/project_euler/problem_062/sol1.py b/project_euler/problem_062/sol1.py index 0c9baf880..3efdb3513 100644 --- a/project_euler/problem_062/sol1.py +++ b/project_euler/problem_062/sol1.py @@ -55,7 +55,7 @@ def get_digits(num: int) -> str: >>> get_digits(123) '0166788' """ - return "".join(sorted(list(str(num**3)))) + return "".join(sorted(str(num**3))) if __name__ == "__main__": diff --git a/project_euler/problem_067/sol1.py b/project_euler/problem_067/sol1.py index 527d4dc59..ab305684d 100644 --- a/project_euler/problem_067/sol1.py +++ b/project_euler/problem_067/sol1.py @@ -28,8 +28,8 @@ def solution(): with open(triangle) as f: triangle = f.readlines() - a = map(lambda x: x.rstrip("\r\n").split(" "), triangle) - a = list(map(lambda x: list(map(int, x)), a)) + a = (x.rstrip("\r\n").split(" ") for x in triangle) + a = [list(map(int, x)) for x in a] for i in range(1, len(a)): for j in range(len(a[i])): diff --git a/project_euler/problem_109/sol1.py b/project_euler/problem_109/sol1.py index 91c71eb9f..852f001d3 100644 --- a/project_euler/problem_109/sol1.py +++ b/project_euler/problem_109/sol1.py @@ -65,7 +65,7 @@ def solution(limit: int = 100) -> int: >>> solution(50) 12577 """ - singles: list[int] = [x for x in range(1, 21)] + [25] + singles: list[int] = list(range(1, 21)) + [25] doubles: list[int] = [2 * x for x in range(1, 21)] + [50] triples: list[int] = [3 * x for x in range(1, 21)] all_values: list[int] = singles + doubles + triples + [0] diff --git a/project_euler/problem_551/sol1.py b/project_euler/problem_551/sol1.py index c15445e4d..2cd75efbb 100644 --- a/project_euler/problem_551/sol1.py +++ b/project_euler/problem_551/sol1.py @@ -13,7 +13,7 @@ Find a(10^15) """ -ks = [k for k in range(2, 20 + 1)] +ks = range(2, 20 + 1) base = [10**k for k in range(ks[-1] + 1)] memo: dict[int, dict[int, list[list[int]]]] = {} diff --git a/sorts/radix_sort.py b/sorts/radix_sort.py index afe62bc7e..a496cdc0c 100644 --- a/sorts/radix_sort.py +++ b/sorts/radix_sort.py @@ -24,7 +24,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] = [[] 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/strings/aho_corasick.py b/strings/aho_corasick.py index 2d2f562df..25ed649ce 100644 --- a/strings/aho_corasick.py +++ b/strings/aho_corasick.py @@ -70,9 +70,7 @@ class Automaton: >>> A.search_in("whatever, err ... , wherever") {'what': [0], 'hat': [1], 'ver': [5, 25], 'er': [6, 10, 22, 26]} """ - result: dict = ( - dict() - ) # returns a dict with keywords and list of its occurrences + result: dict = {} # returns a dict with keywords and list of its occurrences current_state = 0 for i in range(len(string)): while ( From 553624fcd4d7e8a4c561b182967291a1cc44ade9 Mon Sep 17 00:00:00 2001 From: Paul <56065602+ZeroDayOwl@users.noreply.github.com> Date: Sat, 15 Oct 2022 23:39:27 +0600 Subject: [PATCH 375/726] Add algorithm for Casimir Effect (#7141) * Add algorithm for Casimir Effect * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix the line length * Fix the line length * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Import math module and use Pi * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update doctest results * from math import pi Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- physics/casimir_effect.py | 121 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 physics/casimir_effect.py diff --git a/physics/casimir_effect.py b/physics/casimir_effect.py new file mode 100644 index 000000000..ee8a6c1eb --- /dev/null +++ b/physics/casimir_effect.py @@ -0,0 +1,121 @@ +""" +Title : Finding the value of magnitude of either the Casimir force, the surface area +of one of the plates or distance between the plates provided that the other +two parameters are given. + +Description : In quantum field theory, the Casimir effect is a physical force +acting on the macroscopic boundaries of a confined space which arises from the +quantum fluctuations of the field. It is a physical force exerted between separate +objects, which is due to neither charge, gravity, nor the exchange of particles, +but instead is due to resonance of all-pervasive energy fields in the intervening +space between the objects. Since the strength of the force falls off rapidly with +distance it is only measurable when the distance between the objects is extremely +small. On a submicron scale, this force becomes so strong that it becomes the +dominant force between uncharged conductors. + +Dutch physicist Hendrik B. G. Casimir first proposed the existence of the force, +and he formulated an experiment to detect it in 1948 while participating in research +at Philips Research Labs. The classic form of his experiment used a pair of uncharged +parallel metal plates in a vacuum, and successfully demonstrated the force to within +15% of the value he had predicted according to his theory. + +The Casimir force F for idealized, perfectly conducting plates of surface area +A square meter and placed at a distance of a meter apart with vacuum between +them is expressed as - + +F = - ((Reduced Planck Constant ℏ) * c * Pi^2 * A) / (240 * a^4) + +Here, the negative sign indicates the force is attractive in nature. For the ease +of calculation, only the magnitude of the force is considered. + +Source : +- https://en.wikipedia.org/wiki/Casimir_effect +- https://www.cs.mcgill.ca/~rwest/wikispeedia/wpcd/wp/c/Casimir_effect.htm +- Casimir, H. B. ; Polder, D. (1948) "The Influence of Retardation on the + London-van der Waals Forces", Physical Review, vol. 73, Issue 4, pp. 360-372 +""" + +from __future__ import annotations + +from math import pi + +# Define the Reduced Planck Constant ℏ (H bar), speed of light C, value of +# Pi and the function +REDUCED_PLANCK_CONSTANT = 1.054571817e-34 # unit of ℏ : J * s + +SPEED_OF_LIGHT = 3e8 # unit of c : m * s^-1 + + +def casimir_force(force: float, area: float, distance: float) -> dict[str, float]: + + """ + Input Parameters + ---------------- + force -> Casimir Force : magnitude in Newtons + + area -> Surface area of each plate : magnitude in square meters + + distance -> Distance between two plates : distance in Meters + + Returns + ------- + result : dict name, value pair of the parameter having Zero as it's value + + Returns the value of one of the parameters specified as 0, provided the values of + other parameters are given. + >>> casimir_force(force = 0, area = 4, distance = 0.03) + {'force': 6.4248189174864216e-21} + + >>> casimir_force(force = 2635e-13, area = 0.0023, distance = 0) + {'distance': 1.0323056015031114e-05} + + >>> casimir_force(force = 2737e-21, area = 0, distance = 0.0023746) + {'area': 0.06688838837354052} + + >>> casimir_force(force = 3457e-12, area = 0, distance = 0) + Traceback (most recent call last): + ... + ValueError: One and only one argument must be 0 + + >>> casimir_force(force = 3457e-12, area = 0, distance = -0.00344) + Traceback (most recent call last): + ... + ValueError: Distance can not be negative + + >>> casimir_force(force = -912e-12, area = 0, distance = 0.09374) + Traceback (most recent call last): + ... + ValueError: Magnitude of force can not be negative + """ + + if (force, area, distance).count(0) != 1: + raise ValueError("One and only one argument must be 0") + if force < 0: + raise ValueError("Magnitude of force can not be negative") + if distance < 0: + raise ValueError("Distance can not be negative") + if area < 0: + raise ValueError("Area can not be negative") + if force == 0: + force = (REDUCED_PLANCK_CONSTANT * SPEED_OF_LIGHT * pi**2 * area) / ( + 240 * (distance) ** 4 + ) + return {"force": force} + elif area == 0: + area = (240 * force * (distance) ** 4) / ( + REDUCED_PLANCK_CONSTANT * SPEED_OF_LIGHT * pi**2 + ) + return {"area": area} + elif distance == 0: + distance = ( + (REDUCED_PLANCK_CONSTANT * SPEED_OF_LIGHT * pi**2 * area) / (240 * force) + ) ** (1 / 4) + return {"distance": distance} + raise ValueError("One and only one argument must be 0") + + +# Run doctest +if __name__ == "__main__": + import doctest + + doctest.testmod() From c94e215c8dbdfe1f349eab5708be6b5f337b6ddd Mon Sep 17 00:00:00 2001 From: Caeden Date: Sat, 15 Oct 2022 23:51:23 +0100 Subject: [PATCH 376/726] types: Update binary search tree typehints (#7197) * types: Update binary search tree typehints * refactor: Don't return `self` in `:meth:insert` * test: Fix failing doctests * Apply suggestions from code review Co-authored-by: Dhruv Manilawala --- .../binary_tree/binary_search_tree.py | 77 +++++++++++-------- 1 file changed, 44 insertions(+), 33 deletions(-) diff --git a/data_structures/binary_tree/binary_search_tree.py b/data_structures/binary_tree/binary_search_tree.py index 51a651be0..fc60540a1 100644 --- a/data_structures/binary_tree/binary_search_tree.py +++ b/data_structures/binary_tree/binary_search_tree.py @@ -2,15 +2,18 @@ A binary search Tree """ +from collections.abc import Iterable +from typing import Any + class Node: - def __init__(self, value, parent): + def __init__(self, value: int | None = None): self.value = value - self.parent = parent # Added in order to delete a node easier - self.left = None - self.right = None + self.parent: Node | None = None # Added in order to delete a node easier + self.left: Node | None = None + self.right: Node | None = None - def __repr__(self): + def __repr__(self) -> str: from pprint import pformat if self.left is None and self.right is None: @@ -19,16 +22,16 @@ class Node: class BinarySearchTree: - def __init__(self, root=None): + def __init__(self, root: Node | None = None): self.root = root - def __str__(self): + def __str__(self) -> str: """ Return a string of all the Nodes using in order traversal """ return str(self.root) - def __reassign_nodes(self, node, new_children): + def __reassign_nodes(self, node: Node, new_children: Node | None) -> None: if new_children is not None: # reset its kids new_children.parent = node.parent if node.parent is not None: # reset its parent @@ -37,23 +40,27 @@ class BinarySearchTree: else: node.parent.left = new_children else: - self.root = new_children + self.root = None - def is_right(self, node): - return node == node.parent.right + def is_right(self, node: Node) -> bool: + if node.parent and node.parent.right: + return node == node.parent.right + return False - def empty(self): + def empty(self) -> bool: return self.root is None - def __insert(self, value): + def __insert(self, value) -> None: """ Insert a new node in Binary Search Tree with value label """ - new_node = Node(value, None) # create a new Node + new_node = Node(value) # create a new Node if self.empty(): # if Tree is empty self.root = new_node # set its root else: # Tree is not empty parent_node = self.root # from root + if parent_node is None: + return None while True: # While we don't get to a leaf if value < parent_node.value: # We go left if parent_node.left is None: @@ -69,12 +76,11 @@ class BinarySearchTree: parent_node = parent_node.right new_node.parent = parent_node - def insert(self, *values): + def insert(self, *values) -> None: for value in values: self.__insert(value) - return self - def search(self, value): + def search(self, value) -> Node | None: if self.empty(): raise IndexError("Warning: Tree is empty! please use another.") else: @@ -84,30 +90,35 @@ class BinarySearchTree: node = node.left if value < node.value else node.right return node - def get_max(self, node=None): + def get_max(self, node: Node | None = None) -> Node | None: """ We go deep on the right branch """ if node is None: + if self.root is None: + return None node = self.root + if not self.empty(): while node.right is not None: node = node.right return node - def get_min(self, node=None): + def get_min(self, node: Node | None = None) -> Node | None: """ We go deep on the left branch """ if node is None: node = self.root + if self.root is None: + return None if not self.empty(): node = self.root while node.left is not None: node = node.left return node - def remove(self, value): + def remove(self, value: int) -> None: node = self.search(value) # Look for the node with that label if node is not None: if node.left is None and node.right is None: # If it has no children @@ -120,18 +131,18 @@ class BinarySearchTree: tmp_node = self.get_max( node.left ) # Gets the max value of the left branch - self.remove(tmp_node.value) + self.remove(tmp_node.value) # type: ignore node.value = ( - tmp_node.value + tmp_node.value # type: ignore ) # Assigns the value to the node to delete and keep tree structure - def preorder_traverse(self, node): + def preorder_traverse(self, node: Node | None) -> Iterable: if node is not None: yield node # Preorder Traversal yield from self.preorder_traverse(node.left) yield from self.preorder_traverse(node.right) - def traversal_tree(self, traversal_function=None): + def traversal_tree(self, traversal_function=None) -> Any: """ This function traversal the tree. You can pass a function to traversal the tree as needed by client code @@ -141,7 +152,7 @@ class BinarySearchTree: else: return traversal_function(self.root) - def inorder(self, arr: list, node: Node): + def inorder(self, arr: list, node: Node | None) -> None: """Perform an inorder traversal and append values of the nodes to a list named arr""" if node: @@ -151,12 +162,12 @@ class BinarySearchTree: def find_kth_smallest(self, k: int, node: Node) -> int: """Return the kth smallest element in a binary search tree""" - arr: list = [] + arr: list[int] = [] self.inorder(arr, node) # append all values to list using inorder traversal return arr[k - 1] -def postorder(curr_node): +def postorder(curr_node: Node | None) -> list[Node]: """ postOrder (left, right, self) """ @@ -166,7 +177,7 @@ def postorder(curr_node): return node_list -def binary_search_tree(): +def binary_search_tree() -> None: r""" Example 8 @@ -177,7 +188,8 @@ def binary_search_tree(): / \ / 4 7 13 - >>> t = BinarySearchTree().insert(8, 3, 6, 1, 10, 14, 13, 4, 7) + >>> t = BinarySearchTree() + >>> t.insert(8, 3, 6, 1, 10, 14, 13, 4, 7) >>> print(" ".join(repr(i.value) for i in t.traversal_tree())) 8 3 1 6 4 7 10 14 13 >>> print(" ".join(repr(i.value) for i in t.traversal_tree(postorder))) @@ -206,8 +218,8 @@ def binary_search_tree(): print("The value -1 doesn't exist") if not t.empty(): - print("Max Value: ", t.get_max().value) - print("Min Value: ", t.get_min().value) + print("Max Value: ", t.get_max().value) # type: ignore + print("Min Value: ", t.get_min().value) # type: ignore for i in testlist: t.remove(i) @@ -217,5 +229,4 @@ def binary_search_tree(): if __name__ == "__main__": import doctest - doctest.testmod() - # binary_search_tree() + doctest.testmod(verbose=True) From 04698538d816fc5f70c850e8b89c6d1f5599fa84 Mon Sep 17 00:00:00 2001 From: CenTdemeern1 Date: Sat, 15 Oct 2022 22:25:38 -0700 Subject: [PATCH 377/726] Misc fixes across multiple algorithms (#6912) Source: Snyk code quality Add scikit-fuzzy to requirements Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Dhruv Manilawala --- compression/huffman.py | 2 +- data_structures/linked_list/is_palindrome.py | 2 +- .../filters/local_binary_pattern.py | 2 +- fuzzy_logic/fuzzy_operations.py | 6 +----- graphs/dijkstra_algorithm.py | 4 ++-- .../directed_and_undirected_(weighted)_graph.py | 7 ------- hashes/hamming_code.py | 3 +-- linear_algebra/src/test_linear_algebra.py | 2 +- maths/extended_euclidean_algorithm.py | 5 +++-- maths/jaccard_similarity.py | 15 ++++++++------- matrix/matrix_class.py | 2 +- project_euler/problem_001/sol7.py | 4 +--- project_euler/problem_042/solution42.py | 11 +++++------ project_euler/problem_067/sol1.py | 8 ++++++-- project_euler/problem_089/sol1.py | 5 +++-- requirements.txt | 2 +- scheduling/first_come_first_served.py | 4 ++-- scheduling/multi_level_feedback_queue.py | 2 +- web_programming/emails_from_url.py | 2 +- 19 files changed, 40 insertions(+), 48 deletions(-) diff --git a/compression/huffman.py b/compression/huffman.py index d5d78b753..f619ed82c 100644 --- a/compression/huffman.py +++ b/compression/huffman.py @@ -31,7 +31,7 @@ def parse_file(file_path: str) -> list[Letter]: c = f.read(1) if not c: break - chars[c] = chars[c] + 1 if c in chars.keys() else 1 + chars[c] = chars[c] + 1 if c in chars else 1 return sorted((Letter(c, f) for c, f in chars.items()), key=lambda l: l.freq) diff --git a/data_structures/linked_list/is_palindrome.py b/data_structures/linked_list/is_palindrome.py index acc87c1c2..ec19e99f7 100644 --- a/data_structures/linked_list/is_palindrome.py +++ b/data_structures/linked_list/is_palindrome.py @@ -55,7 +55,7 @@ def is_palindrome_dict(head): d = {} pos = 0 while head: - if head.val in d.keys(): + if head.val in d: d[head.val].append(pos) else: d[head.val] = [pos] diff --git a/digital_image_processing/filters/local_binary_pattern.py b/digital_image_processing/filters/local_binary_pattern.py index e73aa59bf..e92e554a3 100644 --- a/digital_image_processing/filters/local_binary_pattern.py +++ b/digital_image_processing/filters/local_binary_pattern.py @@ -60,7 +60,7 @@ def local_binary_value(image: np.ndarray, x_coordinate: int, y_coordinate: int) ) -if __name__ == "main": +if __name__ == "__main__": # Reading the image and converting it to grayscale. image = cv2.imread( diff --git a/fuzzy_logic/fuzzy_operations.py b/fuzzy_logic/fuzzy_operations.py index fbaca9421..0786ef8b0 100644 --- a/fuzzy_logic/fuzzy_operations.py +++ b/fuzzy_logic/fuzzy_operations.py @@ -8,11 +8,7 @@ Python: - 3.5 """ import numpy as np - -try: - import skfuzzy as fuzz -except ImportError: - fuzz = None +import skfuzzy as fuzz if __name__ == "__main__": # Create universe of discourse in Python using linspace () diff --git a/graphs/dijkstra_algorithm.py b/graphs/dijkstra_algorithm.py index 122821a37..1845dad05 100644 --- a/graphs/dijkstra_algorithm.py +++ b/graphs/dijkstra_algorithm.py @@ -89,13 +89,13 @@ class Graph: # Edge going from node u to v and v to u with weight w # u (w)-> v, v (w) -> u # Check if u already in graph - if u in self.adjList.keys(): + if u in self.adjList: self.adjList[u].append((v, w)) else: self.adjList[u] = [(v, w)] # Assuming undirected graph - if v in self.adjList.keys(): + if v in self.adjList: self.adjList[v].append((u, w)) else: self.adjList[v] = [(u, w)] diff --git a/graphs/directed_and_undirected_(weighted)_graph.py b/graphs/directed_and_undirected_(weighted)_graph.py index 5cfa9e13e..43a72b89e 100644 --- a/graphs/directed_and_undirected_(weighted)_graph.py +++ b/graphs/directed_and_undirected_(weighted)_graph.py @@ -226,9 +226,6 @@ class DirectedGraph: break else: return True - # TODO:The following code is unreachable. - anticipating_nodes.add(stack[len_stack_minus_one]) - len_stack_minus_one -= 1 if visited.count(node[1]) < 1: stack.append(node[1]) visited.append(node[1]) @@ -454,10 +451,6 @@ class Graph: break else: return True - # TODO: the following code is unreachable - # is this meant to be called in the else ? - anticipating_nodes.add(stack[len_stack_minus_one]) - len_stack_minus_one -= 1 if visited.count(node[1]) < 1: stack.append(node[1]) visited.append(node[1]) diff --git a/hashes/hamming_code.py b/hashes/hamming_code.py index a62d092a1..481a67507 100644 --- a/hashes/hamming_code.py +++ b/hashes/hamming_code.py @@ -79,8 +79,7 @@ def emitter_converter(size_par, data): ['1', '1', '1', '1', '0', '1', '0', '0', '1', '0', '1', '1', '1', '1', '1', '1'] """ if size_par + len(data) <= 2**size_par - (len(data) - 1): - print("ERROR - size of parity don't match with size of data") - exit(0) + raise ValueError("size of parity don't match with size of data") data_out = [] parity = [] diff --git a/linear_algebra/src/test_linear_algebra.py b/linear_algebra/src/test_linear_algebra.py index 97c06cb44..50d079572 100644 --- a/linear_algebra/src/test_linear_algebra.py +++ b/linear_algebra/src/test_linear_algebra.py @@ -89,7 +89,7 @@ class Test(unittest.TestCase): """ test for global function zero_vector() """ - self.assertTrue(str(zero_vector(10)).count("0") == 10) + self.assertEqual(str(zero_vector(10)).count("0"), 10) def test_unit_basis_vector(self) -> None: """ diff --git a/maths/extended_euclidean_algorithm.py b/maths/extended_euclidean_algorithm.py index 72afd40aa..c54909e19 100644 --- a/maths/extended_euclidean_algorithm.py +++ b/maths/extended_euclidean_algorithm.py @@ -75,11 +75,12 @@ def main(): """Call Extended Euclidean Algorithm.""" if len(sys.argv) < 3: print("2 integer arguments required") - exit(1) + return 1 a = int(sys.argv[1]) b = int(sys.argv[2]) print(extended_euclidean_algorithm(a, b)) + return 0 if __name__ == "__main__": - main() + raise SystemExit(main()) diff --git a/maths/jaccard_similarity.py b/maths/jaccard_similarity.py index 77f4b90ea..b299a8147 100644 --- a/maths/jaccard_similarity.py +++ b/maths/jaccard_similarity.py @@ -14,7 +14,7 @@ Jaccard similarity is widely used with MinHashing. """ -def jaccard_similariy(set_a, set_b, alternative_union=False): +def jaccard_similarity(set_a, set_b, alternative_union=False): """ Finds the jaccard similarity between two sets. Essentially, its intersection over union. @@ -35,18 +35,18 @@ def jaccard_similariy(set_a, set_b, alternative_union=False): Examples: >>> set_a = {'a', 'b', 'c', 'd', 'e'} >>> set_b = {'c', 'd', 'e', 'f', 'h', 'i'} - >>> jaccard_similariy(set_a, set_b) + >>> jaccard_similarity(set_a, set_b) 0.375 - >>> jaccard_similariy(set_a, set_a) + >>> jaccard_similarity(set_a, set_a) 1.0 - >>> jaccard_similariy(set_a, set_a, True) + >>> jaccard_similarity(set_a, set_a, True) 0.5 >>> set_a = ['a', 'b', 'c', 'd', 'e'] >>> set_b = ('c', 'd', 'e', 'f', 'h', 'i') - >>> jaccard_similariy(set_a, set_b) + >>> jaccard_similarity(set_a, set_b) 0.375 """ @@ -67,14 +67,15 @@ def jaccard_similariy(set_a, set_b, alternative_union=False): if alternative_union: union = len(set_a) + len(set_b) + return len(intersection) / union else: union = set_a + [element for element in set_b if element not in set_a] + return len(intersection) / len(union) return len(intersection) / len(union) if __name__ == "__main__": - set_a = {"a", "b", "c", "d", "e"} set_b = {"c", "d", "e", "f", "h", "i"} - print(jaccard_similariy(set_a, set_b)) + print(jaccard_similarity(set_a, set_b)) diff --git a/matrix/matrix_class.py b/matrix/matrix_class.py index 6495bd8fc..8b6fefa21 100644 --- a/matrix/matrix_class.py +++ b/matrix/matrix_class.py @@ -286,7 +286,7 @@ class Matrix: # MATRIX OPERATIONS def __eq__(self, other: object) -> bool: if not isinstance(other, Matrix): - raise TypeError("A Matrix can only be compared with another Matrix") + return NotImplemented return self.rows == other.rows def __ne__(self, other: object) -> bool: diff --git a/project_euler/problem_001/sol7.py b/project_euler/problem_001/sol7.py index 8f5d1977f..6ada70c12 100644 --- a/project_euler/problem_001/sol7.py +++ b/project_euler/problem_001/sol7.py @@ -26,9 +26,7 @@ def solution(n: int = 1000) -> int: result = 0 for i in range(n): - if i % 3 == 0: - result += i - elif i % 5 == 0: + if i % 3 == 0 or i % 5 == 0: result += i return result diff --git a/project_euler/problem_042/solution42.py b/project_euler/problem_042/solution42.py index c0fb2ad50..f8a54e40e 100644 --- a/project_euler/problem_042/solution42.py +++ b/project_euler/problem_042/solution42.py @@ -34,12 +34,11 @@ def solution(): words = f.readline() words = [word.strip('"') for word in words.strip("\r\n").split(",")] - words = list( - filter( - lambda word: word in TRIANGULAR_NUMBERS, - (sum(ord(x) - 64 for x in word) for word in words), - ) - ) + words = [ + word + for word in [sum(ord(x) - 64 for x in word) for word in words] + if word in TRIANGULAR_NUMBERS + ] return len(words) diff --git a/project_euler/problem_067/sol1.py b/project_euler/problem_067/sol1.py index ab305684d..f20c206cc 100644 --- a/project_euler/problem_067/sol1.py +++ b/project_euler/problem_067/sol1.py @@ -28,8 +28,12 @@ def solution(): with open(triangle) as f: triangle = f.readlines() - a = (x.rstrip("\r\n").split(" ") for x in triangle) - a = [list(map(int, x)) for x in a] + a = [] + for line in triangle: + numbers_from_line = [] + for number in line.strip().split(" "): + numbers_from_line.append(int(number)) + a.append(numbers_from_line) for i in range(1, len(a)): for j in range(len(a[i])): diff --git a/project_euler/problem_089/sol1.py b/project_euler/problem_089/sol1.py index 1c4e2600f..83609cd23 100644 --- a/project_euler/problem_089/sol1.py +++ b/project_euler/problem_089/sol1.py @@ -125,8 +125,9 @@ def solution(roman_numerals_filename: str = "/p089_roman.txt") -> int: savings = 0 - file1 = open(os.path.dirname(__file__) + roman_numerals_filename) - lines = file1.readlines() + with open(os.path.dirname(__file__) + roman_numerals_filename) as file1: + lines = file1.readlines() + for line in lines: original = line.strip() num = parse_roman_numerals(original) diff --git a/requirements.txt b/requirements.txt index 0fbc1cc4b..b14a3eb01 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,7 +9,7 @@ pandas pillow qiskit requests -# scikit-fuzzy # Causing broken builds +scikit-fuzzy sklearn statsmodels sympy diff --git a/scheduling/first_come_first_served.py b/scheduling/first_come_first_served.py index c5f61720f..06cdb8ddf 100644 --- a/scheduling/first_come_first_served.py +++ b/scheduling/first_come_first_served.py @@ -79,7 +79,7 @@ if __name__ == "__main__": # ensure that we actually have processes if len(processes) == 0: print("Zero amount of processes") - exit() + raise SystemExit(0) # duration time of all processes duration_times = [19, 8, 9] @@ -87,7 +87,7 @@ if __name__ == "__main__": # ensure we can match each id to a duration time if len(duration_times) != len(processes): print("Unable to match all id's with their duration time") - exit() + raise SystemExit(0) # get the waiting times and the turnaround times waiting_times = calculate_waiting_times(duration_times) diff --git a/scheduling/multi_level_feedback_queue.py b/scheduling/multi_level_feedback_queue.py index a3ba1b340..abee3c85c 100644 --- a/scheduling/multi_level_feedback_queue.py +++ b/scheduling/multi_level_feedback_queue.py @@ -276,7 +276,7 @@ if __name__ == "__main__": queue = deque([P1, P2, P3, P4]) if len(time_slices) != number_of_queues - 1: - exit() + raise SystemExit(0) doctest.testmod(extraglobs={"queue": deque([P1, P2, P3, P4])}) diff --git a/web_programming/emails_from_url.py b/web_programming/emails_from_url.py index afaee5bbe..074ef878c 100644 --- a/web_programming/emails_from_url.py +++ b/web_programming/emails_from_url.py @@ -93,7 +93,7 @@ def emails_from_url(url: str = "https://github.com") -> list[str]: except ValueError: pass except ValueError: - exit(-1) + raise SystemExit(1) # Finally return a sorted list of email addresses with no duplicates. return sorted(valid_emails) From e7b6d2824a65985790d0044262f717898ffbeb4d Mon Sep 17 00:00:00 2001 From: Sagar Giri Date: Sun, 16 Oct 2022 16:43:29 +0900 Subject: [PATCH 378/726] Change to https. (#7277) * Change to https. * Revert the py_tf file. --- fractals/julia_sets.py | 2 +- fractals/sierpinski_triangle.py | 2 +- machine_learning/lstm/lstm_prediction.py | 2 +- machine_learning/sequential_minimum_optimization.py | 4 ++-- maths/matrix_exponentiation.py | 2 +- maths/test_prime_check.py | 2 +- physics/n_body_simulation.py | 4 ++-- strings/frequency_finder.py | 2 +- web_programming/crawl_google_results.py | 2 +- web_programming/crawl_google_scholar_citation.py | 2 +- web_programming/current_weather.py | 2 +- web_programming/giphy.py | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/fractals/julia_sets.py b/fractals/julia_sets.py index 28c675c75..35fdc45d0 100644 --- a/fractals/julia_sets.py +++ b/fractals/julia_sets.py @@ -12,7 +12,7 @@ The examples presented here are: https://en.wikipedia.org/wiki/File:Julia_z2%2B0,25.png - Other examples from https://en.wikipedia.org/wiki/Julia_set - An exponential map Julia set, ambiantly homeomorphic to the examples in -http://www.math.univ-toulouse.fr/~cheritat/GalII/galery.html +https://www.math.univ-toulouse.fr/~cheritat/GalII/galery.html and https://ddd.uab.cat/pub/pubmat/02141493v43n1/02141493v43n1p27.pdf diff --git a/fractals/sierpinski_triangle.py b/fractals/sierpinski_triangle.py index 8be2897c1..084f6661f 100644 --- a/fractals/sierpinski_triangle.py +++ b/fractals/sierpinski_triangle.py @@ -24,7 +24,7 @@ Usage: - $python sierpinski_triangle.py Credits: This code was written by editing the code from -http://www.riannetrujillo.com/blog/python-fractal/ +https://www.riannetrujillo.com/blog/python-fractal/ """ import sys diff --git a/machine_learning/lstm/lstm_prediction.py b/machine_learning/lstm/lstm_prediction.py index 6fd3cf291..74197c46a 100644 --- a/machine_learning/lstm/lstm_prediction.py +++ b/machine_learning/lstm/lstm_prediction.py @@ -1,7 +1,7 @@ """ Create a Long Short Term Memory (LSTM) network model An LSTM is a type of Recurrent Neural Network (RNN) as discussed at: - * http://colah.github.io/posts/2015-08-Understanding-LSTMs + * https://colah.github.io/posts/2015-08-Understanding-LSTMs * https://en.wikipedia.org/wiki/Long_short-term_memory """ import numpy as np diff --git a/machine_learning/sequential_minimum_optimization.py b/machine_learning/sequential_minimum_optimization.py index fb4b35f31..40adca7e0 100644 --- a/machine_learning/sequential_minimum_optimization.py +++ b/machine_learning/sequential_minimum_optimization.py @@ -28,7 +28,7 @@ Usage: Reference: https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/smo-book.pdf https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/tr-98-14.pdf - http://web.cs.iastate.edu/~honavar/smo-svm.pdf + https://web.cs.iastate.edu/~honavar/smo-svm.pdf """ @@ -43,7 +43,7 @@ from sklearn.datasets import make_blobs, make_circles from sklearn.preprocessing import StandardScaler CANCER_DATASET_URL = ( - "http://archive.ics.uci.edu/ml/machine-learning-databases/" + "https://archive.ics.uci.edu/ml/machine-learning-databases/" "breast-cancer-wisconsin/wdbc.data" ) diff --git a/maths/matrix_exponentiation.py b/maths/matrix_exponentiation.py index 033ceb3f2..7c37151c8 100644 --- a/maths/matrix_exponentiation.py +++ b/maths/matrix_exponentiation.py @@ -5,7 +5,7 @@ import timeit """ Matrix Exponentiation is a technique to solve linear recurrences in logarithmic time. You read more about it here: -http://zobayer.blogspot.com/2010/11/matrix-exponentiation.html +https://zobayer.blogspot.com/2010/11/matrix-exponentiation.html https://www.hackerearth.com/practice/notes/matrix-exponentiation-1/ """ diff --git a/maths/test_prime_check.py b/maths/test_prime_check.py index b6389684a..3ea3b2f1f 100644 --- a/maths/test_prime_check.py +++ b/maths/test_prime_check.py @@ -1,6 +1,6 @@ """ Minimalist file that allows pytest to find and run the Test unittest. For details, see: -http://doc.pytest.org/en/latest/goodpractices.html#conventions-for-python-test-discovery +https://doc.pytest.org/en/latest/goodpractices.html#conventions-for-python-test-discovery """ from .prime_check import Test diff --git a/physics/n_body_simulation.py b/physics/n_body_simulation.py index 2f8153782..e62e1de62 100644 --- a/physics/n_body_simulation.py +++ b/physics/n_body_simulation.py @@ -8,7 +8,7 @@ velocity and position brought about by these forces. Softening is used to preven numerical divergences when a particle comes too close to another (and the force goes to infinity). (Description adapted from https://en.wikipedia.org/wiki/N-body_simulation ) -(See also http://www.shodor.org/refdesk/Resources/Algorithms/EulersMethod/ ) +(See also https://www.shodor.org/refdesk/Resources/Algorithms/EulersMethod/ ) """ @@ -258,7 +258,7 @@ def example_1() -> BodySystem: Example 1: figure-8 solution to the 3-body-problem This example can be seen as a test of the implementation: given the right initial conditions, the bodies should move in a figure-8. - (initial conditions taken from http://www.artcompsci.org/vol_1/v1_web/node56.html) + (initial conditions taken from https://www.artcompsci.org/vol_1/v1_web/node56.html) >>> body_system = example_1() >>> len(body_system) 3 diff --git a/strings/frequency_finder.py b/strings/frequency_finder.py index 7024be17b..19f97afbb 100644 --- a/strings/frequency_finder.py +++ b/strings/frequency_finder.py @@ -2,7 +2,7 @@ import string -# frequency taken from http://en.wikipedia.org/wiki/Letter_frequency +# frequency taken from https://en.wikipedia.org/wiki/Letter_frequency english_letter_freq = { "E": 12.70, "T": 9.06, diff --git a/web_programming/crawl_google_results.py b/web_programming/crawl_google_results.py index a33a3f3bb..1f5e6d319 100644 --- a/web_programming/crawl_google_results.py +++ b/web_programming/crawl_google_results.py @@ -21,4 +21,4 @@ if __name__ == "__main__": if link.text == "Maps": webbrowser.open(link.get("href")) else: - webbrowser.open(f"http://google.com{link.get('href')}") + webbrowser.open(f"https://google.com{link.get('href')}") diff --git a/web_programming/crawl_google_scholar_citation.py b/web_programming/crawl_google_scholar_citation.py index d023380c0..f92a3d139 100644 --- a/web_programming/crawl_google_scholar_citation.py +++ b/web_programming/crawl_google_scholar_citation.py @@ -29,4 +29,4 @@ if __name__ == "__main__": "year": 2018, "hl": "en", } - print(get_citation("http://scholar.google.com/scholar_lookup", params=params)) + print(get_citation("https://scholar.google.com/scholar_lookup", params=params)) diff --git a/web_programming/current_weather.py b/web_programming/current_weather.py index e043b4384..3ed4c8a95 100644 --- a/web_programming/current_weather.py +++ b/web_programming/current_weather.py @@ -1,7 +1,7 @@ import requests APPID = "" # <-- Put your OpenWeatherMap appid here! -URL_BASE = "http://api.openweathermap.org/data/2.5/" +URL_BASE = "https://api.openweathermap.org/data/2.5/" def current_weather(q: str = "Chicago", appid: str = APPID) -> dict: diff --git a/web_programming/giphy.py b/web_programming/giphy.py index dc8c6be08..a5c3f8f74 100644 --- a/web_programming/giphy.py +++ b/web_programming/giphy.py @@ -10,7 +10,7 @@ def get_gifs(query: str, api_key: str = giphy_api_key) -> list: Get a list of URLs of GIFs based on a given query.. """ formatted_query = "+".join(query.split()) - url = f"http://api.giphy.com/v1/gifs/search?q={formatted_query}&api_key={api_key}" + url = f"https://api.giphy.com/v1/gifs/search?q={formatted_query}&api_key={api_key}" gifs = requests.get(url).json()["data"] return [gif["url"] for gif in gifs] From 77764116217708933bdc65b29801092fa291398e Mon Sep 17 00:00:00 2001 From: Kevin Joven <59969678+KevinJoven11@users.noreply.github.com> Date: Sun, 16 Oct 2022 02:47:54 -0500 Subject: [PATCH 379/726] Create q_full_adder.py (#6735) * Create q_full_adder.py This is for the #Hacktoberfest. This circuit is the quantum full adder. I saw that in the repo is the half adder so I decided to build the full adder to complete the set of adders. I hope that this is enough to be consider a contribution. Best, Kevin * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Erase the unused numpy library * Create the doctest. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * doctest for negative numbers, float, etc. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- quantum/q_full_adder.py | 112 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 quantum/q_full_adder.py diff --git a/quantum/q_full_adder.py b/quantum/q_full_adder.py new file mode 100644 index 000000000..597efb834 --- /dev/null +++ b/quantum/q_full_adder.py @@ -0,0 +1,112 @@ +""" +Build the quantum full adder (QFA) for any sum of +two quantum registers and one carry in. This circuit +is designed using the Qiskit framework. This +experiment run in IBM Q simulator with 1000 shots. +. +References: +https://www.quantum-inspire.com/kbase/full-adder/ +""" + +import math + +import qiskit +from qiskit import Aer, ClassicalRegister, QuantumCircuit, QuantumRegister, execute + + +def quantum_full_adder( + input_1: int = 1, input_2: int = 1, carry_in: int = 1 +) -> qiskit.result.counts.Counts: + """ + # >>> q_full_adder(inp_1, inp_2, cin) + # the inputs can be 0/1 for qubits in define + # values, or can be in a superposition of both + # states with hadamard gate using the input value 2. + # result for default values: {11: 1000} + qr_0: ──■────■──────────────■── + │ ┌─┴─┐ ┌─┴─┐ + qr_1: ──■──┤ X ├──■────■──┤ X ├ + │ └───┘ │ ┌─┴─┐└───┘ + qr_2: ──┼─────────■──┤ X ├───── + ┌─┴─┐ ┌─┴─┐└───┘ + qr_3: ┤ X ├─────┤ X ├────────── + └───┘ └───┘ + cr: 2/═════════════════════════ + Args: + input_1: input 1 for the circuit. + input_2: input 2 for the circuit. + carry_in: carry in for the circuit. + Returns: + qiskit.result.counts.Counts: sum result counts. + >>> quantum_full_adder(1,1,1) + {'11': 1000} + >>> quantum_full_adder(0,0,1) + {'01': 1000} + >>> quantum_full_adder(1,0,1) + {'10': 1000} + >>> quantum_full_adder(1,-4,1) + Traceback (most recent call last): + ... + ValueError: inputs must be positive. + >>> quantum_full_adder('q',0,1) + Traceback (most recent call last): + ... + TypeError: inputs must be integers. + >>> quantum_full_adder(0.5,0,1) + Traceback (most recent call last): + ... + ValueError: inputs must be exact integers. + >>> quantum_full_adder(0,1,3) + Traceback (most recent call last): + ... + ValueError: inputs must be less or equal to 2. + """ + if (type(input_1) == str) or (type(input_2) == str) or (type(carry_in) == str): + raise TypeError("inputs must be integers.") + + if (input_1 < 0) or (input_2 < 0) or (carry_in < 0): + raise ValueError("inputs must be positive.") + + if ( + (math.floor(input_1) != input_1) + or (math.floor(input_2) != input_2) + or (math.floor(carry_in) != carry_in) + ): + raise ValueError("inputs must be exact integers.") + + if (input_1 > 2) or (input_2 > 2) or (carry_in > 2): + raise ValueError("inputs must be less or equal to 2.") + + # build registers + qr = QuantumRegister(4, "qr") + cr = ClassicalRegister(2, "cr") + # list the entries + entry = [input_1, input_2, carry_in] + + quantum_circuit = QuantumCircuit(qr, cr) + + for i in range(0, 3): + if entry[i] == 2: + quantum_circuit.h(i) # for hadamard entries + elif entry[i] == 1: + quantum_circuit.x(i) # for 1 entries + elif entry[i] == 0: + quantum_circuit.i(i) # for 0 entries + + # build the circuit + quantum_circuit.ccx(0, 1, 3) # ccx = toffoli gate + quantum_circuit.cx(0, 1) + quantum_circuit.ccx(1, 2, 3) + quantum_circuit.cx(1, 2) + quantum_circuit.cx(0, 1) + + quantum_circuit.measure([2, 3], cr) # measure the last two qbits + + backend = Aer.get_backend("qasm_simulator") + job = execute(quantum_circuit, backend, shots=1000) + + return job.result().get_counts(quantum_circuit) + + +if __name__ == "__main__": + print(f"Total sum count for state is: {quantum_full_adder(1,1,1)}") From c6582b35bf8b8aba622c63096e3ab2f01aa36854 Mon Sep 17 00:00:00 2001 From: Caeden Date: Sun, 16 Oct 2022 10:33:29 +0100 Subject: [PATCH 380/726] refactor: Move constants outside of variable scope (#7262) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Dhruv Manilawala Co-authored-by: Christian Clauss --- ciphers/bifid.py | 15 ++++---- ciphers/brute_force_caesar_cipher.py | 14 ++++--- ciphers/polybius.py | 16 ++++---- compression/peak_signal_to_noise_ratio.py | 13 ++++--- conversions/binary_to_hexadecimal.py | 39 ++++++++++---------- conversions/decimal_to_any.py | 11 ++---- conversions/roman_numerals.py | 32 ++++++++-------- geodesy/haversine_distance.py | 7 ++-- geodesy/lamberts_ellipsoidal_distance.py | 8 ++-- hashes/adler32.py | 3 +- physics/n_body_simulation.py | 12 +++--- project_euler/problem_054/test_poker_hand.py | 6 +-- project_euler/problem_064/sol1.py | 8 ++-- project_euler/problem_097/sol1.py | 6 +-- project_euler/problem_125/sol1.py | 3 +- sorts/radix_sort.py | 3 +- web_programming/fetch_quotes.py | 8 ++-- 17 files changed, 107 insertions(+), 97 deletions(-) diff --git a/ciphers/bifid.py b/ciphers/bifid.py index 54d55574c..c005e051a 100644 --- a/ciphers/bifid.py +++ b/ciphers/bifid.py @@ -9,16 +9,17 @@ https://www.braingle.com/brainteasers/codes/bifid.php import numpy as np +SQUARE = [ + ["a", "b", "c", "d", "e"], + ["f", "g", "h", "i", "k"], + ["l", "m", "n", "o", "p"], + ["q", "r", "s", "t", "u"], + ["v", "w", "x", "y", "z"], +] + class BifidCipher: def __init__(self) -> None: - SQUARE = [ # noqa: N806 - ["a", "b", "c", "d", "e"], - ["f", "g", "h", "i", "k"], - ["l", "m", "n", "o", "p"], - ["q", "r", "s", "t", "u"], - ["v", "w", "x", "y", "z"], - ] self.SQUARE = np.array(SQUARE) def letter_to_numbers(self, letter: str) -> np.ndarray: diff --git a/ciphers/brute_force_caesar_cipher.py b/ciphers/brute_force_caesar_cipher.py index cc97111e0..458d08db2 100644 --- a/ciphers/brute_force_caesar_cipher.py +++ b/ciphers/brute_force_caesar_cipher.py @@ -1,3 +1,6 @@ +import string + + def decrypt(message: str) -> None: """ >>> decrypt('TMDETUX PMDVU') @@ -28,16 +31,15 @@ def decrypt(message: str) -> None: Decryption using Key #24: VOFGVWZ ROFXW Decryption using Key #25: UNEFUVY QNEWV """ - LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" # noqa: N806 - for key in range(len(LETTERS)): + for key in range(len(string.ascii_uppercase)): translated = "" for symbol in message: - if symbol in LETTERS: - num = LETTERS.find(symbol) + if symbol in string.ascii_uppercase: + num = string.ascii_uppercase.find(symbol) num = num - key if num < 0: - num = num + len(LETTERS) - translated = translated + LETTERS[num] + num = num + len(string.ascii_uppercase) + translated = translated + string.ascii_uppercase[num] else: translated = translated + symbol print(f"Decryption using Key #{key}: {translated}") diff --git a/ciphers/polybius.py b/ciphers/polybius.py index bf5d62f8d..c81c1d395 100644 --- a/ciphers/polybius.py +++ b/ciphers/polybius.py @@ -8,16 +8,18 @@ https://www.braingle.com/brainteasers/codes/polybius.php import numpy as np +SQUARE = [ + ["a", "b", "c", "d", "e"], + ["f", "g", "h", "i", "k"], + ["l", "m", "n", "o", "p"], + ["q", "r", "s", "t", "u"], + ["v", "w", "x", "y", "z"], +] + class PolybiusCipher: def __init__(self) -> None: - SQUARE = [ # noqa: N806 - ["a", "b", "c", "d", "e"], - ["f", "g", "h", "i", "k"], - ["l", "m", "n", "o", "p"], - ["q", "r", "s", "t", "u"], - ["v", "w", "x", "y", "z"], - ] + self.SQUARE = np.array(SQUARE) def letter_to_numbers(self, letter: str) -> np.ndarray: diff --git a/compression/peak_signal_to_noise_ratio.py b/compression/peak_signal_to_noise_ratio.py index 66b18b50b..284f2904a 100644 --- a/compression/peak_signal_to_noise_ratio.py +++ b/compression/peak_signal_to_noise_ratio.py @@ -11,14 +11,15 @@ import os import cv2 import numpy as np +PIXEL_MAX = 255.0 -def psnr(original: float, contrast: float) -> float: + +def peak_signal_to_noise_ratio(original: float, contrast: float) -> float: mse = np.mean((original - contrast) ** 2) if mse == 0: return 100 - PIXEL_MAX = 255.0 # noqa: N806 - PSNR = 20 * math.log10(PIXEL_MAX / math.sqrt(mse)) # noqa: N806 - return PSNR + + return 20 * math.log10(PIXEL_MAX / math.sqrt(mse)) def main() -> None: @@ -34,11 +35,11 @@ def main() -> None: # Value expected: 29.73dB print("-- First Test --") - print(f"PSNR value is {psnr(original, contrast)} dB") + print(f"PSNR value is {peak_signal_to_noise_ratio(original, contrast)} dB") # # Value expected: 31.53dB (Wikipedia Example) print("\n-- Second Test --") - print(f"PSNR value is {psnr(original2, contrast2)} dB") + print(f"PSNR value is {peak_signal_to_noise_ratio(original2, contrast2)} dB") if __name__ == "__main__": diff --git a/conversions/binary_to_hexadecimal.py b/conversions/binary_to_hexadecimal.py index 61f335a4c..89f7af696 100644 --- a/conversions/binary_to_hexadecimal.py +++ b/conversions/binary_to_hexadecimal.py @@ -1,3 +1,23 @@ +BITS_TO_HEX = { + "0000": "0", + "0001": "1", + "0010": "2", + "0011": "3", + "0100": "4", + "0101": "5", + "0110": "6", + "0111": "7", + "1000": "8", + "1001": "9", + "1010": "a", + "1011": "b", + "1100": "c", + "1101": "d", + "1110": "e", + "1111": "f", +} + + def bin_to_hexadecimal(binary_str: str) -> str: """ Converting a binary string into hexadecimal using Grouping Method @@ -17,25 +37,6 @@ def bin_to_hexadecimal(binary_str: str) -> str: ... ValueError: Empty string was passed to the function """ - BITS_TO_HEX = { # noqa: N806 - "0000": "0", - "0001": "1", - "0010": "2", - "0011": "3", - "0100": "4", - "0101": "5", - "0110": "6", - "0111": "7", - "1000": "8", - "1001": "9", - "1010": "a", - "1011": "b", - "1100": "c", - "1101": "d", - "1110": "e", - "1111": "f", - } - # Sanitising parameter binary_str = str(binary_str).strip() diff --git a/conversions/decimal_to_any.py b/conversions/decimal_to_any.py index e54fa154a..908c89e8f 100644 --- a/conversions/decimal_to_any.py +++ b/conversions/decimal_to_any.py @@ -1,5 +1,9 @@ """Convert a positive Decimal Number to Any Other Representation""" +from string import ascii_uppercase + +ALPHABET_VALUES = {str(ord(c) - 55): c for c in ascii_uppercase} + def decimal_to_any(num: int, base: int) -> str: """ @@ -65,13 +69,6 @@ def decimal_to_any(num: int, base: int) -> str: raise ValueError("base must be >= 2") if base > 36: raise ValueError("base must be <= 36") - # fmt: off - ALPHABET_VALUES = {'10': 'A', '11': 'B', '12': 'C', '13': 'D', '14': 'E', '15': 'F', # noqa: N806, E501 - '16': 'G', '17': 'H', '18': 'I', '19': 'J', '20': 'K', '21': 'L', - '22': 'M', '23': 'N', '24': 'O', '25': 'P', '26': 'Q', '27': 'R', - '28': 'S', '29': 'T', '30': 'U', '31': 'V', '32': 'W', '33': 'X', - '34': 'Y', '35': 'Z'} - # fmt: on new_value = "" mod = 0 div = 0 diff --git a/conversions/roman_numerals.py b/conversions/roman_numerals.py index 960d41342..61215a0c0 100644 --- a/conversions/roman_numerals.py +++ b/conversions/roman_numerals.py @@ -1,3 +1,20 @@ +ROMAN = [ + (1000, "M"), + (900, "CM"), + (500, "D"), + (400, "CD"), + (100, "C"), + (90, "XC"), + (50, "L"), + (40, "XL"), + (10, "X"), + (9, "IX"), + (5, "V"), + (4, "IV"), + (1, "I"), +] + + def roman_to_int(roman: str) -> int: """ LeetCode No. 13 Roman to Integer @@ -29,21 +46,6 @@ def int_to_roman(number: int) -> str: >>> all(int_to_roman(value) == key for key, value in tests.items()) True """ - ROMAN = [ # noqa: N806 - (1000, "M"), - (900, "CM"), - (500, "D"), - (400, "CD"), - (100, "C"), - (90, "XC"), - (50, "L"), - (40, "XL"), - (10, "X"), - (9, "IX"), - (5, "V"), - (4, "IV"), - (1, "I"), - ] result = [] for (arabic, roman) in ROMAN: (factor, number) = divmod(number, arabic) diff --git a/geodesy/haversine_distance.py b/geodesy/haversine_distance.py index b601d2fd1..93e625770 100644 --- a/geodesy/haversine_distance.py +++ b/geodesy/haversine_distance.py @@ -1,5 +1,9 @@ from math import asin, atan, cos, radians, sin, sqrt, tan +AXIS_A = 6378137.0 +AXIS_B = 6356752.314245 +RADIUS = 6378137 + def haversine_distance(lat1: float, lon1: float, lat2: float, lon2: float) -> float: """ @@ -30,9 +34,6 @@ def haversine_distance(lat1: float, lon1: float, lat2: float, lon2: float) -> fl """ # CONSTANTS per WGS84 https://en.wikipedia.org/wiki/World_Geodetic_System # Distance in metres(m) - AXIS_A = 6378137.0 # noqa: N806 - AXIS_B = 6356752.314245 # noqa: N806 - RADIUS = 6378137 # noqa: N806 # Equation parameters # Equation https://en.wikipedia.org/wiki/Haversine_formula#Formulation flattening = (AXIS_A - AXIS_B) / AXIS_A diff --git a/geodesy/lamberts_ellipsoidal_distance.py b/geodesy/lamberts_ellipsoidal_distance.py index d36d39953..62ce59bb4 100644 --- a/geodesy/lamberts_ellipsoidal_distance.py +++ b/geodesy/lamberts_ellipsoidal_distance.py @@ -2,6 +2,10 @@ from math import atan, cos, radians, sin, tan from .haversine_distance import haversine_distance +AXIS_A = 6378137.0 +AXIS_B = 6356752.314245 +EQUATORIAL_RADIUS = 6378137 + def lamberts_ellipsoidal_distance( lat1: float, lon1: float, lat2: float, lon2: float @@ -45,10 +49,6 @@ def lamberts_ellipsoidal_distance( # CONSTANTS per WGS84 https://en.wikipedia.org/wiki/World_Geodetic_System # Distance in metres(m) - AXIS_A = 6378137.0 # noqa: N806 - AXIS_B = 6356752.314245 # noqa: N806 - EQUATORIAL_RADIUS = 6378137 # noqa: N806 - # Equation Parameters # https://en.wikipedia.org/wiki/Geographical_distance#Lambert's_formula_for_long_lines flattening = (AXIS_A - AXIS_B) / AXIS_A diff --git a/hashes/adler32.py b/hashes/adler32.py index 80229f046..611ebc88b 100644 --- a/hashes/adler32.py +++ b/hashes/adler32.py @@ -8,6 +8,8 @@ source: https://en.wikipedia.org/wiki/Adler-32 """ +MOD_ADLER = 65521 + def adler32(plain_text: str) -> int: """ @@ -20,7 +22,6 @@ def adler32(plain_text: str) -> int: >>> adler32('go adler em all') 708642122 """ - MOD_ADLER = 65521 # noqa: N806 a = 1 b = 0 for plain_chr in plain_text: diff --git a/physics/n_body_simulation.py b/physics/n_body_simulation.py index e62e1de62..f6efb0fec 100644 --- a/physics/n_body_simulation.py +++ b/physics/n_body_simulation.py @@ -19,6 +19,12 @@ import random from matplotlib import animation from matplotlib import pyplot as plt +# Frame rate of the animation +INTERVAL = 20 + +# Time between time steps in seconds +DELTA_TIME = INTERVAL / 1000 + class Body: def __init__( @@ -219,12 +225,6 @@ def plot( Utility function to plot how the given body-system evolves over time. No doctest provided since this function does not have a return value. """ - # Frame rate of the animation - INTERVAL = 20 # noqa: N806 - - # Time between time steps in seconds - DELTA_TIME = INTERVAL / 1000 # noqa: N806 - fig = plt.figure() fig.canvas.set_window_title(title) ax = plt.axes( diff --git a/project_euler/problem_054/test_poker_hand.py b/project_euler/problem_054/test_poker_hand.py index bf5a20a8e..5735bfc37 100644 --- a/project_euler/problem_054/test_poker_hand.py +++ b/project_euler/problem_054/test_poker_hand.py @@ -185,12 +185,12 @@ def test_compare_random(hand, other, expected): def test_hand_sorted(): - POKER_HANDS = [PokerHand(hand) for hand in SORTED_HANDS] # noqa: N806 - list_copy = POKER_HANDS.copy() + poker_hands = [PokerHand(hand) for hand in SORTED_HANDS] + list_copy = poker_hands.copy() shuffle(list_copy) user_sorted = chain(sorted(list_copy)) for index, hand in enumerate(user_sorted): - assert hand == POKER_HANDS[index] + assert hand == poker_hands[index] def test_custom_sort_five_high_straight(): diff --git a/project_euler/problem_064/sol1.py b/project_euler/problem_064/sol1.py index 9edd9a1e7..81ebcc7b7 100644 --- a/project_euler/problem_064/sol1.py +++ b/project_euler/problem_064/sol1.py @@ -33,13 +33,13 @@ def continuous_fraction_period(n: int) -> int: """ numerator = 0.0 denominator = 1.0 - ROOT = int(sqrt(n)) # noqa: N806 - integer_part = ROOT + root = int(sqrt(n)) + integer_part = root period = 0 - while integer_part != 2 * ROOT: + while integer_part != 2 * root: numerator = denominator * integer_part - numerator denominator = (n - numerator**2) / denominator - integer_part = int((ROOT + numerator) / denominator) + integer_part = int((root + numerator) / denominator) period += 1 return period diff --git a/project_euler/problem_097/sol1.py b/project_euler/problem_097/sol1.py index 94a43894e..2807e893d 100644 --- a/project_euler/problem_097/sol1.py +++ b/project_euler/problem_097/sol1.py @@ -34,9 +34,9 @@ def solution(n: int = 10) -> str: """ if not isinstance(n, int) or n < 0: raise ValueError("Invalid input") - MODULUS = 10**n # noqa: N806 - NUMBER = 28433 * (pow(2, 7830457, MODULUS)) + 1 # noqa: N806 - return str(NUMBER % MODULUS) + modulus = 10**n + number = 28433 * (pow(2, 7830457, modulus)) + 1 + return str(number % modulus) if __name__ == "__main__": diff --git a/project_euler/problem_125/sol1.py b/project_euler/problem_125/sol1.py index 1812df361..616f6f122 100644 --- a/project_euler/problem_125/sol1.py +++ b/project_euler/problem_125/sol1.py @@ -13,6 +13,8 @@ Find the sum of all the numbers less than 10^8 that are both palindromic and can be written as the sum of consecutive squares. """ +LIMIT = 10**8 + def is_palindrome(n: int) -> bool: """ @@ -35,7 +37,6 @@ def solution() -> int: Returns the sum of all numbers less than 1e8 that are both palindromic and can be written as the sum of consecutive squares. """ - LIMIT = 10**8 # noqa: N806 answer = set() first_square = 1 sum_squares = 5 diff --git a/sorts/radix_sort.py b/sorts/radix_sort.py index a496cdc0c..832b6162f 100644 --- a/sorts/radix_sort.py +++ b/sorts/radix_sort.py @@ -5,6 +5,8 @@ Source: https://en.wikipedia.org/wiki/Radix_sort """ from __future__ import annotations +RADIX = 10 + def radix_sort(list_of_ints: list[int]) -> list[int]: """ @@ -19,7 +21,6 @@ def radix_sort(list_of_ints: list[int]) -> list[int]: >>> radix_sort([1,100,10,1000]) == sorted([1,100,10,1000]) True """ - RADIX = 10 # noqa: N806 placement = 1 max_digit = max(list_of_ints) while placement <= max_digit: diff --git a/web_programming/fetch_quotes.py b/web_programming/fetch_quotes.py index a45f6ea0e..d557e2d95 100644 --- a/web_programming/fetch_quotes.py +++ b/web_programming/fetch_quotes.py @@ -10,15 +10,15 @@ import pprint import requests +API_ENDPOINT_URL = "https://zenquotes.io/api" + def quote_of_the_day() -> list: - API_ENDPOINT_URL = "https://zenquotes.io/api/today/" # noqa: N806 - return requests.get(API_ENDPOINT_URL).json() + return requests.get(API_ENDPOINT_URL + "/today").json() def random_quotes() -> list: - API_ENDPOINT_URL = "https://zenquotes.io/api/random/" # noqa: N806 - return requests.get(API_ENDPOINT_URL).json() + return requests.get(API_ENDPOINT_URL + "/random").json() if __name__ == "__main__": From d728f5a96bce1cb748d903de2f7dff2e2a2b54eb Mon Sep 17 00:00:00 2001 From: Advik Sharma <70201060+advik-student-dev@users.noreply.github.com> Date: Sun, 16 Oct 2022 06:28:10 -0700 Subject: [PATCH 381/726] Added some more comments to volume.py in maths folder (#7080) * Added some more comments added some more comments (to formulas which need it) which make the code more readable and understandable. might make a list of all the formulas on the top, later * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Apply suggestions from code review * The order changes the result * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix long line * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- maths/volume.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/maths/volume.py b/maths/volume.py index 97c06d7e1..a594e1b90 100644 --- a/maths/volume.py +++ b/maths/volume.py @@ -1,6 +1,7 @@ """ -Find Volumes of Various Shapes. -Wikipedia reference: https://en.wikipedia.org/wiki/Volume +Find the volume of various shapes. +* https://en.wikipedia.org/wiki/Volume +* https://en.wikipedia.org/wiki/Spherical_cap """ from __future__ import annotations @@ -30,8 +31,7 @@ def vol_cube(side_length: int | float) -> float: def vol_spherical_cap(height: float, radius: float) -> float: """ - Calculate the Volume of the spherical cap. - :return 1/3 pi * height ^ 2 * (3 * radius - height) + Calculate the volume of the spherical cap. >>> vol_spherical_cap(1, 2) 5.235987755982988 >>> vol_spherical_cap(1.6, 2.6) @@ -49,6 +49,7 @@ def vol_spherical_cap(height: float, radius: float) -> float: """ if height < 0 or radius < 0: raise ValueError("vol_spherical_cap() only accepts non-negative values") + # Volume is 1/3 pi * height squared * (3 * radius - height) return 1 / 3 * pi * pow(height, 2) * (3 * radius - height) @@ -263,6 +264,7 @@ def vol_sphere(radius: float) -> float: """ if radius < 0: raise ValueError("vol_sphere() only accepts non-negative values") + # Volume is 4/3 * pi * radius cubed return 4 / 3 * pi * pow(radius, 3) @@ -274,7 +276,7 @@ def vol_hemisphere(radius: float) -> float: >>> vol_hemisphere(1) 2.0943951023931953 >>> vol_hemisphere(7) - 718.3775201208659 + 718.377520120866 >>> vol_hemisphere(1.6) 8.57864233940253 >>> vol_hemisphere(0) @@ -286,7 +288,8 @@ def vol_hemisphere(radius: float) -> float: """ if radius < 0: raise ValueError("vol_hemisphere() only accepts non-negative values") - return 2 / 3 * pi * pow(radius, 3) + # Volume is radius cubed * pi * 2/3 + return pow(radius, 3) * pi * 2 / 3 def vol_circular_cylinder(radius: float, height: float) -> float: @@ -312,7 +315,8 @@ def vol_circular_cylinder(radius: float, height: float) -> float: """ if height < 0 or radius < 0: raise ValueError("vol_circular_cylinder() only accepts non-negative values") - return pi * pow(radius, 2) * height + # Volume is radius squared * height * pi + return pow(radius, 2) * height * pi def vol_hollow_circular_cylinder( @@ -344,6 +348,7 @@ def vol_hollow_circular_cylinder( ... ValueError: outer_radius must be greater than inner_radius """ + # Volume - (outer_radius squared - inner_radius squared) * pi * height if inner_radius < 0 or outer_radius < 0 or height < 0: raise ValueError( "vol_hollow_circular_cylinder() only accepts non-negative values" @@ -356,7 +361,7 @@ def vol_hollow_circular_cylinder( def vol_conical_frustum(height: float, radius_1: float, radius_2: float) -> float: """Calculate the Volume of a Conical Frustum. Wikipedia reference: https://en.wikipedia.org/wiki/Frustum - :return 1/3 * pi * height * (radius_1^2 + radius_top^2 + radius_1 * radius_2) + >>> vol_conical_frustum(45, 7, 28) 48490.482608158454 >>> vol_conical_frustum(1, 1, 2) @@ -378,6 +383,8 @@ def vol_conical_frustum(height: float, radius_1: float, radius_2: float) -> floa ... ValueError: vol_conical_frustum() only accepts non-negative values """ + # Volume is 1/3 * pi * height * + # (radius_1 squared + radius_2 squared + radius_1 * radius_2) if radius_1 < 0 or radius_2 < 0 or height < 0: raise ValueError("vol_conical_frustum() only accepts non-negative values") return ( From b5b1eb2f00f942955217ef6968fe8016476690ba Mon Sep 17 00:00:00 2001 From: Sagar Giri Date: Sun, 16 Oct 2022 22:45:25 +0900 Subject: [PATCH 382/726] Fix broken links by PR #7277 (#7319) --- bit_manipulation/count_1s_brian_kernighan_method.py | 2 +- machine_learning/sequential_minimum_optimization.py | 1 - physics/n_body_simulation.py | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/bit_manipulation/count_1s_brian_kernighan_method.py b/bit_manipulation/count_1s_brian_kernighan_method.py index d217af90b..e6d6d6534 100644 --- a/bit_manipulation/count_1s_brian_kernighan_method.py +++ b/bit_manipulation/count_1s_brian_kernighan_method.py @@ -1,7 +1,7 @@ def get_1s_count(number: int) -> int: """ Count the number of set bits in a 32 bit integer using Brian Kernighan's way. - Ref - http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan + Ref - https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan >>> get_1s_count(25) 3 >>> get_1s_count(37) diff --git a/machine_learning/sequential_minimum_optimization.py b/machine_learning/sequential_minimum_optimization.py index 40adca7e0..df5b03790 100644 --- a/machine_learning/sequential_minimum_optimization.py +++ b/machine_learning/sequential_minimum_optimization.py @@ -28,7 +28,6 @@ Usage: Reference: https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/smo-book.pdf https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/tr-98-14.pdf - https://web.cs.iastate.edu/~honavar/smo-svm.pdf """ diff --git a/physics/n_body_simulation.py b/physics/n_body_simulation.py index f6efb0fec..2b701283f 100644 --- a/physics/n_body_simulation.py +++ b/physics/n_body_simulation.py @@ -8,7 +8,7 @@ velocity and position brought about by these forces. Softening is used to preven numerical divergences when a particle comes too close to another (and the force goes to infinity). (Description adapted from https://en.wikipedia.org/wiki/N-body_simulation ) -(See also https://www.shodor.org/refdesk/Resources/Algorithms/EulersMethod/ ) +(See also http://www.shodor.org/refdesk/Resources/Algorithms/EulersMethod/ ) """ @@ -258,7 +258,7 @@ def example_1() -> BodySystem: Example 1: figure-8 solution to the 3-body-problem This example can be seen as a test of the implementation: given the right initial conditions, the bodies should move in a figure-8. - (initial conditions taken from https://www.artcompsci.org/vol_1/v1_web/node56.html) + (initial conditions taken from http://www.artcompsci.org/vol_1/v1_web/node56.html) >>> body_system = example_1() >>> len(body_system) 3 From 6d20e2b750839d978873f6a89ce6d844ba3cc0b8 Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Sun, 16 Oct 2022 20:50:48 +0100 Subject: [PATCH 383/726] Add `flake8-broken-line` to `pre-commit` (#7338) * ci: Add ``flake8-broken-line`` plugin to ``pre-commit`` * refactor: Fix errors from ``flake8-broken-line`` --- .pre-commit-config.yaml | 1 + project_euler/problem_008/sol1.py | 42 ++++++++++++++++--------------- project_euler/problem_008/sol3.py | 42 ++++++++++++++++--------------- 3 files changed, 45 insertions(+), 40 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 345513565..39af0f3b4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -39,6 +39,7 @@ repos: additional_dependencies: - flake8-bugbear - flake8-builtins + - flake8-broken-line - flake8-comprehensions - pep8-naming diff --git a/project_euler/problem_008/sol1.py b/project_euler/problem_008/sol1.py index 796080127..69dd1b473 100644 --- a/project_euler/problem_008/sol1.py +++ b/project_euler/problem_008/sol1.py @@ -33,26 +33,28 @@ greatest product. What is the value of this product? import sys -N = """73167176531330624919225119674426574742355349194934\ -96983520312774506326239578318016984801869478851843\ -85861560789112949495459501737958331952853208805511\ -12540698747158523863050715693290963295227443043557\ -66896648950445244523161731856403098711121722383113\ -62229893423380308135336276614282806444486645238749\ -30358907296290491560440772390713810515859307960866\ -70172427121883998797908792274921901699720888093776\ -65727333001053367881220235421809751254540594752243\ -52584907711670556013604839586446706324415722155397\ -53697817977846174064955149290862569321978468622482\ -83972241375657056057490261407972968652414535100474\ -82166370484403199890008895243450658541227588666881\ -16427171479924442928230863465674813919123162824586\ -17866458359124566529476545682848912883142607690042\ -24219022671055626321111109370544217506941658960408\ -07198403850962455444362981230987879927244284909188\ -84580156166097919133875499200524063689912560717606\ -05886116467109405077541002256983155200055935729725\ -71636269561882670428252483600823257530420752963450""" +N = ( + "73167176531330624919225119674426574742355349194934" + "96983520312774506326239578318016984801869478851843" + "85861560789112949495459501737958331952853208805511" + "12540698747158523863050715693290963295227443043557" + "66896648950445244523161731856403098711121722383113" + "62229893423380308135336276614282806444486645238749" + "30358907296290491560440772390713810515859307960866" + "70172427121883998797908792274921901699720888093776" + "65727333001053367881220235421809751254540594752243" + "52584907711670556013604839586446706324415722155397" + "53697817977846174064955149290862569321978468622482" + "83972241375657056057490261407972968652414535100474" + "82166370484403199890008895243450658541227588666881" + "16427171479924442928230863465674813919123162824586" + "17866458359124566529476545682848912883142607690042" + "24219022671055626321111109370544217506941658960408" + "07198403850962455444362981230987879927244284909188" + "84580156166097919133875499200524063689912560717606" + "05886116467109405077541002256983155200055935729725" + "71636269561882670428252483600823257530420752963450" +) def solution(n: str = N) -> int: diff --git a/project_euler/problem_008/sol3.py b/project_euler/problem_008/sol3.py index 4b99d0ea6..c6081aa05 100644 --- a/project_euler/problem_008/sol3.py +++ b/project_euler/problem_008/sol3.py @@ -32,26 +32,28 @@ greatest product. What is the value of this product? """ import sys -N = """73167176531330624919225119674426574742355349194934\ -96983520312774506326239578318016984801869478851843\ -85861560789112949495459501737958331952853208805511\ -12540698747158523863050715693290963295227443043557\ -66896648950445244523161731856403098711121722383113\ -62229893423380308135336276614282806444486645238749\ -30358907296290491560440772390713810515859307960866\ -70172427121883998797908792274921901699720888093776\ -65727333001053367881220235421809751254540594752243\ -52584907711670556013604839586446706324415722155397\ -53697817977846174064955149290862569321978468622482\ -83972241375657056057490261407972968652414535100474\ -82166370484403199890008895243450658541227588666881\ -16427171479924442928230863465674813919123162824586\ -17866458359124566529476545682848912883142607690042\ -24219022671055626321111109370544217506941658960408\ -07198403850962455444362981230987879927244284909188\ -84580156166097919133875499200524063689912560717606\ -05886116467109405077541002256983155200055935729725\ -71636269561882670428252483600823257530420752963450""" +N = ( + "73167176531330624919225119674426574742355349194934" + "96983520312774506326239578318016984801869478851843" + "85861560789112949495459501737958331952853208805511" + "12540698747158523863050715693290963295227443043557" + "66896648950445244523161731856403098711121722383113" + "62229893423380308135336276614282806444486645238749" + "30358907296290491560440772390713810515859307960866" + "70172427121883998797908792274921901699720888093776" + "65727333001053367881220235421809751254540594752243" + "52584907711670556013604839586446706324415722155397" + "53697817977846174064955149290862569321978468622482" + "83972241375657056057490261407972968652414535100474" + "82166370484403199890008895243450658541227588666881" + "16427171479924442928230863465674813919123162824586" + "17866458359124566529476545682848912883142607690042" + "24219022671055626321111109370544217506941658960408" + "07198403850962455444362981230987879927244284909188" + "84580156166097919133875499200524063689912560717606" + "05886116467109405077541002256983155200055935729725" + "71636269561882670428252483600823257530420752963450" +) def str_eval(s: str) -> int: From 7f6e0b656f6362e452b11d06acde50b8b81cb31a Mon Sep 17 00:00:00 2001 From: SudhanshuSuman <51868273+SudhanshuSuman@users.noreply.github.com> Date: Mon, 17 Oct 2022 02:11:28 +0530 Subject: [PATCH 384/726] Corrected the directory of Fractional Knapsack algorithm (#7086) * Moved fractional knapsack from 'dynamic_programming' to 'greedy_methods' * Updated DIRECTORY.md --- DIRECTORY.md | 4 +- .../fractional_knapsack.py | 0 .../fractional_knapsack_2.py | 106 +++++++++--------- 3 files changed, 55 insertions(+), 55 deletions(-) rename {dynamic_programming => greedy_methods}/fractional_knapsack.py (100%) rename {dynamic_programming => greedy_methods}/fractional_knapsack_2.py (96%) diff --git a/DIRECTORY.md b/DIRECTORY.md index 92bed9cb4..fae9a5183 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -279,8 +279,6 @@ * [Fast Fibonacci](dynamic_programming/fast_fibonacci.py) * [Fibonacci](dynamic_programming/fibonacci.py) * [Floyd Warshall](dynamic_programming/floyd_warshall.py) - * [Fractional Knapsack](dynamic_programming/fractional_knapsack.py) - * [Fractional Knapsack 2](dynamic_programming/fractional_knapsack_2.py) * [Integer Partition](dynamic_programming/integer_partition.py) * [Iterating Through Submasks](dynamic_programming/iterating_through_submasks.py) * [Knapsack](dynamic_programming/knapsack.py) @@ -396,6 +394,8 @@ * [Test Min Spanning Tree Prim](graphs/tests/test_min_spanning_tree_prim.py) ## Greedy Methods + * [Fractional Knapsack](greedy_methods/fractional_knapsack.py) + * [Fractional Knapsack 2](greedy_methods/fractional_knapsack_2.py) * [Optimal Merge Pattern](greedy_methods/optimal_merge_pattern.py) ## Hashes diff --git a/dynamic_programming/fractional_knapsack.py b/greedy_methods/fractional_knapsack.py similarity index 100% rename from dynamic_programming/fractional_knapsack.py rename to greedy_methods/fractional_knapsack.py diff --git a/dynamic_programming/fractional_knapsack_2.py b/greedy_methods/fractional_knapsack_2.py similarity index 96% rename from dynamic_programming/fractional_knapsack_2.py rename to greedy_methods/fractional_knapsack_2.py index bd776723c..6d9ed2ec3 100644 --- a/dynamic_programming/fractional_knapsack_2.py +++ b/greedy_methods/fractional_knapsack_2.py @@ -1,53 +1,53 @@ -# https://en.wikipedia.org/wiki/Continuous_knapsack_problem -# https://www.guru99.com/fractional-knapsack-problem-greedy.html -# https://medium.com/walkinthecode/greedy-algorithm-fractional-knapsack-problem-9aba1daecc93 - -from __future__ import annotations - - -def fractional_knapsack( - value: list[int], weight: list[int], capacity: int -) -> tuple[float, list[float]]: - """ - >>> value = [1, 3, 5, 7, 9] - >>> weight = [0.9, 0.7, 0.5, 0.3, 0.1] - >>> fractional_knapsack(value, weight, 5) - (25, [1, 1, 1, 1, 1]) - >>> fractional_knapsack(value, weight, 15) - (25, [1, 1, 1, 1, 1]) - >>> fractional_knapsack(value, weight, 25) - (25, [1, 1, 1, 1, 1]) - >>> fractional_knapsack(value, weight, 26) - (25, [1, 1, 1, 1, 1]) - >>> fractional_knapsack(value, weight, -1) - (-90.0, [0, 0, 0, 0, -10.0]) - >>> fractional_knapsack([1, 3, 5, 7], weight, 30) - (16, [1, 1, 1, 1]) - >>> fractional_knapsack(value, [0.9, 0.7, 0.5, 0.3, 0.1], 30) - (25, [1, 1, 1, 1, 1]) - >>> fractional_knapsack([], [], 30) - (0, []) - """ - index = list(range(len(value))) - ratio = [v / w for v, w in zip(value, weight)] - index.sort(key=lambda i: ratio[i], reverse=True) - - max_value: float = 0 - fractions: list[float] = [0] * len(value) - for i in index: - if weight[i] <= capacity: - fractions[i] = 1 - max_value += value[i] - capacity -= weight[i] - else: - fractions[i] = capacity / weight[i] - max_value += value[i] * capacity / weight[i] - break - - return max_value, fractions - - -if __name__ == "__main__": - import doctest - - doctest.testmod() +# https://en.wikipedia.org/wiki/Continuous_knapsack_problem +# https://www.guru99.com/fractional-knapsack-problem-greedy.html +# https://medium.com/walkinthecode/greedy-algorithm-fractional-knapsack-problem-9aba1daecc93 + +from __future__ import annotations + + +def fractional_knapsack( + value: list[int], weight: list[int], capacity: int +) -> tuple[float, list[float]]: + """ + >>> value = [1, 3, 5, 7, 9] + >>> weight = [0.9, 0.7, 0.5, 0.3, 0.1] + >>> fractional_knapsack(value, weight, 5) + (25, [1, 1, 1, 1, 1]) + >>> fractional_knapsack(value, weight, 15) + (25, [1, 1, 1, 1, 1]) + >>> fractional_knapsack(value, weight, 25) + (25, [1, 1, 1, 1, 1]) + >>> fractional_knapsack(value, weight, 26) + (25, [1, 1, 1, 1, 1]) + >>> fractional_knapsack(value, weight, -1) + (-90.0, [0, 0, 0, 0, -10.0]) + >>> fractional_knapsack([1, 3, 5, 7], weight, 30) + (16, [1, 1, 1, 1]) + >>> fractional_knapsack(value, [0.9, 0.7, 0.5, 0.3, 0.1], 30) + (25, [1, 1, 1, 1, 1]) + >>> fractional_knapsack([], [], 30) + (0, []) + """ + index = list(range(len(value))) + ratio = [v / w for v, w in zip(value, weight)] + index.sort(key=lambda i: ratio[i], reverse=True) + + max_value: float = 0 + fractions: list[float] = [0] * len(value) + for i in index: + if weight[i] <= capacity: + fractions[i] = 1 + max_value += value[i] + capacity -= weight[i] + else: + fractions[i] = capacity / weight[i] + max_value += value[i] * capacity / weight[i] + break + + return max_value, fractions + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From f15cc2f01c2a4124ff6dc0843c728a546f9d9f79 Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Sun, 16 Oct 2022 21:50:11 +0100 Subject: [PATCH 385/726] Follow Flake8 pep3101 and remove modulo formatting (#7339) * ci: Add ``flake8-pep3101`` plugin to ``pre-commit`` * refactor: Remove all modulo string formatting * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * refactor: Remove ``flake8-pep3101`` plugin from ``pre-commit`` * revert: Revert to modulo formatting * refactor: Use f-string instead of `join` Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- ciphers/elgamal_key_generator.py | 9 +++------ ciphers/rsa_key_generator.py | 3 +-- dynamic_programming/edit_distance.py | 4 ++-- genetic_algorithm/basic_string.py | 4 ++-- graphs/minimum_spanning_tree_boruvka.py | 2 +- machine_learning/linear_regression.py | 2 +- matrix/sherman_morrison.py | 6 +++--- neural_network/back_propagation_neural_network.py | 2 +- neural_network/convolution_neural_network.py | 2 +- 9 files changed, 15 insertions(+), 19 deletions(-) diff --git a/ciphers/elgamal_key_generator.py b/ciphers/elgamal_key_generator.py index 4d72128ae..17ba55c0d 100644 --- a/ciphers/elgamal_key_generator.py +++ b/ciphers/elgamal_key_generator.py @@ -41,22 +41,19 @@ def make_key_files(name: str, key_size: int) -> None: if os.path.exists(f"{name}_pubkey.txt") or os.path.exists(f"{name}_privkey.txt"): print("\nWARNING:") print( - '"%s_pubkey.txt" or "%s_privkey.txt" already exists. \n' + f'"{name}_pubkey.txt" or "{name}_privkey.txt" already exists. \n' "Use a different name or delete these files and re-run this program." - % (name, name) ) sys.exit() public_key, private_key = generate_key(key_size) print(f"\nWriting public key to file {name}_pubkey.txt...") with open(f"{name}_pubkey.txt", "w") as fo: - fo.write( - "%d,%d,%d,%d" % (public_key[0], public_key[1], public_key[2], public_key[3]) - ) + fo.write(f"{public_key[0]},{public_key[1]},{public_key[2]},{public_key[3]}") print(f"Writing private key to file {name}_privkey.txt...") with open(f"{name}_privkey.txt", "w") as fo: - fo.write("%d,%d" % (private_key[0], private_key[1])) + fo.write(f"{private_key[0]},{private_key[1]}") def main() -> None: diff --git a/ciphers/rsa_key_generator.py b/ciphers/rsa_key_generator.py index f64bc7dd0..2573ed013 100644 --- a/ciphers/rsa_key_generator.py +++ b/ciphers/rsa_key_generator.py @@ -37,9 +37,8 @@ def make_key_files(name: str, key_size: int) -> None: if os.path.exists(f"{name}_pubkey.txt") or os.path.exists(f"{name}_privkey.txt"): print("\nWARNING:") print( - '"%s_pubkey.txt" or "%s_privkey.txt" already exists. \n' + f'"{name}_pubkey.txt" or "{name}_privkey.txt" already exists. \n' "Use a different name or delete these files and re-run this program." - % (name, name) ) sys.exit() diff --git a/dynamic_programming/edit_distance.py b/dynamic_programming/edit_distance.py index d63e559e3..fe23431a7 100644 --- a/dynamic_programming/edit_distance.py +++ b/dynamic_programming/edit_distance.py @@ -99,7 +99,7 @@ if __name__ == "__main__": S2 = input("Enter the second string: ").strip() print() - print("The minimum Edit Distance is: %d" % (solver.solve(S1, S2))) - print("The minimum Edit Distance is: %d" % (min_distance_bottom_up(S1, S2))) + print(f"The minimum Edit Distance is: {solver.solve(S1, S2)}") + print(f"The minimum Edit Distance is: {min_distance_bottom_up(S1, S2)}") print() print("*************** End of Testing Edit Distance DP Algorithm ***************") diff --git a/genetic_algorithm/basic_string.py b/genetic_algorithm/basic_string.py index bd7d80268..d2d305189 100644 --- a/genetic_algorithm/basic_string.py +++ b/genetic_algorithm/basic_string.py @@ -172,7 +172,7 @@ if __name__ == "__main__": " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm" "nopqrstuvwxyz.,;!?+-*#@^'èéòà€ù=)(&%$£/\\" ) + generation, population, target = basic(target_str, genes_list) print( - "\nGeneration: %s\nTotal Population: %s\nTarget: %s" - % basic(target_str, genes_list) + f"\nGeneration: {generation}\nTotal Population: {population}\nTarget: {target}" ) diff --git a/graphs/minimum_spanning_tree_boruvka.py b/graphs/minimum_spanning_tree_boruvka.py index 32548b2ec..6c72615cc 100644 --- a/graphs/minimum_spanning_tree_boruvka.py +++ b/graphs/minimum_spanning_tree_boruvka.py @@ -63,7 +63,7 @@ class Graph: for tail in self.adjacency: for head in self.adjacency[tail]: weight = self.adjacency[head][tail] - string += "%d -> %d == %d\n" % (head, tail, weight) + string += f"{head} -> {tail} == {weight}\n" return string.rstrip("\n") def get_edges(self): diff --git a/machine_learning/linear_regression.py b/machine_learning/linear_regression.py index 85fdfb000..92ab91c01 100644 --- a/machine_learning/linear_regression.py +++ b/machine_learning/linear_regression.py @@ -82,7 +82,7 @@ def run_linear_regression(data_x, data_y): for i in range(0, iterations): theta = run_steep_gradient_descent(data_x, data_y, len_data, alpha, theta) error = sum_of_square_error(data_x, data_y, len_data, theta) - print("At Iteration %d - Error is %.5f " % (i + 1, error)) + print(f"At Iteration {i + 1} - Error is {error:.5f}") return theta diff --git a/matrix/sherman_morrison.py b/matrix/sherman_morrison.py index 29c9b3381..39eddfed8 100644 --- a/matrix/sherman_morrison.py +++ b/matrix/sherman_morrison.py @@ -31,14 +31,14 @@ class Matrix: """ # Prefix - s = "Matrix consist of %d rows and %d columns\n" % (self.row, self.column) + s = f"Matrix consist of {self.row} rows and {self.column} columns\n" # Make string identifier max_element_length = 0 for row_vector in self.array: for obj in row_vector: max_element_length = max(max_element_length, len(str(obj))) - string_format_identifier = "%%%ds" % (max_element_length,) + string_format_identifier = f"%{max_element_length}s" # Make string and return def single_line(row_vector: list[float]) -> str: @@ -252,7 +252,7 @@ if __name__ == "__main__": v[0, 0], v[1, 0], v[2, 0] = 4, -2, 5 print(f"u is {u}") print(f"v is {v}") - print("uv^T is %s" % (u * v.transpose())) + print(f"uv^T is {u * v.transpose()}") # Sherman Morrison print(f"(a + uv^T)^(-1) is {ainv.sherman_morrison(u, v)}") diff --git a/neural_network/back_propagation_neural_network.py b/neural_network/back_propagation_neural_network.py index 23b818b0f..cb47b8290 100644 --- a/neural_network/back_propagation_neural_network.py +++ b/neural_network/back_propagation_neural_network.py @@ -117,7 +117,7 @@ class BPNN: def summary(self): for i, layer in enumerate(self.layers[:]): - print("------- layer %d -------" % i) + print(f"------- layer {i} -------") print("weight.shape ", np.shape(layer.weight)) print("bias.shape ", np.shape(layer.bias)) diff --git a/neural_network/convolution_neural_network.py b/neural_network/convolution_neural_network.py index 9dfb6d091..bd0550212 100644 --- a/neural_network/convolution_neural_network.py +++ b/neural_network/convolution_neural_network.py @@ -219,7 +219,7 @@ class CNN: mse = 10000 while rp < n_repeat and mse >= error_accuracy: error_count = 0 - print("-------------Learning Time %d--------------" % rp) + print(f"-------------Learning Time {rp}--------------") for p in range(len(datas_train)): # print('------------Learning Image: %d--------------'%p) data_train = np.asmatrix(datas_train[p]) From a34b756fd40e5cdfb69abc06dcd42f5f1b5fa21e Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Sun, 16 Oct 2022 21:51:40 +0100 Subject: [PATCH 386/726] ci: Add ``yesqa`` (flake8-plugin) to ``pre-commit`` (#7340) --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 39af0f3b4..aea82d12c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -42,6 +42,7 @@ repos: - flake8-broken-line - flake8-comprehensions - pep8-naming + - yesqa - repo: https://github.com/pre-commit/mirrors-mypy rev: v0.982 From 0c7c5fa7b0161a7433467240155356c93ae106b8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 17 Oct 2022 21:59:25 +0200 Subject: [PATCH 387/726] [pre-commit.ci] pre-commit autoupdate (#7387) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/asottile/pyupgrade: v3.0.0 → v3.1.0](https://github.com/asottile/pyupgrade/compare/v3.0.0...v3.1.0) - [github.com/codespell-project/codespell: v2.2.1 → v2.2.2](https://github.com/codespell-project/codespell/compare/v2.2.1...v2.2.2) * updating DIRECTORY.md * Fix typo discovered by codespell * Fix typo discovered by codespell * Update .pre-commit-config.yaml * Update .pre-commit-config.yaml * Update .pre-commit-config.yaml Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss --- .pre-commit-config.yaml | 6 +++--- DIRECTORY.md | 2 ++ .../local_weighted_learning/local_weighted_learning.md | 2 +- maths/is_square_free.py | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index aea82d12c..5bdda50be 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,7 +26,7 @@ repos: - --profile=black - repo: https://github.com/asottile/pyupgrade - rev: v3.0.0 + rev: v3.1.0 hooks: - id: pyupgrade args: @@ -55,14 +55,14 @@ repos: additional_dependencies: [types-requests] - repo: https://github.com/codespell-project/codespell - rev: v2.2.1 + rev: v2.2.2 hooks: - id: codespell args: - --ignore-words-list=ans,crate,damon,fo,followings,hist,iff,mater,secant,som,sur,tim,zar - - --skip="./.*,./strings/dictionary.txt,./strings/words.txt,./project_euler/problem_022/p022_names.txt" exclude: | (?x)^( + ciphers/prehistoric_men.txt | strings/dictionary.txt | strings/words.txt | project_euler/problem_022/p022_names.txt diff --git a/DIRECTORY.md b/DIRECTORY.md index fae9a5183..94ec42832 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -642,6 +642,7 @@ * [Tower Of Hanoi](other/tower_of_hanoi.py) ## Physics + * [Casimir Effect](physics/casimir_effect.py) * [Horizontal Projectile Motion](physics/horizontal_projectile_motion.py) * [Lorentz Transformation Four Vector](physics/lorentz_transformation_four_vector.py) * [N Body Simulation](physics/n_body_simulation.py) @@ -928,6 +929,7 @@ * [Deutsch Jozsa](quantum/deutsch_jozsa.py) * [Half Adder](quantum/half_adder.py) * [Not Gate](quantum/not_gate.py) + * [Q Full Adder](quantum/q_full_adder.py) * [Quantum Entanglement](quantum/quantum_entanglement.py) * [Ripple Adder Classic](quantum/ripple_adder_classic.py) * [Single Qubit Measure](quantum/single_qubit_measure.py) diff --git a/machine_learning/local_weighted_learning/local_weighted_learning.md b/machine_learning/local_weighted_learning/local_weighted_learning.md index 5c7895e75..ef4dbc958 100644 --- a/machine_learning/local_weighted_learning/local_weighted_learning.md +++ b/machine_learning/local_weighted_learning/local_weighted_learning.md @@ -29,7 +29,7 @@ This training phase is possible when data points are linear, but there again com So, here comes the role of non-parametric algorithm which doesn't compute predictions based on fixed set of params. Rather parameters $\theta$ are computed individually for each query point/data point x.

-While Computing $\theta$ , a higher "preferance" is given to points in the vicinity of x than points farther from x. +While Computing $\theta$ , a higher preference is given to points in the vicinity of x than points farther from x. Cost Function J($\theta$) = $\sum_{i=1}^m$ $w^i$ (($\theta$)$^T$ $x^i$ - $y^i$)$^2$ diff --git a/maths/is_square_free.py b/maths/is_square_free.py index 8d83d95ff..4134398d2 100644 --- a/maths/is_square_free.py +++ b/maths/is_square_free.py @@ -15,7 +15,7 @@ def is_square_free(factors: list[int]) -> bool: False These are wrong but should return some value - it simply checks for repition in the numbers. + it simply checks for repetition in the numbers. >>> is_square_free([1, 3, 4, 'sd', 0.0]) True From 3448ae5cec868d4a03349cb952765e9abff41243 Mon Sep 17 00:00:00 2001 From: Shubham Kondekar <40213815+kondekarshubham123@users.noreply.github.com> Date: Tue, 18 Oct 2022 02:00:01 +0530 Subject: [PATCH 388/726] [Binary Tree] Different views of binary tree added (#6965) * Different views of binary tree added * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * mypy errors resolved * doc test for remaining functions * Flake8 comments resolved * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Example moved in if block * doctest cases added * Cases from if block removed * Update data_structures/binary_tree/diff_views_of_binary_tree.py Co-authored-by: Christian Clauss * Update data_structures/binary_tree/diff_views_of_binary_tree.py Co-authored-by: Christian Clauss * PR Comments resolved * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * flake8 warning resolved * Changes revered * flake8 issue resolved * Put the diagrams just above the doctests * Update diff_views_of_binary_tree.py * Update diff_views_of_binary_tree.py * I love mypy * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .../binary_tree/diff_views_of_binary_tree.py | 210 ++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 data_structures/binary_tree/diff_views_of_binary_tree.py diff --git a/data_structures/binary_tree/diff_views_of_binary_tree.py b/data_structures/binary_tree/diff_views_of_binary_tree.py new file mode 100644 index 000000000..3198d8065 --- /dev/null +++ b/data_structures/binary_tree/diff_views_of_binary_tree.py @@ -0,0 +1,210 @@ +r""" +Problem: Given root of a binary tree, return the: +1. binary-tree-right-side-view +2. binary-tree-left-side-view +3. binary-tree-top-side-view +4. binary-tree-bottom-side-view +""" + +from __future__ import annotations + +from collections import defaultdict +from dataclasses import dataclass + + +@dataclass +class TreeNode: + val: int + left: TreeNode | None = None + right: TreeNode | None = None + + +def make_tree() -> TreeNode: + """ + >>> make_tree().val + 3 + """ + return TreeNode(3, TreeNode(9), TreeNode(20, TreeNode(15), TreeNode(7))) + + +def binary_tree_right_side_view(root: TreeNode) -> list[int]: + r""" + Function returns the right side view of binary tree. + + 3 <- 3 + / \ + 9 20 <- 20 + / \ + 15 7 <- 7 + + >>> binary_tree_right_side_view(make_tree()) + [3, 20, 7] + >>> binary_tree_right_side_view(None) + [] + """ + + def depth_first_search( + root: TreeNode | None, depth: int, right_view: list[int] + ) -> None: + """ + A depth first search preorder traversal to append the values at + right side of tree. + """ + if not root: + return + + if depth == len(right_view): + right_view.append(root.val) + + depth_first_search(root.right, depth + 1, right_view) + depth_first_search(root.left, depth + 1, right_view) + + right_view: list = [] + if not root: + return right_view + + depth_first_search(root, 0, right_view) + return right_view + + +def binary_tree_left_side_view(root: TreeNode) -> list[int]: + r""" + Function returns the left side view of binary tree. + + 3 -> 3 + / \ + 9 -> 9 20 + / \ + 15 -> 15 7 + + >>> binary_tree_left_side_view(make_tree()) + [3, 9, 15] + >>> binary_tree_left_side_view(None) + [] + """ + + def depth_first_search( + root: TreeNode | None, depth: int, left_view: list[int] + ) -> None: + """ + A depth first search preorder traversal to append the values + at left side of tree. + """ + if not root: + return + + if depth == len(left_view): + left_view.append(root.val) + + depth_first_search(root.left, depth + 1, left_view) + depth_first_search(root.right, depth + 1, left_view) + + left_view: list = [] + if not root: + return left_view + + depth_first_search(root, 0, left_view) + return left_view + + +def binary_tree_top_side_view(root: TreeNode) -> list[int]: + r""" + Function returns the top side view of binary tree. + + 9 3 20 7 + ⬇ ⬇ ⬇ ⬇ + + 3 + / \ + 9 20 + / \ + 15 7 + + >>> binary_tree_top_side_view(make_tree()) + [9, 3, 20, 7] + >>> binary_tree_top_side_view(None) + [] + """ + + def breadth_first_search(root: TreeNode, top_view: list[int]) -> None: + """ + A breadth first search traversal with defaultdict ds to append + the values of tree from top view + """ + queue = [(root, 0)] + lookup = defaultdict(list) + + while queue: + first = queue.pop(0) + node, hd = first + + lookup[hd].append(node.val) + + if node.left: + queue.append((node.left, hd - 1)) + if node.right: + queue.append((node.right, hd + 1)) + + for pair in sorted(lookup.items(), key=lambda each: each[0]): + top_view.append(pair[1][0]) + + top_view: list = [] + if not root: + return top_view + + breadth_first_search(root, top_view) + return top_view + + +def binary_tree_bottom_side_view(root: TreeNode) -> list[int]: + r""" + Function returns the bottom side view of binary tree + + 3 + / \ + 9 20 + / \ + 15 7 + ↑ ↑ ↑ ↑ + 9 15 20 7 + + >>> binary_tree_bottom_side_view(make_tree()) + [9, 15, 20, 7] + >>> binary_tree_bottom_side_view(None) + [] + """ + from collections import defaultdict + + def breadth_first_search(root: TreeNode, bottom_view: list[int]) -> None: + """ + A breadth first search traversal with defaultdict ds to append + the values of tree from bottom view + """ + queue = [(root, 0)] + lookup = defaultdict(list) + + while queue: + first = queue.pop(0) + node, hd = first + lookup[hd].append(node.val) + + if node.left: + queue.append((node.left, hd - 1)) + if node.right: + queue.append((node.right, hd + 1)) + + for pair in sorted(lookup.items(), key=lambda each: each[0]): + bottom_view.append(pair[1][-1]) + + bottom_view: list = [] + if not root: + return bottom_view + + breadth_first_search(root, bottom_view) + return bottom_view + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 49cd46acea37350c8c22488316f8cf3f5ea88925 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Tue, 18 Oct 2022 02:09:41 -0400 Subject: [PATCH 389/726] Update convolve function namespace (#7390) --- computer_vision/horn_schunck.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/computer_vision/horn_schunck.py b/computer_vision/horn_schunck.py index 2a153d06d..b63e02682 100644 --- a/computer_vision/horn_schunck.py +++ b/computer_vision/horn_schunck.py @@ -12,7 +12,7 @@ from typing import SupportsIndex import numpy as np -from scipy.ndimage.filters import convolve +from scipy.ndimage import convolve def warp( From 6d1e009f35dd172ef51d484d0310919cdbab189d Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Tue, 18 Oct 2022 05:57:03 -0400 Subject: [PATCH 390/726] Remove depreciated np.float (#7394) --- machine_learning/decision_tree.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/machine_learning/decision_tree.py b/machine_learning/decision_tree.py index 4a86e5322..7cd1b02c4 100644 --- a/machine_learning/decision_tree.py +++ b/machine_learning/decision_tree.py @@ -24,13 +24,13 @@ class DecisionTree: estimate the labels >>> tester = DecisionTree() >>> test_labels = np.array([1,2,3,4,5,6,7,8,9,10]) - >>> test_prediction = np.float(6) + >>> test_prediction = float(6) >>> tester.mean_squared_error(test_labels, test_prediction) == ( ... TestDecisionTree.helper_mean_squared_error_test(test_labels, ... test_prediction)) True >>> test_labels = np.array([1,2,3]) - >>> test_prediction = np.float(2) + >>> test_prediction = float(2) >>> tester.mean_squared_error(test_labels, test_prediction) == ( ... TestDecisionTree.helper_mean_squared_error_test(test_labels, ... test_prediction)) @@ -145,11 +145,11 @@ class TestDecisionTree: @param prediction: a floating point value return value: helper_mean_squared_error_test calculates the mean squared error """ - squared_error_sum = np.float(0) + squared_error_sum = float(0) for label in labels: squared_error_sum += (label - prediction) ** 2 - return np.float(squared_error_sum / labels.size) + return float(squared_error_sum / labels.size) def main(): From 2ca695b0fe28519d3449106bff9f9004d93a0b3f Mon Sep 17 00:00:00 2001 From: Shubham Kondekar <40213815+kondekarshubham123@users.noreply.github.com> Date: Tue, 18 Oct 2022 23:35:18 +0530 Subject: [PATCH 391/726] [Matrix] Max area of island problem solved DFS algorithm (#6918) * Maximum area of island program added * Update matrix/max_area_of_island.py Co-authored-by: Caeden * Update matrix/max_area_of_island.py Co-authored-by: Caeden * Update matrix/max_area_of_island.py Co-authored-by: Caeden * Review's comment resolved * max area of island * PR Comments resolved * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Test case fail fix * Grammer correction * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * flake8 issue resolved * some variable name fix * Update matrix/max_area_of_island.py Co-authored-by: Caeden Perelli-Harris * Update matrix/max_area_of_island.py Co-authored-by: Caeden Perelli-Harris * PR, comments resolved * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update matrix/max_area_of_island.py Co-authored-by: Christian Clauss * Update matrix/max_area_of_island.py Co-authored-by: Christian Clauss * PR, comments resolved * Update max_area_of_island.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Typo Co-authored-by: Caeden Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- matrix/max_area_of_island.py | 112 +++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 matrix/max_area_of_island.py diff --git a/matrix/max_area_of_island.py b/matrix/max_area_of_island.py new file mode 100644 index 000000000..40950c303 --- /dev/null +++ b/matrix/max_area_of_island.py @@ -0,0 +1,112 @@ +""" +Given an two dimensional binary matrix grid. An island is a group of 1's (representing +land) connected 4-directionally (horizontal or vertical.) You may assume all four edges +of the grid are surrounded by water. The area of an island is the number of cells with +a value 1 in the island. Return the maximum area of an island in a grid. If there is no +island, return 0. +""" + +matrix = [ + [0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0], + [0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0], + [0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0], +] + + +def is_safe(row: int, col: int, rows: int, cols: int) -> bool: + """ + Checking whether coordinate (row, col) is valid or not. + + >>> is_safe(0, 0, 5, 5) + True + >>> is_safe(-1,-1, 5, 5) + False + """ + return 0 <= row < rows and 0 <= col < cols + + +def depth_first_search(row: int, col: int, seen: set, mat: list[list[int]]) -> int: + """ + Returns the current area of the island + + >>> depth_first_search(0, 0, set(), matrix) + 0 + """ + rows = len(mat) + cols = len(mat[0]) + if is_safe(row, col, rows, cols) and (row, col) not in seen and mat[row][col] == 1: + seen.add((row, col)) + return ( + 1 + + depth_first_search(row + 1, col, seen, mat) + + depth_first_search(row - 1, col, seen, mat) + + depth_first_search(row, col + 1, seen, mat) + + depth_first_search(row, col - 1, seen, mat) + ) + else: + return 0 + + +def find_max_area(mat: list[list[int]]) -> int: + """ + Finds the area of all islands and returns the maximum area. + + >>> find_max_area(matrix) + 6 + """ + seen: set = set() + + max_area = 0 + for row, line in enumerate(mat): + for col, item in enumerate(line): + if item == 1 and (row, col) not in seen: + # Maximizing the area + max_area = max(max_area, depth_first_search(row, col, seen, mat)) + return max_area + + +if __name__ == "__main__": + import doctest + + print(find_max_area(matrix)) # Output -> 6 + + """ + Explanation: + We are allowed to move in four directions (horizontal or vertical) so the possible + in a matrix if we are at x and y position the possible moving are + + Directions are [(x, y+1), (x, y-1), (x+1, y), (x-1, y)] but we need to take care of + boundary cases as well which are x and y can not be smaller than 0 and greater than + the number of rows and columns respectively. + + Visualization + mat = [ + [0,0,A,0,0,0,0,B,0,0,0,0,0], + [0,0,0,0,0,0,0,B,B,B,0,0,0], + [0,C,C,0,D,0,0,0,0,0,0,0,0], + [0,C,0,0,D,D,0,0,E,0,E,0,0], + [0,C,0,0,D,D,0,0,E,E,E,0,0], + [0,0,0,0,0,0,0,0,0,0,E,0,0], + [0,0,0,0,0,0,0,F,F,F,0,0,0], + [0,0,0,0,0,0,0,F,F,0,0,0,0] + ] + + For visualization, I have defined the connected island with letters + by observation, we can see that + A island is of area 1 + B island is of area 4 + C island is of area 4 + D island is of area 5 + E island is of area 6 and + F island is of area 5 + + it has 6 unique islands of mentioned areas + and the maximum of all of them is 6 so we return 6. + """ + + doctest.testmod() From 5bfcab1aa4392e4e3f43927a7fbd8bf6c6815c88 Mon Sep 17 00:00:00 2001 From: Manish Kumar <73126278+ManishKumar219@users.noreply.github.com> Date: Wed, 19 Oct 2022 00:52:38 +0530 Subject: [PATCH 392/726] Create minmax.py (#7409) * Create minmax.py * Update minmax.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: Christian Clauss Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- backtracking/minmax.py | 69 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 backtracking/minmax.py diff --git a/backtracking/minmax.py b/backtracking/minmax.py new file mode 100644 index 000000000..9b87183cf --- /dev/null +++ b/backtracking/minmax.py @@ -0,0 +1,69 @@ +""" +Minimax helps to achieve maximum score in a game by checking all possible moves. + +""" +from __future__ import annotations + +import math + + +def minimax( + depth: int, node_index: int, is_max: bool, scores: list[int], height: float +) -> int: + """ + depth is current depth in game tree. + node_index is index of current node in scores[]. + scores[] contains the leaves of game tree. + height is maximum height of game tree. + + >>> scores = [90, 23, 6, 33, 21, 65, 123, 34423] + >>> height = math.log(len(scores), 2) + >>> minimax(0, 0, True, scores, height) + 65 + >>> minimax(-1, 0, True, scores, height) + Traceback (most recent call last): + ... + ValueError: Depth cannot be less than 0 + >>> minimax(0, 0, True, [], 2) + Traceback (most recent call last): + ... + ValueError: Scores cannot be empty + >>> scores = [3, 5, 2, 9, 12, 5, 23, 23] + >>> height = math.log(len(scores), 2) + >>> minimax(0, 0, True, scores, height) + 12 + """ + + if depth < 0: + raise ValueError("Depth cannot be less than 0") + + if not scores: + raise ValueError("Scores cannot be empty") + + if depth == height: + return scores[node_index] + + return ( + max( + minimax(depth + 1, node_index * 2, False, scores, height), + minimax(depth + 1, node_index * 2 + 1, False, scores, height), + ) + if is_max + else min( + minimax(depth + 1, node_index * 2, True, scores, height), + minimax(depth + 1, node_index * 2 + 1, True, scores, height), + ) + ) + + +def main() -> None: + scores = [90, 23, 6, 33, 21, 65, 123, 34423] + height = math.log(len(scores), 2) + print(f"Optimal value : {minimax(0, 0, True, scores, height)}") + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + main() From b90ec303989b864996e31e021863f8b2c8852054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nadirhan=20=C5=9Eahin?= Date: Tue, 18 Oct 2022 22:55:43 +0300 Subject: [PATCH 393/726] Create combination_sum.py (#7403) * Create combination_sum.py * Update DIRECTORY.md * Adds doctests Co-authored-by: Christian Clauss * Update combination_sum.py * Update combination_sum.py Co-authored-by: Christian Clauss --- DIRECTORY.md | 1 + backtracking/combination_sum.py | 66 +++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 backtracking/combination_sum.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 94ec42832..c1fad8d9d 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -23,6 +23,7 @@ * [All Permutations](backtracking/all_permutations.py) * [All Subsequences](backtracking/all_subsequences.py) * [Coloring](backtracking/coloring.py) + * [Combination Sum](backtracking/combination_sum.py) * [Hamiltonian Cycle](backtracking/hamiltonian_cycle.py) * [Knight Tour](backtracking/knight_tour.py) * [Minimax](backtracking/minimax.py) diff --git a/backtracking/combination_sum.py b/backtracking/combination_sum.py new file mode 100644 index 000000000..f555adb75 --- /dev/null +++ b/backtracking/combination_sum.py @@ -0,0 +1,66 @@ +""" +In the Combination Sum problem, we are given a list consisting of distinct integers. +We need to find all the combinations whose sum equals to target given. +We can use an element more than one. + +Time complexity(Average Case): O(n!) + +Constraints: +1 <= candidates.length <= 30 +2 <= candidates[i] <= 40 +All elements of candidates are distinct. +1 <= target <= 40 +""" + + +def backtrack( + candidates: list, path: list, answer: list, target: int, previous_index: int +) -> None: + """ + A recursive function that searches for possible combinations. Backtracks in case + of a bigger current combination value than the target value. + + Parameters + ---------- + previous_index: Last index from the previous search + target: The value we need to obtain by summing our integers in the path list. + answer: A list of possible combinations + path: Current combination + candidates: A list of integers we can use. + """ + if target == 0: + answer.append(path.copy()) + else: + for index in range(previous_index, len(candidates)): + if target >= candidates[index]: + path.append(candidates[index]) + backtrack(candidates, path, answer, target - candidates[index], index) + path.pop(len(path) - 1) + + +def combination_sum(candidates: list, target: int) -> list: + """ + >>> combination_sum([2, 3, 5], 8) + [[2, 2, 2, 2], [2, 3, 3], [3, 5]] + >>> combination_sum([2, 3, 6, 7], 7) + [[2, 2, 3], [7]] + >>> combination_sum([-8, 2.3, 0], 1) + Traceback (most recent call last): + ... + RecursionError: maximum recursion depth exceeded in comparison + """ + path = [] # type: list[int] + answer = [] # type: list[int] + backtrack(candidates, path, answer, target, 0) + return answer + + +def main() -> None: + print(combination_sum([-8, 2.3, 0], 1)) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + main() From 80ff25ed38e62bcf2e51a4a51bf7bf8f9b03ea11 Mon Sep 17 00:00:00 2001 From: Sai Ganesh Manda <89340753+mvsg2@users.noreply.github.com> Date: Wed, 19 Oct 2022 17:13:26 +0530 Subject: [PATCH 394/726] Update gaussian_naive_bayes.py (#7406) * Update gaussian_naive_bayes.py Just adding in a final metric of accuracy to declare... * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- machine_learning/gaussian_naive_bayes.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/machine_learning/gaussian_naive_bayes.py b/machine_learning/gaussian_naive_bayes.py index 77e732662..7e9a8d7f6 100644 --- a/machine_learning/gaussian_naive_bayes.py +++ b/machine_learning/gaussian_naive_bayes.py @@ -1,7 +1,9 @@ # Gaussian Naive Bayes Example +import time + from matplotlib import pyplot as plt from sklearn.datasets import load_iris -from sklearn.metrics import plot_confusion_matrix +from sklearn.metrics import accuracy_score, plot_confusion_matrix from sklearn.model_selection import train_test_split from sklearn.naive_bayes import GaussianNB @@ -25,7 +27,9 @@ def main(): # Gaussian Naive Bayes nb_model = GaussianNB() - nb_model.fit(x_train, y_train) + time.sleep(2.9) + model_fit = nb_model.fit(x_train, y_train) + y_pred = model_fit.predict(x_test) # Predictions on the test set # Display Confusion Matrix plot_confusion_matrix( @@ -33,12 +37,16 @@ def main(): x_test, y_test, display_labels=iris["target_names"], - cmap="Blues", + cmap="Blues", # although, Greys_r has a better contrast... normalize="true", ) plt.title("Normalized Confusion Matrix - IRIS Dataset") plt.show() + time.sleep(1.8) + final_accuracy = 100 * accuracy_score(y_true=y_test, y_pred=y_pred) + print(f"The overall accuracy of the model is: {round(final_accuracy, 2)}%") + if __name__ == "__main__": main() From b8281d79ef6fdfa11bdd697be3f4a1ef7824cf7f Mon Sep 17 00:00:00 2001 From: Kuldeep Borkar <74557588+KuldeepBorkar@users.noreply.github.com> Date: Wed, 19 Oct 2022 17:16:56 +0530 Subject: [PATCH 395/726] Fixed a typo of 'a' and 'an' and used f string in print statement (#7398) --- boolean_algebra/norgate.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/boolean_algebra/norgate.py b/boolean_algebra/norgate.py index 1c341e8a7..2c27b80af 100644 --- a/boolean_algebra/norgate.py +++ b/boolean_algebra/norgate.py @@ -1,13 +1,15 @@ -""" A NOR Gate is a logic gate in boolean algebra which results to false(0) - if any of the input is 1, and True(1) if both the inputs are 0. - Following is the truth table of an NOR Gate: +""" +A NOR Gate is a logic gate in boolean algebra which results to false(0) +if any of the input is 1, and True(1) if both the inputs are 0. +Following is the truth table of a NOR Gate: | Input 1 | Input 2 | Output | | 0 | 0 | 1 | | 0 | 1 | 0 | | 1 | 0 | 0 | | 1 | 1 | 0 | + +Following is the code implementation of the NOR Gate """ -"""Following is the code implementation of the NOR Gate""" def nor_gate(input_1: int, input_2: int) -> int: @@ -30,11 +32,11 @@ def nor_gate(input_1: int, input_2: int) -> int: def main() -> None: print("Truth Table of NOR Gate:") - print("| Input 1 |", " Input 2 |", " Output |") - print("| 0 |", " 0 | ", nor_gate(0, 0), " |") - print("| 0 |", " 1 | ", nor_gate(0, 1), " |") - print("| 1 |", " 0 | ", nor_gate(1, 0), " |") - print("| 1 |", " 1 | ", nor_gate(1, 1), " |") + print("| Input 1 | Input 2 | Output |") + print(f"| 0 | 0 | {nor_gate(0, 0)} |") + print(f"| 0 | 1 | {nor_gate(0, 1)} |") + print(f"| 1 | 0 | {nor_gate(1, 0)} |") + print(f"| 1 | 1 | {nor_gate(1, 1)} |") if __name__ == "__main__": From 50da472ddcdc2d79d1ad325ec05cda3558802fda Mon Sep 17 00:00:00 2001 From: Kuldeep Borkar <74557588+KuldeepBorkar@users.noreply.github.com> Date: Wed, 19 Oct 2022 22:48:33 +0530 Subject: [PATCH 396/726] Implemented Gelu Function (#7368) * Implemented Gelu Function * Renamed file and added more description to function * Extended the name GELU * Update gaussian_error_linear_unit.py Co-authored-by: Christian Clauss --- maths/gaussian_error_linear_unit.py | 53 +++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 maths/gaussian_error_linear_unit.py diff --git a/maths/gaussian_error_linear_unit.py b/maths/gaussian_error_linear_unit.py new file mode 100644 index 000000000..7b5f87514 --- /dev/null +++ b/maths/gaussian_error_linear_unit.py @@ -0,0 +1,53 @@ +""" +This script demonstrates an implementation of the Gaussian Error Linear Unit function. +* https://en.wikipedia.org/wiki/Activation_function#Comparison_of_activation_functions + +The function takes a vector of K real numbers as input and returns x * sigmoid(1.702*x). +Gaussian Error Linear Unit (GELU) is a high-performing neural network activation +function. + +This script is inspired by a corresponding research paper. +* https://arxiv.org/abs/1606.08415 +""" + +import numpy as np + + +def sigmoid(vector: np.array) -> np.array: + """ + Mathematical function sigmoid takes a vector x of K real numbers as input and + returns 1/ (1 + e^-x). + https://en.wikipedia.org/wiki/Sigmoid_function + + >>> sigmoid(np.array([-1.0, 1.0, 2.0])) + array([0.26894142, 0.73105858, 0.88079708]) + """ + return 1 / (1 + np.exp(-vector)) + + +def gaussian_error_linear_unit(vector: np.array) -> np.array: + """ + Implements the Gaussian Error Linear Unit (GELU) function + + Parameters: + vector (np.array): A numpy array of shape (1,n) + consisting of real values + + Returns: + gelu_vec (np.array): The input numpy array, after applying + gelu. + + Examples: + >>> gaussian_error_linear_unit(np.array([-1.0, 1.0, 2.0])) + array([-0.15420423, 0.84579577, 1.93565862]) + + >>> gaussian_error_linear_unit(np.array([-3])) + array([-0.01807131]) + """ + return vector * sigmoid(1.702 * vector) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 2859d4bf3aa96737a4715c65d4a9051d9c62d24d Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Wed, 19 Oct 2022 16:12:44 -0400 Subject: [PATCH 397/726] Remove references to depreciated QasmSimulator (#7417) * Fix typos * Replace depreciated QasmSimulator in Deutsch-Jozsa algorithm * Replace depreciated QasmSimulator in half adder algorithm * Replace depreciated QasmSimulator in not gate algorithm * Replace depreciated QasmSimulator in full adder algorithm * Simplify qiskit import * Make formatting more consistent * Replace depreciated QasmSimulator in quantum entanglement algorithm * Replace depreciated QasmSimulator in ripple adder algorithm * Replace depreciated QasmSimulator in qubit measure algorithm * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * updating DIRECTORY.md * updating DIRECTORY.md * Remove qiskit import alias for clarity Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 4 ++++ quantum/deutsch_jozsa.py | 28 +++++++++++++++------------- quantum/half_adder.py | 14 +++++++------- quantum/not_gate.py | 14 ++++++++------ quantum/q_full_adder.py | 27 +++++++++++++-------------- quantum/quantum_entanglement.py | 6 +++--- quantum/ripple_adder_classic.py | 16 ++++++++-------- quantum/single_qubit_measure.py | 16 +++++++++------- 8 files changed, 67 insertions(+), 58 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index c1fad8d9d..1fad28798 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -27,6 +27,7 @@ * [Hamiltonian Cycle](backtracking/hamiltonian_cycle.py) * [Knight Tour](backtracking/knight_tour.py) * [Minimax](backtracking/minimax.py) + * [Minmax](backtracking/minmax.py) * [N Queens](backtracking/n_queens.py) * [N Queens Math](backtracking/n_queens_math.py) * [Rat In Maze](backtracking/rat_in_maze.py) @@ -157,6 +158,7 @@ * [Binary Tree Mirror](data_structures/binary_tree/binary_tree_mirror.py) * [Binary Tree Node Sum](data_structures/binary_tree/binary_tree_node_sum.py) * [Binary Tree Traversals](data_structures/binary_tree/binary_tree_traversals.py) + * [Diff Views Of Binary Tree](data_structures/binary_tree/diff_views_of_binary_tree.py) * [Fenwick Tree](data_structures/binary_tree/fenwick_tree.py) * [Inorder Tree Traversal 2022](data_structures/binary_tree/inorder_tree_traversal_2022.py) * [Lazy Segment Tree](data_structures/binary_tree/lazy_segment_tree.py) @@ -513,6 +515,7 @@ * [Gamma](maths/gamma.py) * [Gamma Recursive](maths/gamma_recursive.py) * [Gaussian](maths/gaussian.py) + * [Gaussian Error Linear Unit](maths/gaussian_error_linear_unit.py) * [Greatest Common Divisor](maths/greatest_common_divisor.py) * [Greedy Coin Change](maths/greedy_coin_change.py) * [Hamming Numbers](maths/hamming_numbers.py) @@ -601,6 +604,7 @@ * [Inverse Of Matrix](matrix/inverse_of_matrix.py) * [Matrix Class](matrix/matrix_class.py) * [Matrix Operation](matrix/matrix_operation.py) + * [Max Area Of Island](matrix/max_area_of_island.py) * [Nth Fibonacci Using Matrix Exponentiation](matrix/nth_fibonacci_using_matrix_exponentiation.py) * [Rotate Matrix](matrix/rotate_matrix.py) * [Searching In Sorted Matrix](matrix/searching_in_sorted_matrix.py) diff --git a/quantum/deutsch_jozsa.py b/quantum/deutsch_jozsa.py index d7e2d8335..95c3e65b5 100755 --- a/quantum/deutsch_jozsa.py +++ b/quantum/deutsch_jozsa.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 """ -Deutsch-Josza Algorithm is one of the first examples of a quantum +Deutsch-Jozsa Algorithm is one of the first examples of a quantum algorithm that is exponentially faster than any possible deterministic classical algorithm @@ -22,10 +22,10 @@ References: """ import numpy as np -import qiskit as q +import qiskit -def dj_oracle(case: str, num_qubits: int) -> q.QuantumCircuit: +def dj_oracle(case: str, num_qubits: int) -> qiskit.QuantumCircuit: """ Returns a Quantum Circuit for the Oracle function. The circuit returned can represent balanced or constant function, @@ -33,7 +33,7 @@ def dj_oracle(case: str, num_qubits: int) -> q.QuantumCircuit: """ # This circuit has num_qubits+1 qubits: the size of the input, # plus one output qubit - oracle_qc = q.QuantumCircuit(num_qubits + 1) + oracle_qc = qiskit.QuantumCircuit(num_qubits + 1) # First, let's deal with the case in which oracle is balanced if case == "balanced": @@ -43,7 +43,7 @@ def dj_oracle(case: str, num_qubits: int) -> q.QuantumCircuit: # Next, format 'b' as a binary string of length 'n', padded with zeros: b_str = format(b, f"0{num_qubits}b") # Next, we place the first X-gates. Each digit in our binary string - # correspopnds to a qubit, if the digit is 0, we do nothing, if it's 1 + # corresponds to a qubit, if the digit is 0, we do nothing, if it's 1 # we apply an X-gate to that qubit: for index, bit in enumerate(b_str): if bit == "1": @@ -70,13 +70,15 @@ def dj_oracle(case: str, num_qubits: int) -> q.QuantumCircuit: return oracle_gate -def dj_algorithm(oracle: q.QuantumCircuit, num_qubits: int) -> q.QuantumCircuit: +def dj_algorithm( + oracle: qiskit.QuantumCircuit, num_qubits: int +) -> qiskit.QuantumCircuit: """ - Returns the complete Deustch-Jozsa Quantum Circuit, + Returns the complete Deutsch-Jozsa Quantum Circuit, adding Input & Output registers and Hadamard & Measurement Gates, to the Oracle Circuit passed in arguments """ - dj_circuit = q.QuantumCircuit(num_qubits + 1, num_qubits) + dj_circuit = qiskit.QuantumCircuit(num_qubits + 1, num_qubits) # Set up the output qubit: dj_circuit.x(num_qubits) dj_circuit.h(num_qubits) @@ -95,7 +97,7 @@ def dj_algorithm(oracle: q.QuantumCircuit, num_qubits: int) -> q.QuantumCircuit: return dj_circuit -def deutsch_jozsa(case: str, num_qubits: int) -> q.result.counts.Counts: +def deutsch_jozsa(case: str, num_qubits: int) -> qiskit.result.counts.Counts: """ Main function that builds the circuit using other helper functions, runs the experiment 1000 times & returns the resultant qubit counts @@ -104,14 +106,14 @@ def deutsch_jozsa(case: str, num_qubits: int) -> q.result.counts.Counts: >>> deutsch_jozsa("balanced", 3) {'111': 1000} """ - # Use Aer's qasm_simulator - simulator = q.Aer.get_backend("qasm_simulator") + # Use Aer's simulator + simulator = qiskit.Aer.get_backend("aer_simulator") oracle_gate = dj_oracle(case, num_qubits) dj_circuit = dj_algorithm(oracle_gate, num_qubits) - # Execute the circuit on the qasm simulator - job = q.execute(dj_circuit, simulator, shots=1000) + # Execute the circuit on the simulator + job = qiskit.execute(dj_circuit, simulator, shots=1000) # Return the histogram data of the results of the experiment. return job.result().get_counts(dj_circuit) diff --git a/quantum/half_adder.py b/quantum/half_adder.py index 4af704e64..21a57ddcf 100755 --- a/quantum/half_adder.py +++ b/quantum/half_adder.py @@ -10,10 +10,10 @@ https://en.wikipedia.org/wiki/Adder_(electronics) https://qiskit.org/textbook/ch-states/atoms-computation.html#4.2-Remembering-how-to-add- """ -import qiskit as q +import qiskit -def half_adder(bit0: int, bit1: int) -> q.result.counts.Counts: +def half_adder(bit0: int, bit1: int) -> qiskit.result.counts.Counts: """ >>> half_adder(0, 0) {'00': 1000} @@ -24,10 +24,10 @@ def half_adder(bit0: int, bit1: int) -> q.result.counts.Counts: >>> half_adder(1, 1) {'10': 1000} """ - # Use Aer's qasm_simulator - simulator = q.Aer.get_backend("qasm_simulator") + # Use Aer's simulator + simulator = qiskit.Aer.get_backend("aer_simulator") - qc_ha = q.QuantumCircuit(4, 2) + qc_ha = qiskit.QuantumCircuit(4, 2) # encode inputs in qubits 0 and 1 if bit0 == 1: qc_ha.x(0) @@ -48,9 +48,9 @@ def half_adder(bit0: int, bit1: int) -> q.result.counts.Counts: qc_ha.measure(3, 1) # extract AND value # Execute the circuit on the qasm simulator - job = q.execute(qc_ha, simulator, shots=1000) + job = qiskit.execute(qc_ha, simulator, shots=1000) - # Return the histogram data of the results of the experiment. + # Return the histogram data of the results of the experiment return job.result().get_counts(qc_ha) diff --git a/quantum/not_gate.py b/quantum/not_gate.py index e68a78009..ee23272d7 100644 --- a/quantum/not_gate.py +++ b/quantum/not_gate.py @@ -6,21 +6,23 @@ times and print the total count of the states finally observed. Qiskit Docs: https://qiskit.org/documentation/getting_started.html """ -import qiskit as q +import qiskit -def single_qubit_measure(qubits: int, classical_bits: int) -> q.result.counts.Counts: +def single_qubit_measure( + qubits: int, classical_bits: int +) -> qiskit.result.counts.Counts: """ >>> single_qubit_measure(2, 2) {'11': 1000} >>> single_qubit_measure(4, 4) {'0011': 1000} """ - # Use Aer's qasm_simulator - simulator = q.Aer.get_backend("qasm_simulator") + # Use Aer's simulator + simulator = qiskit.Aer.get_backend("aer_simulator") # Create a Quantum Circuit acting on the q register - circuit = q.QuantumCircuit(qubits, classical_bits) + circuit = qiskit.QuantumCircuit(qubits, classical_bits) # Apply X (NOT) Gate to Qubits 0 & 1 circuit.x(0) @@ -30,7 +32,7 @@ def single_qubit_measure(qubits: int, classical_bits: int) -> q.result.counts.Co circuit.measure([0, 1], [0, 1]) # Execute the circuit on the qasm simulator - job = q.execute(circuit, simulator, shots=1000) + job = qiskit.execute(circuit, simulator, shots=1000) # Return the histogram data of the results of the experiment. return job.result().get_counts(circuit) diff --git a/quantum/q_full_adder.py b/quantum/q_full_adder.py index 597efb834..c6d03d170 100644 --- a/quantum/q_full_adder.py +++ b/quantum/q_full_adder.py @@ -11,7 +11,6 @@ https://www.quantum-inspire.com/kbase/full-adder/ import math import qiskit -from qiskit import Aer, ClassicalRegister, QuantumCircuit, QuantumRegister, execute def quantum_full_adder( @@ -38,25 +37,25 @@ def quantum_full_adder( carry_in: carry in for the circuit. Returns: qiskit.result.counts.Counts: sum result counts. - >>> quantum_full_adder(1,1,1) + >>> quantum_full_adder(1, 1, 1) {'11': 1000} - >>> quantum_full_adder(0,0,1) + >>> quantum_full_adder(0, 0, 1) {'01': 1000} - >>> quantum_full_adder(1,0,1) + >>> quantum_full_adder(1, 0, 1) {'10': 1000} - >>> quantum_full_adder(1,-4,1) + >>> quantum_full_adder(1, -4, 1) Traceback (most recent call last): ... ValueError: inputs must be positive. - >>> quantum_full_adder('q',0,1) + >>> quantum_full_adder('q', 0, 1) Traceback (most recent call last): ... TypeError: inputs must be integers. - >>> quantum_full_adder(0.5,0,1) + >>> quantum_full_adder(0.5, 0, 1) Traceback (most recent call last): ... ValueError: inputs must be exact integers. - >>> quantum_full_adder(0,1,3) + >>> quantum_full_adder(0, 1, 3) Traceback (most recent call last): ... ValueError: inputs must be less or equal to 2. @@ -78,12 +77,12 @@ def quantum_full_adder( raise ValueError("inputs must be less or equal to 2.") # build registers - qr = QuantumRegister(4, "qr") - cr = ClassicalRegister(2, "cr") + qr = qiskit.QuantumRegister(4, "qr") + cr = qiskit.ClassicalRegister(2, "cr") # list the entries entry = [input_1, input_2, carry_in] - quantum_circuit = QuantumCircuit(qr, cr) + quantum_circuit = qiskit.QuantumCircuit(qr, cr) for i in range(0, 3): if entry[i] == 2: @@ -102,11 +101,11 @@ def quantum_full_adder( quantum_circuit.measure([2, 3], cr) # measure the last two qbits - backend = Aer.get_backend("qasm_simulator") - job = execute(quantum_circuit, backend, shots=1000) + backend = qiskit.Aer.get_backend("aer_simulator") + job = qiskit.execute(quantum_circuit, backend, shots=1000) return job.result().get_counts(quantum_circuit) if __name__ == "__main__": - print(f"Total sum count for state is: {quantum_full_adder(1,1,1)}") + print(f"Total sum count for state is: {quantum_full_adder(1, 1, 1)}") diff --git a/quantum/quantum_entanglement.py b/quantum/quantum_entanglement.py index 3d8e27713..08fc32e49 100644 --- a/quantum/quantum_entanglement.py +++ b/quantum/quantum_entanglement.py @@ -29,8 +29,8 @@ def quantum_entanglement(qubits: int = 2) -> qiskit.result.counts.Counts: """ classical_bits = qubits - # Using Aer's qasm_simulator - simulator = qiskit.Aer.get_backend("qasm_simulator") + # Using Aer's simulator + simulator = qiskit.Aer.get_backend("aer_simulator") # Creating a Quantum Circuit acting on the q register circuit = qiskit.QuantumCircuit(qubits, classical_bits) @@ -48,7 +48,7 @@ def quantum_entanglement(qubits: int = 2) -> qiskit.result.counts.Counts: # Now measuring any one qubit would affect other qubits to collapse # their super position and have same state as the measured one. - # Executing the circuit on the qasm simulator + # Executing the circuit on the simulator job = qiskit.execute(circuit, simulator, shots=1000) return job.result().get_counts(circuit) diff --git a/quantum/ripple_adder_classic.py b/quantum/ripple_adder_classic.py index 1d3724476..c07757af7 100644 --- a/quantum/ripple_adder_classic.py +++ b/quantum/ripple_adder_classic.py @@ -2,11 +2,11 @@ # https://en.wikipedia.org/wiki/Adder_(electronics)#Full_adder # https://en.wikipedia.org/wiki/Controlled_NOT_gate -from qiskit import Aer, QuantumCircuit, execute +import qiskit from qiskit.providers import Backend -def store_two_classics(val1: int, val2: int) -> tuple[QuantumCircuit, str, str]: +def store_two_classics(val1: int, val2: int) -> tuple[qiskit.QuantumCircuit, str, str]: """ Generates a Quantum Circuit which stores two classical integers Returns the circuit and binary representation of the integers @@ -21,10 +21,10 @@ def store_two_classics(val1: int, val2: int) -> tuple[QuantumCircuit, str, str]: # We need (3 * number of bits in the larger number)+1 qBits # The second parameter is the number of classical registers, to measure the result - circuit = QuantumCircuit((len(x) * 3) + 1, len(x) + 1) + circuit = qiskit.QuantumCircuit((len(x) * 3) + 1, len(x) + 1) # We are essentially "not-ing" the bits that are 1 - # Reversed because its easier to perform ops on more significant bits + # Reversed because it's easier to perform ops on more significant bits for i in range(len(x)): if x[::-1][i] == "1": circuit.x(i) @@ -36,7 +36,7 @@ def store_two_classics(val1: int, val2: int) -> tuple[QuantumCircuit, str, str]: def full_adder( - circuit: QuantumCircuit, + circuit: qiskit.QuantumCircuit, input1_loc: int, input2_loc: int, carry_in: int, @@ -55,14 +55,14 @@ def full_adder( # The default value for **backend** is the result of a function call which is not # normally recommended and causes flake8-bugbear to raise a B008 error. However, -# in this case, this is accptable because `Aer.get_backend()` is called when the +# in this case, this is acceptable because `Aer.get_backend()` is called when the # function is defined and that same backend is then reused for all function calls. def ripple_adder( val1: int, val2: int, - backend: Backend = Aer.get_backend("qasm_simulator"), # noqa: B008 + backend: Backend = qiskit.Aer.get_backend("aer_simulator"), # noqa: B008 ) -> int: """ Quantum Equivalent of a Ripple Adder Circuit @@ -104,7 +104,7 @@ def ripple_adder( for i in range(len(x) + 1): circuit.measure([(len(x) * 2) + i], [i]) - res = execute(circuit, backend, shots=1).result() + res = qiskit.execute(circuit, backend, shots=1).result() # The result is in binary. Convert it back to int return int(list(res.get_counts())[0], 2) diff --git a/quantum/single_qubit_measure.py b/quantum/single_qubit_measure.py index 7f058c217..605bd8043 100755 --- a/quantum/single_qubit_measure.py +++ b/quantum/single_qubit_measure.py @@ -6,25 +6,27 @@ finally prints the total count of the states finally observed. Qiskit Docs: https://qiskit.org/documentation/getting_started.html """ -import qiskit as q +import qiskit -def single_qubit_measure(qubits: int, classical_bits: int) -> q.result.counts.Counts: +def single_qubit_measure( + qubits: int, classical_bits: int +) -> qiskit.result.counts.Counts: """ >>> single_qubit_measure(1, 1) {'0': 1000} """ - # Use Aer's qasm_simulator - simulator = q.Aer.get_backend("qasm_simulator") + # Use Aer's simulator + simulator = qiskit.Aer.get_backend("aer_simulator") # Create a Quantum Circuit acting on the q register - circuit = q.QuantumCircuit(qubits, classical_bits) + circuit = qiskit.QuantumCircuit(qubits, classical_bits) # Map the quantum measurement to the classical bits circuit.measure([0], [0]) - # Execute the circuit on the qasm simulator - job = q.execute(circuit, simulator, shots=1000) + # Execute the circuit on the simulator + job = qiskit.execute(circuit, simulator, shots=1000) # Return the histogram data of the results of the experiment. return job.result().get_counts(circuit) From 4829fea24dc2c75ffc49571538fc40bce2d7e64b Mon Sep 17 00:00:00 2001 From: Atul Rajput <92659293+AtulRajput01@users.noreply.github.com> Date: Thu, 20 Oct 2022 13:18:28 +0530 Subject: [PATCH 398/726] Create graphs/dijkstra_alternate.py (#7405) * Update dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update dijkstra.py * Update graphs/dijkstra.py Co-authored-by: Christian Clauss * Update graphs/dijkstra.py Co-authored-by: Christian Clauss * Update graphs/dijkstra.py Co-authored-by: Christian Clauss * Update dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update dijkstra.py * Apply suggestions from code review * Create dijkstra_alternate.py * Update dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * int(1e7) * Update dijkstra_alternate.py * Update graphs/dijkstra_alternate.py * sptset --> visited Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- graphs/dijkstra_alternate.py | 98 ++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 graphs/dijkstra_alternate.py diff --git a/graphs/dijkstra_alternate.py b/graphs/dijkstra_alternate.py new file mode 100644 index 000000000..7beef6b04 --- /dev/null +++ b/graphs/dijkstra_alternate.py @@ -0,0 +1,98 @@ +from __future__ import annotations + + +class Graph: + def __init__(self, vertices: int) -> None: + """ + >>> graph = Graph(2) + >>> graph.vertices + 2 + >>> len(graph.graph) + 2 + >>> len(graph.graph[0]) + 2 + """ + self.vertices = vertices + self.graph = [[0] * vertices for _ in range(vertices)] + + def print_solution(self, distances_from_source: list[int]) -> None: + """ + >>> Graph(0).print_solution([]) # doctest: +NORMALIZE_WHITESPACE + Vertex Distance from Source + """ + print("Vertex \t Distance from Source") + for vertex in range(self.vertices): + print(vertex, "\t\t", distances_from_source[vertex]) + + def minimum_distance( + self, distances_from_source: list[int], visited: list[bool] + ) -> int: + """ + A utility function to find the vertex with minimum distance value, from the set + of vertices not yet included in shortest path tree. + + >>> Graph(3).minimum_distance([1, 2, 3], [False, False, True]) + 0 + """ + + # Initialize minimum distance for next node + minimum = 1e7 + min_index = 0 + + # Search not nearest vertex not in the shortest path tree + for vertex in range(self.vertices): + if distances_from_source[vertex] < minimum and visited[vertex] is False: + minimum = distances_from_source[vertex] + min_index = vertex + return min_index + + def dijkstra(self, source: int) -> None: + """ + Function that implements Dijkstra's single source shortest path algorithm for a + graph represented using adjacency matrix representation. + + >>> Graph(4).dijkstra(1) # doctest: +NORMALIZE_WHITESPACE + Vertex Distance from Source + 0 10000000 + 1 0 + 2 10000000 + 3 10000000 + """ + + distances = [int(1e7)] * self.vertices # distances from the source + distances[source] = 0 + visited = [False] * self.vertices + + for _ in range(self.vertices): + u = self.minimum_distance(distances, visited) + visited[u] = True + + # Update dist value of the adjacent vertices + # of the picked vertex only if the current + # distance is greater than new distance and + # the vertex in not in the shortest path tree + for v in range(self.vertices): + if ( + self.graph[u][v] > 0 + and visited[v] is False + and distances[v] > distances[u] + self.graph[u][v] + ): + distances[v] = distances[u] + self.graph[u][v] + + self.print_solution(distances) + + +if __name__ == "__main__": + graph = Graph(9) + graph.graph = [ + [0, 4, 0, 0, 0, 0, 0, 8, 0], + [4, 0, 8, 0, 0, 0, 0, 11, 0], + [0, 8, 0, 7, 0, 4, 0, 0, 2], + [0, 0, 7, 0, 9, 14, 0, 0, 0], + [0, 0, 0, 9, 0, 10, 0, 0, 0], + [0, 0, 4, 14, 10, 0, 2, 0, 0], + [0, 0, 0, 0, 0, 2, 0, 1, 6], + [8, 11, 0, 0, 0, 0, 1, 0, 7], + [0, 0, 2, 0, 0, 0, 6, 7, 0], + ] + graph.dijkstra(0) From 831280ceddb1e37bb0215fd32899a52acbbccf2d Mon Sep 17 00:00:00 2001 From: Alan Paul <57307037+Alanzz@users.noreply.github.com> Date: Thu, 20 Oct 2022 15:57:13 +0530 Subject: [PATCH 399/726] Add quantum_random.py (#7446) * Create quantum_random.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update quantum_random.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update quantum_random.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update quantum/quantum_random.py Co-authored-by: Christian Clauss * Update quantum/quantum_random.py Co-authored-by: Christian Clauss * Update quantum/quantum_random.py Co-authored-by: Christian Clauss * Update quantum_random.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update quantum_random.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * requirements.txt: Add projectq * Update quantum_random.py * Update quantum/quantum_random.py Co-authored-by: Christian Clauss * Update quantum_random.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update quantum_random.py * Update quantum_random.py * Update quantum/quantum_random.py * Update quantum/quantum_random.py * Update quantum_random.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- quantum/quantum_random.py | 30 ++++++++++++++++++++++++++++++ requirements.txt | 1 + 2 files changed, 31 insertions(+) create mode 100644 quantum/quantum_random.py diff --git a/quantum/quantum_random.py b/quantum/quantum_random.py new file mode 100644 index 000000000..01c8faa12 --- /dev/null +++ b/quantum/quantum_random.py @@ -0,0 +1,30 @@ +import doctest + +import projectq +from projectq.ops import H, Measure + + +def get_random_number(quantum_engine: projectq.cengines._main.MainEngine) -> int: + """ + >>> isinstance(get_random_number(projectq.MainEngine()), int) + True + """ + qubit = quantum_engine.allocate_qubit() + H | qubit + Measure | qubit + return int(qubit) + + +if __name__ == "__main__": + doctest.testmod() + + # initialises a new quantum backend + quantum_engine = projectq.MainEngine() + + # Generate a list of 10 random numbers + random_numbers_list = [get_random_number(quantum_engine) for _ in range(10)] + + # Flushes the quantum engine from memory + quantum_engine.flush() + + print("Random numbers", random_numbers_list) diff --git a/requirements.txt b/requirements.txt index b14a3eb01..25d2b4ef9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,6 +7,7 @@ numpy opencv-python pandas pillow +projectq qiskit requests scikit-fuzzy From 42b56f2345ed4566ea48306d3a727f1aa5c88218 Mon Sep 17 00:00:00 2001 From: Modassir Afzal <60973906+Moddy2024@users.noreply.github.com> Date: Fri, 21 Oct 2022 03:29:11 +0530 Subject: [PATCH 400/726] XGBoost Classifier (#7106) * Fixes: #{6551} * Update xgboostclassifier.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update xgboostclassifier.py * Update xgboostclassifier.py * Update xgboostclassifier.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixes: #{6551} * Update xgboostclassifier.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update xgboostclassifier.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update xgboostclassifier.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update xgboostclassifier.py * Fixes : #6551 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixes : #6551 * Fixes : #6551 * Fixes: #6551 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update xgboostclassifier.py * Update xgboostclassifier.py * Update xgboostclassifier.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixes: #6551 * Fixes #6551 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixes: {#6551} * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixes: {#6551} * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixes: #6551 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * FIXES: {#6551} * Fixes : { #6551} * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixes : { #6551} * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixes: { #6551] * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update xgboostclassifier.py * Update xgboostclassifier.py * Apply suggestions from code review * Update xgboostclassifier.py * Update xgboostclassifier.py * Update xgboostclassifier.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixes: { #6551} * Update xgboostclassifier.py * Fixes: { #6551} * Update xgboostclassifier.py * Fixes: ( #6551) * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixes: { #6551} Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- machine_learning/xgboostclassifier.py | 82 +++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 machine_learning/xgboostclassifier.py diff --git a/machine_learning/xgboostclassifier.py b/machine_learning/xgboostclassifier.py new file mode 100644 index 000000000..bb5b48b7a --- /dev/null +++ b/machine_learning/xgboostclassifier.py @@ -0,0 +1,82 @@ +# XGBoost Classifier Example +import numpy as np +from matplotlib import pyplot as plt +from sklearn.datasets import load_iris +from sklearn.metrics import plot_confusion_matrix +from sklearn.model_selection import train_test_split +from xgboost import XGBClassifier + + +def data_handling(data: dict) -> tuple: + # Split dataset into features and target + # data is features + """ + >>> data_handling(({'data':'[5.1, 3.5, 1.4, 0.2]','target':([0])})) + ('[5.1, 3.5, 1.4, 0.2]', [0]) + >>> data_handling( + ... {'data': '[4.9, 3.0, 1.4, 0.2], [4.7, 3.2, 1.3, 0.2]', 'target': ([0, 0])} + ... ) + ('[4.9, 3.0, 1.4, 0.2], [4.7, 3.2, 1.3, 0.2]', [0, 0]) + """ + return (data["data"], data["target"]) + + +def xgboost(features: np.ndarray, target: np.ndarray) -> XGBClassifier: + """ + >>> xgboost(np.array([[5.1, 3.6, 1.4, 0.2]]), np.array([0])) + XGBClassifier(base_score=0.5, booster='gbtree', callbacks=None, + colsample_bylevel=1, colsample_bynode=1, colsample_bytree=1, + early_stopping_rounds=None, enable_categorical=False, + eval_metric=None, gamma=0, gpu_id=-1, grow_policy='depthwise', + importance_type=None, interaction_constraints='', + learning_rate=0.300000012, max_bin=256, max_cat_to_onehot=4, + max_delta_step=0, max_depth=6, max_leaves=0, min_child_weight=1, + missing=nan, monotone_constraints='()', n_estimators=100, + n_jobs=0, num_parallel_tree=1, predictor='auto', random_state=0, + reg_alpha=0, reg_lambda=1, ...) + """ + classifier = XGBClassifier() + classifier.fit(features, target) + return classifier + + +def main() -> None: + + """ + >>> main() + + Url for the algorithm: + https://xgboost.readthedocs.io/en/stable/ + Iris type dataset is used to demonstrate algorithm. + """ + + # Load Iris dataset + iris = load_iris() + features, targets = data_handling(iris) + x_train, x_test, y_train, y_test = train_test_split( + features, targets, test_size=0.25 + ) + + names = iris["target_names"] + + # Create an XGBoost Classifier from the training data + xgboost_classifier = xgboost(x_train, y_train) + + # Display the confusion matrix of the classifier with both training and test sets + plot_confusion_matrix( + xgboost_classifier, + x_test, + y_test, + display_labels=names, + cmap="Blues", + normalize="true", + ) + plt.title("Normalized Confusion Matrix - IRIS Dataset") + plt.show() + + +if __name__ == "__main__": + import doctest + + doctest.testmod(verbose=True) + main() From 717f0e46d950060f2147f022f65b7e44e72cfdd8 Mon Sep 17 00:00:00 2001 From: Chris O <46587501+ChrisO345@users.noreply.github.com> Date: Fri, 21 Oct 2022 20:03:57 +1300 Subject: [PATCH 401/726] Maclaurin series approximation of sin (#7451) * added maclaurin_sin.py function * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * added type hints and fixed line overflows * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * removed incompatable type examples * Update maths/maclaurin_sin.py Co-authored-by: Caeden Perelli-Harris * changed error details * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fixed grammatical errors * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * improved function accuracy and added test case * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update maths/maclaurin_sin.py Co-authored-by: Christian Clauss * removed redundant return * fixed pytest * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Caeden Perelli-Harris Co-authored-by: Christian Clauss --- maths/maclaurin_sin.py | 64 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 maths/maclaurin_sin.py diff --git a/maths/maclaurin_sin.py b/maths/maclaurin_sin.py new file mode 100644 index 000000000..3c27ccf63 --- /dev/null +++ b/maths/maclaurin_sin.py @@ -0,0 +1,64 @@ +""" +https://en.wikipedia.org/wiki/Taylor_series#Trigonometric_functions +""" +from math import factorial, pi + + +def maclaurin_sin(theta: float, accuracy: int = 30) -> float: + """ + Finds the maclaurin approximation of sin + + :param theta: the angle to which sin is found + :param accuracy: the degree of accuracy wanted minimum ~ 1.5 theta + :return: the value of sine in radians + + + >>> from math import isclose, sin + >>> all(isclose(maclaurin_sin(x, 50), sin(x)) for x in range(-25, 25)) + True + >>> maclaurin_sin(10) + -0.544021110889369 + >>> maclaurin_sin(-10) + 0.5440211108893703 + >>> maclaurin_sin(10, 15) + -0.5440211108893689 + >>> maclaurin_sin(-10, 15) + 0.5440211108893703 + >>> maclaurin_sin("10") + Traceback (most recent call last): + ... + ValueError: maclaurin_sin() requires either an int or float for theta + >>> maclaurin_sin(10, -30) + Traceback (most recent call last): + ... + ValueError: maclaurin_sin() requires a positive int for accuracy + >>> maclaurin_sin(10, 30.5) + Traceback (most recent call last): + ... + ValueError: maclaurin_sin() requires a positive int for accuracy + >>> maclaurin_sin(10, "30") + Traceback (most recent call last): + ... + ValueError: maclaurin_sin() requires a positive int for accuracy + """ + + if not isinstance(theta, (int, float)): + raise ValueError("maclaurin_sin() requires either an int or float for theta") + + if not isinstance(accuracy, int) or accuracy <= 0: + raise ValueError("maclaurin_sin() requires a positive int for accuracy") + + theta = float(theta) + div = theta // (2 * pi) + theta -= 2 * div * pi + return sum( + (((-1) ** r) * ((theta ** (2 * r + 1)) / factorial(2 * r + 1))) + for r in range(accuracy) + ) + + +if __name__ == "__main__": + print(maclaurin_sin(10)) + print(maclaurin_sin(-10)) + print(maclaurin_sin(10, 15)) + print(maclaurin_sin(-10, 15)) From cc10b20beb8f0b10b50c84bd523bf41095fe9f37 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Sat, 22 Oct 2022 07:33:51 -0400 Subject: [PATCH 402/726] Remove some print statements within algorithmic functions (#7499) * Remove commented-out print statements in algorithmic functions * Encapsulate non-algorithmic code in __main__ * Remove unused print_matrix function * Remove print statement in __init__ * Remove print statement from doctest * Encapsulate non-algorithmic code in __main__ * Modify algorithm to return instead of print * Encapsulate non-algorithmic code in __main__ * Refactor data_safety_checker to return instead of print * updating DIRECTORY.md * updating DIRECTORY.md * Apply suggestions from code review * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- DIRECTORY.md | 4 + cellular_automata/game_of_life.py | 1 - digital_image_processing/index_calculation.py | 1 - divide_and_conquer/max_subarray_sum.py | 12 +-- .../strassen_matrix_multiplication.py | 3 +- dynamic_programming/longest_sub_array.py | 1 - dynamic_programming/max_non_adjacent_sum.py | 2 +- dynamic_programming/subset_generation.py | 9 +- dynamic_programming/sum_of_subset.py | 14 ++- machine_learning/forecasting/run.py | 86 ++++++++++--------- 10 files changed, 69 insertions(+), 64 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 1fad28798..70644d063 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -360,6 +360,7 @@ * [Dijkstra](graphs/dijkstra.py) * [Dijkstra 2](graphs/dijkstra_2.py) * [Dijkstra Algorithm](graphs/dijkstra_algorithm.py) + * [Dijkstra Alternate](graphs/dijkstra_alternate.py) * [Dinic](graphs/dinic.py) * [Directed And Undirected (Weighted) Graph](graphs/directed_and_undirected_(weighted)_graph.py) * [Edmonds Karp Multiple Source And Sink](graphs/edmonds_karp_multiple_source_and_sink.py) @@ -460,6 +461,7 @@ * [Similarity Search](machine_learning/similarity_search.py) * [Support Vector Machines](machine_learning/support_vector_machines.py) * [Word Frequency Functions](machine_learning/word_frequency_functions.py) + * [Xgboostclassifier](machine_learning/xgboostclassifier.py) ## Maths * [3N Plus 1](maths/3n_plus_1.py) @@ -534,6 +536,7 @@ * [Line Length](maths/line_length.py) * [Lucas Lehmer Primality Test](maths/lucas_lehmer_primality_test.py) * [Lucas Series](maths/lucas_series.py) + * [Maclaurin Sin](maths/maclaurin_sin.py) * [Matrix Exponentiation](maths/matrix_exponentiation.py) * [Max Sum Sliding Window](maths/max_sum_sliding_window.py) * [Median Of Two Arrays](maths/median_of_two_arrays.py) @@ -936,6 +939,7 @@ * [Not Gate](quantum/not_gate.py) * [Q Full Adder](quantum/q_full_adder.py) * [Quantum Entanglement](quantum/quantum_entanglement.py) + * [Quantum Random](quantum/quantum_random.py) * [Ripple Adder Classic](quantum/ripple_adder_classic.py) * [Single Qubit Measure](quantum/single_qubit_measure.py) diff --git a/cellular_automata/game_of_life.py b/cellular_automata/game_of_life.py index c5324da73..8e5470251 100644 --- a/cellular_automata/game_of_life.py +++ b/cellular_automata/game_of_life.py @@ -66,7 +66,6 @@ def run(canvas: list[list[bool]]) -> list[list[bool]]: next_gen_canvas = np.array(create_canvas(current_canvas.shape[0])) for r, row in enumerate(current_canvas): for c, pt in enumerate(row): - # print(r-1,r+2,c-1,c+2) next_gen_canvas[r][c] = __judge_point( pt, current_canvas[r - 1 : r + 2, c - 1 : c + 2] ) diff --git a/digital_image_processing/index_calculation.py b/digital_image_processing/index_calculation.py index 01cd79fc1..be1855e99 100644 --- a/digital_image_processing/index_calculation.py +++ b/digital_image_processing/index_calculation.py @@ -105,7 +105,6 @@ class IndexCalculation: """ def __init__(self, red=None, green=None, blue=None, red_edge=None, nir=None): - # print("Numpy version: " + np.__version__) self.set_matricies(red=red, green=green, blue=blue, red_edge=red_edge, nir=nir) def set_matricies(self, red=None, green=None, blue=None, red_edge=None, nir=None): diff --git a/divide_and_conquer/max_subarray_sum.py b/divide_and_conquer/max_subarray_sum.py index 43f58086e..f23e81719 100644 --- a/divide_and_conquer/max_subarray_sum.py +++ b/divide_and_conquer/max_subarray_sum.py @@ -69,8 +69,10 @@ def max_subarray_sum(array, left, right): return max(left_half_sum, right_half_sum, cross_sum) -array = [-2, -5, 6, -2, -3, 1, 5, -6] -array_length = len(array) -print( - "Maximum sum of contiguous subarray:", max_subarray_sum(array, 0, array_length - 1) -) +if __name__ == "__main__": + array = [-2, -5, 6, -2, -3, 1, 5, -6] + array_length = len(array) + print( + "Maximum sum of contiguous subarray:", + max_subarray_sum(array, 0, array_length - 1), + ) diff --git a/divide_and_conquer/strassen_matrix_multiplication.py b/divide_and_conquer/strassen_matrix_multiplication.py index 0ee426e4b..371605d6d 100644 --- a/divide_and_conquer/strassen_matrix_multiplication.py +++ b/divide_and_conquer/strassen_matrix_multiplication.py @@ -68,8 +68,7 @@ def matrix_dimensions(matrix: list) -> tuple[int, int]: def print_matrix(matrix: list) -> None: - for i in range(len(matrix)): - print(matrix[i]) + print("\n".join(str(line) for line in matrix)) def actual_strassen(matrix_a: list, matrix_b: list) -> list: diff --git a/dynamic_programming/longest_sub_array.py b/dynamic_programming/longest_sub_array.py index 30159a138..b477acf61 100644 --- a/dynamic_programming/longest_sub_array.py +++ b/dynamic_programming/longest_sub_array.py @@ -14,7 +14,6 @@ class SubArray: def __init__(self, arr): # we need a list not a string, so do something to change the type self.array = arr.split(",") - print(("the input array is:", self.array)) def solve_sub_array(self): rear = [int(self.array[0])] * len(self.array) diff --git a/dynamic_programming/max_non_adjacent_sum.py b/dynamic_programming/max_non_adjacent_sum.py index 5362b22ca..e3cc23f49 100644 --- a/dynamic_programming/max_non_adjacent_sum.py +++ b/dynamic_programming/max_non_adjacent_sum.py @@ -7,7 +7,7 @@ def maximum_non_adjacent_sum(nums: list[int]) -> int: """ Find the maximum non-adjacent sum of the integers in the nums input list - >>> print(maximum_non_adjacent_sum([1, 2, 3])) + >>> maximum_non_adjacent_sum([1, 2, 3]) 4 >>> maximum_non_adjacent_sum([1, 5, 3, 7, 2, 2, 6]) 18 diff --git a/dynamic_programming/subset_generation.py b/dynamic_programming/subset_generation.py index 4781b23b3..819fd8106 100644 --- a/dynamic_programming/subset_generation.py +++ b/dynamic_programming/subset_generation.py @@ -37,7 +37,8 @@ def print_combination(arr, n, r): combination_util(arr, n, r, 0, data, 0) -# Driver function to check for above function -arr = [10, 20, 30, 40, 50] -print_combination(arr, len(arr), 3) -# This code is contributed by Ambuj sahu +if __name__ == "__main__": + # Driver code to check the function above + arr = [10, 20, 30, 40, 50] + print_combination(arr, len(arr), 3) + # This code is contributed by Ambuj sahu diff --git a/dynamic_programming/sum_of_subset.py b/dynamic_programming/sum_of_subset.py index 77672b0b8..96ebcf583 100644 --- a/dynamic_programming/sum_of_subset.py +++ b/dynamic_programming/sum_of_subset.py @@ -1,13 +1,14 @@ -def is_sum_subset(arr, arr_len, required_sum): +def is_sum_subset(arr: list[int], required_sum: int) -> bool: """ - >>> is_sum_subset([2, 4, 6, 8], 4, 5) + >>> is_sum_subset([2, 4, 6, 8], 5) False - >>> is_sum_subset([2, 4, 6, 8], 4, 14) + >>> is_sum_subset([2, 4, 6, 8], 14) True """ # a subset value says 1 if that subset sum can be formed else 0 # initially no subsets can be formed hence False/0 - subset = [[False for i in range(required_sum + 1)] for i in range(arr_len + 1)] + arr_len = len(arr) + subset = [[False] * (required_sum + 1) for _ in range(arr_len + 1)] # for each arr value, a sum of zero(0) can be formed by not taking any element # hence True/1 @@ -25,10 +26,7 @@ def is_sum_subset(arr, arr_len, required_sum): if arr[i - 1] <= j: subset[i][j] = subset[i - 1][j] or subset[i - 1][j - arr[i - 1]] - # uncomment to print the subset - # for i in range(arrLen+1): - # print(subset[i]) - print(subset[arr_len][required_sum]) + return subset[arr_len][required_sum] if __name__ == "__main__": diff --git a/machine_learning/forecasting/run.py b/machine_learning/forecasting/run.py index b11a23012..0909b76d8 100644 --- a/machine_learning/forecasting/run.py +++ b/machine_learning/forecasting/run.py @@ -1,7 +1,7 @@ """ this is code for forecasting but i modified it and used it for safety checker of data -for ex: you have a online shop and for some reason some data are +for ex: you have an online shop and for some reason some data are missing (the amount of data that u expected are not supposed to be) then we can use it *ps : 1. ofc we can use normal statistic method but in this case @@ -91,14 +91,14 @@ def interquartile_range_checker(train_user: list) -> float: return low_lim -def data_safety_checker(list_vote: list, actual_result: float) -> None: +def data_safety_checker(list_vote: list, actual_result: float) -> bool: """ Used to review all the votes (list result prediction) and compare it to the actual result. input : list of predictions output : print whether it's safe or not - >>> data_safety_checker([2,3,4],5.0) - Today's data is not safe. + >>> data_safety_checker([2, 3, 4], 5.0) + False """ safe = 0 not_safe = 0 @@ -107,50 +107,54 @@ def data_safety_checker(list_vote: list, actual_result: float) -> None: safe = not_safe + 1 else: if abs(abs(i) - abs(actual_result)) <= 0.1: - safe = safe + 1 + safe += 1 else: - not_safe = not_safe + 1 - print(f"Today's data is {'not ' if safe <= not_safe else ''}safe.") + not_safe += 1 + return safe > not_safe -# data_input_df = pd.read_csv("ex_data.csv", header=None) -data_input = [[18231, 0.0, 1], [22621, 1.0, 2], [15675, 0.0, 3], [23583, 1.0, 4]] -data_input_df = pd.DataFrame(data_input, columns=["total_user", "total_even", "days"]) +if __name__ == "__main__": + # data_input_df = pd.read_csv("ex_data.csv", header=None) + data_input = [[18231, 0.0, 1], [22621, 1.0, 2], [15675, 0.0, 3], [23583, 1.0, 4]] + data_input_df = pd.DataFrame( + data_input, columns=["total_user", "total_even", "days"] + ) -""" -data column = total user in a day, how much online event held in one day, -what day is that(sunday-saturday) -""" + """ + data column = total user in a day, how much online event held in one day, + what day is that(sunday-saturday) + """ -# start normalization -normalize_df = Normalizer().fit_transform(data_input_df.values) -# split data -total_date = normalize_df[:, 2].tolist() -total_user = normalize_df[:, 0].tolist() -total_match = normalize_df[:, 1].tolist() + # start normalization + normalize_df = Normalizer().fit_transform(data_input_df.values) + # split data + total_date = normalize_df[:, 2].tolist() + total_user = normalize_df[:, 0].tolist() + total_match = normalize_df[:, 1].tolist() -# for svr (input variable = total date and total match) -x = normalize_df[:, [1, 2]].tolist() -x_train = x[: len(x) - 1] -x_test = x[len(x) - 1 :] + # for svr (input variable = total date and total match) + x = normalize_df[:, [1, 2]].tolist() + x_train = x[: len(x) - 1] + x_test = x[len(x) - 1 :] -# for linear reression & sarimax -trn_date = total_date[: len(total_date) - 1] -trn_user = total_user[: len(total_user) - 1] -trn_match = total_match[: len(total_match) - 1] + # for linear regression & sarimax + trn_date = total_date[: len(total_date) - 1] + trn_user = total_user[: len(total_user) - 1] + trn_match = total_match[: len(total_match) - 1] -tst_date = total_date[len(total_date) - 1 :] -tst_user = total_user[len(total_user) - 1 :] -tst_match = total_match[len(total_match) - 1 :] + tst_date = total_date[len(total_date) - 1 :] + tst_user = total_user[len(total_user) - 1 :] + tst_match = total_match[len(total_match) - 1 :] + # voting system with forecasting + res_vote = [ + linear_regression_prediction( + trn_date, trn_user, trn_match, tst_date, tst_match + ), + sarimax_predictor(trn_user, trn_match, tst_match), + support_vector_regressor(x_train, x_test, trn_user), + ] -# voting system with forecasting -res_vote = [] -res_vote.append( - linear_regression_prediction(trn_date, trn_user, trn_match, tst_date, tst_match) -) -res_vote.append(sarimax_predictor(trn_user, trn_match, tst_match)) -res_vote.append(support_vector_regressor(x_train, x_test, trn_user)) - -# check the safety of todays'data^^ -data_safety_checker(res_vote, tst_user) + # check the safety of today's data + not_str = "" if data_safety_checker(res_vote, tst_user) else "not " + print("Today's data is {not_str}safe.") From a5dd07c3707a0d3ebde0321ce7984082b3d322ff Mon Sep 17 00:00:00 2001 From: Chris O <46587501+ChrisO345@users.noreply.github.com> Date: Sun, 23 Oct 2022 05:17:07 +1300 Subject: [PATCH 403/726] Maclaurin approximation of cos (#7507) * renamed maclaurin_sin.py to maclaurin_series.py and included function for cos approximation * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * attempt to fix pytest error Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/maclaurin_series.py | 121 ++++++++++++++++++++++++++++++++++++++ maths/maclaurin_sin.py | 64 -------------------- 2 files changed, 121 insertions(+), 64 deletions(-) create mode 100644 maths/maclaurin_series.py delete mode 100644 maths/maclaurin_sin.py diff --git a/maths/maclaurin_series.py b/maths/maclaurin_series.py new file mode 100644 index 000000000..57edc90bf --- /dev/null +++ b/maths/maclaurin_series.py @@ -0,0 +1,121 @@ +""" +https://en.wikipedia.org/wiki/Taylor_series#Trigonometric_functions +""" +from math import factorial, pi + + +def maclaurin_sin(theta: float, accuracy: int = 30) -> float: + """ + Finds the maclaurin approximation of sin + + :param theta: the angle to which sin is found + :param accuracy: the degree of accuracy wanted minimum + :return: the value of sine in radians + + + >>> from math import isclose, sin + >>> all(isclose(maclaurin_sin(x, 50), sin(x)) for x in range(-25, 25)) + True + >>> maclaurin_sin(10) + -0.544021110889369 + >>> maclaurin_sin(-10) + 0.5440211108893703 + >>> maclaurin_sin(10, 15) + -0.5440211108893689 + >>> maclaurin_sin(-10, 15) + 0.5440211108893703 + >>> maclaurin_sin("10") + Traceback (most recent call last): + ... + ValueError: maclaurin_sin() requires either an int or float for theta + >>> maclaurin_sin(10, -30) + Traceback (most recent call last): + ... + ValueError: maclaurin_sin() requires a positive int for accuracy + >>> maclaurin_sin(10, 30.5) + Traceback (most recent call last): + ... + ValueError: maclaurin_sin() requires a positive int for accuracy + >>> maclaurin_sin(10, "30") + Traceback (most recent call last): + ... + ValueError: maclaurin_sin() requires a positive int for accuracy + """ + + if not isinstance(theta, (int, float)): + raise ValueError("maclaurin_sin() requires either an int or float for theta") + + if not isinstance(accuracy, int) or accuracy <= 0: + raise ValueError("maclaurin_sin() requires a positive int for accuracy") + + theta = float(theta) + div = theta // (2 * pi) + theta -= 2 * div * pi + return sum( + (((-1) ** r) * ((theta ** (2 * r + 1)) / factorial(2 * r + 1))) + for r in range(accuracy) + ) + + +def maclaurin_cos(theta: float, accuracy: int = 30) -> float: + """ + Finds the maclaurin approximation of cos + + :param theta: the angle to which cos is found + :param accuracy: the degree of accuracy wanted + :return: the value of cosine in radians + + + >>> from math import isclose, cos + >>> all(isclose(maclaurin_cos(x, 50), cos(x)) for x in range(-25, 25)) + True + >>> maclaurin_cos(5) + 0.28366218546322675 + >>> maclaurin_cos(-5) + 0.2836621854632266 + >>> maclaurin_cos(10, 15) + -0.8390715290764525 + >>> maclaurin_cos(-10, 15) + -0.8390715290764521 + >>> maclaurin_cos("10") + Traceback (most recent call last): + ... + ValueError: maclaurin_cos() requires either an int or float for theta + >>> maclaurin_cos(10, -30) + Traceback (most recent call last): + ... + ValueError: maclaurin_cos() requires a positive int for accuracy + >>> maclaurin_cos(10, 30.5) + Traceback (most recent call last): + ... + ValueError: maclaurin_cos() requires a positive int for accuracy + >>> maclaurin_cos(10, "30") + Traceback (most recent call last): + ... + ValueError: maclaurin_cos() requires a positive int for accuracy + """ + + if not isinstance(theta, (int, float)): + raise ValueError("maclaurin_cos() requires either an int or float for theta") + + if not isinstance(accuracy, int) or accuracy <= 0: + raise ValueError("maclaurin_cos() requires a positive int for accuracy") + + theta = float(theta) + div = theta // (2 * pi) + theta -= 2 * div * pi + return sum( + (((-1) ** r) * ((theta ** (2 * r)) / factorial(2 * r))) for r in range(accuracy) + ) + + +if __name__ == "__main__": + print(maclaurin_sin(10)) + print(maclaurin_sin(-10)) + print(maclaurin_sin(10, 15)) + print(maclaurin_sin(-10, 15)) + + print(maclaurin_cos(5)) + print(maclaurin_cos(-5)) + print(maclaurin_cos(10, 15)) + print(maclaurin_cos(-10, 15)) diff --git a/maths/maclaurin_sin.py b/maths/maclaurin_sin.py deleted file mode 100644 index 3c27ccf63..000000000 --- a/maths/maclaurin_sin.py +++ /dev/null @@ -1,64 +0,0 @@ -""" -https://en.wikipedia.org/wiki/Taylor_series#Trigonometric_functions -""" -from math import factorial, pi - - -def maclaurin_sin(theta: float, accuracy: int = 30) -> float: - """ - Finds the maclaurin approximation of sin - - :param theta: the angle to which sin is found - :param accuracy: the degree of accuracy wanted minimum ~ 1.5 theta - :return: the value of sine in radians - - - >>> from math import isclose, sin - >>> all(isclose(maclaurin_sin(x, 50), sin(x)) for x in range(-25, 25)) - True - >>> maclaurin_sin(10) - -0.544021110889369 - >>> maclaurin_sin(-10) - 0.5440211108893703 - >>> maclaurin_sin(10, 15) - -0.5440211108893689 - >>> maclaurin_sin(-10, 15) - 0.5440211108893703 - >>> maclaurin_sin("10") - Traceback (most recent call last): - ... - ValueError: maclaurin_sin() requires either an int or float for theta - >>> maclaurin_sin(10, -30) - Traceback (most recent call last): - ... - ValueError: maclaurin_sin() requires a positive int for accuracy - >>> maclaurin_sin(10, 30.5) - Traceback (most recent call last): - ... - ValueError: maclaurin_sin() requires a positive int for accuracy - >>> maclaurin_sin(10, "30") - Traceback (most recent call last): - ... - ValueError: maclaurin_sin() requires a positive int for accuracy - """ - - if not isinstance(theta, (int, float)): - raise ValueError("maclaurin_sin() requires either an int or float for theta") - - if not isinstance(accuracy, int) or accuracy <= 0: - raise ValueError("maclaurin_sin() requires a positive int for accuracy") - - theta = float(theta) - div = theta // (2 * pi) - theta -= 2 * div * pi - return sum( - (((-1) ** r) * ((theta ** (2 * r + 1)) / factorial(2 * r + 1))) - for r in range(accuracy) - ) - - -if __name__ == "__main__": - print(maclaurin_sin(10)) - print(maclaurin_sin(-10)) - print(maclaurin_sin(10, 15)) - print(maclaurin_sin(-10, 15)) From ed127032b303d06f2c1ceefd58a8680bb4c2ce50 Mon Sep 17 00:00:00 2001 From: Akshit Gulyan <103456810+AkshitGulyan@users.noreply.github.com> Date: Sun, 23 Oct 2022 09:59:10 +0530 Subject: [PATCH 404/726] Created sum_of_harmonic_series.py (#7504) * Created sum_of_harmonic_series.py Here in this code the formula for Harmonic sum is not used, Sum of the series is calculated by creating a list of the elements in the given Harmonic series and adding all the elements of that list ! * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update maths/sum_of_harmonic_series.py Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> * Update maths/sum_of_harmonic_series.py Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> * Update maths/sum_of_harmonic_series.py Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update maths/sum_of_harmonic_series.py Co-authored-by: Christian Clauss * Update maths/sum_of_harmonic_series.py Co-authored-by: Christian Clauss * Update maths/sum_of_harmonic_series.py Co-authored-by: Christian Clauss * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update sum_of_harmonic_series.py * Add doctests * Update sum_of_harmonic_series.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> Co-authored-by: Christian Clauss --- maths/sum_of_harmonic_series.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 maths/sum_of_harmonic_series.py diff --git a/maths/sum_of_harmonic_series.py b/maths/sum_of_harmonic_series.py new file mode 100644 index 000000000..9e0d6b19b --- /dev/null +++ b/maths/sum_of_harmonic_series.py @@ -0,0 +1,29 @@ +def sum_of_harmonic_progression( + first_term: float, common_difference: float, number_of_terms: int +) -> float: + """ + https://en.wikipedia.org/wiki/Harmonic_progression_(mathematics) + + Find the sum of n terms in an harmonic progression. The calculation starts with the + first_term and loops adding the common difference of Arithmetic Progression by which + the given Harmonic Progression is linked. + + >>> sum_of_harmonic_progression(1 / 2, 2, 2) + 0.75 + >>> sum_of_harmonic_progression(1 / 5, 5, 5) + 0.45666666666666667 + """ + arithmetic_progression = [1 / first_term] + first_term = 1 / first_term + for _ in range(number_of_terms - 1): + first_term += common_difference + arithmetic_progression.append(first_term) + harmonic_series = [1 / step for step in arithmetic_progression] + return sum(harmonic_series) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + print(sum_of_harmonic_progression(1 / 2, 2, 2)) From f32f78a9e0a4c2c1e2e9c985fd2375e7ede8925c Mon Sep 17 00:00:00 2001 From: Abhishek Chakraborty Date: Sun, 23 Oct 2022 03:42:02 -0700 Subject: [PATCH 405/726] Basic string grammar fix (#7534) * Grammar edit * Flake8 consistency fix * Apply suggestions from code review Co-authored-by: Christian Clauss --- genetic_algorithm/basic_string.py | 54 +++++++++++++++---------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/genetic_algorithm/basic_string.py b/genetic_algorithm/basic_string.py index d2d305189..3227adf53 100644 --- a/genetic_algorithm/basic_string.py +++ b/genetic_algorithm/basic_string.py @@ -9,15 +9,15 @@ from __future__ import annotations import random -# Maximum size of the population. bigger could be faster but is more memory expensive +# Maximum size of the population. Bigger could be faster but is more memory expensive. N_POPULATION = 200 -# Number of elements selected in every generation for evolution the selection takes -# place from the best to the worst of that generation must be smaller than N_POPULATION +# Number of elements selected in every generation of evolution. The selection takes +# place from best to worst of that generation and must be smaller than N_POPULATION. N_SELECTED = 50 -# Probability that an element of a generation can mutate changing one of its genes this -# guarantees that all genes will be used during evolution +# Probability that an element of a generation can mutate, changing one of its genes. +# This will guarantee that all genes will be used during evolution. MUTATION_PROBABILITY = 0.4 -# just a seed to improve randomness required by the algorithm +# Just a seed to improve randomness required by the algorithm. random.seed(random.randint(0, 1000)) @@ -56,20 +56,20 @@ def basic(target: str, genes: list[str], debug: bool = True) -> tuple[int, int, f"{not_in_genes_list} is not in genes list, evolution cannot converge" ) - # Generate random starting population + # Generate random starting population. population = [] for _ in range(N_POPULATION): population.append("".join([random.choice(genes) for i in range(len(target))])) - # Just some logs to know what the algorithms is doing + # Just some logs to know what the algorithms is doing. generation, total_population = 0, 0 - # This loop will end when we will find a perfect match for our target + # This loop will end when we find a perfect match for our target. while True: generation += 1 total_population += len(population) - # Random population created now it's time to evaluate + # Random population created. Now it's time to evaluate. def evaluate(item: str, main_target: str = target) -> tuple[str, float]: """ Evaluate how similar the item is with the target by just @@ -92,17 +92,17 @@ def basic(target: str, genes: list[str], debug: bool = True) -> tuple[int, int, # concurrent.futures.wait(futures) # population_score = [item.result() for item in futures] # - # but with a simple algorithm like this will probably be slower - # we just need to call evaluate for every item inside population + # but with a simple algorithm like this, it will probably be slower. + # We just need to call evaluate for every item inside the population. population_score = [evaluate(item) for item in population] - # Check if there is a matching evolution + # Check if there is a matching evolution. population_score = sorted(population_score, key=lambda x: x[1], reverse=True) if population_score[0][0] == target: return (generation, total_population, population_score[0][0]) - # Print the Best result every 10 generation - # just to know that the algorithm is working + # Print the best result every 10 generation. + # Just to know that the algorithm is working. if debug and generation % 10 == 0: print( f"\nGeneration: {generation}" @@ -111,21 +111,21 @@ def basic(target: str, genes: list[str], debug: bool = True) -> tuple[int, int, f"\nBest string: {population_score[0][0]}" ) - # Flush the old population keeping some of the best evolutions - # Keeping this avoid regression of evolution + # Flush the old population, keeping some of the best evolutions. + # Keeping this avoid regression of evolution. population_best = population[: int(N_POPULATION / 3)] population.clear() population.extend(population_best) - # Normalize population score from 0 to 1 + # Normalize population score to be between 0 and 1. population_score = [ (item, score / len(target)) for item, score in population_score ] - # Select, Crossover and Mutate a new population + # Select, crossover and mutate a new population. def select(parent_1: tuple[str, float]) -> list[str]: """Select the second parent and generate new population""" pop = [] - # Generate more child proportionally to the fitness score + # Generate more children proportionally to the fitness score. child_n = int(parent_1[1] * 100) + 1 child_n = 10 if child_n >= 10 else child_n for _ in range(child_n): @@ -134,32 +134,32 @@ def basic(target: str, genes: list[str], debug: bool = True) -> tuple[int, int, ][0] child_1, child_2 = crossover(parent_1[0], parent_2) - # Append new string to the population list + # Append new string to the population list. pop.append(mutate(child_1)) pop.append(mutate(child_2)) return pop def crossover(parent_1: str, parent_2: str) -> tuple[str, str]: - """Slice and combine two string in a random point""" + """Slice and combine two string at a random point.""" random_slice = random.randint(0, len(parent_1) - 1) child_1 = parent_1[:random_slice] + parent_2[random_slice:] child_2 = parent_2[:random_slice] + parent_1[random_slice:] return (child_1, child_2) def mutate(child: str) -> str: - """Mutate a random gene of a child with another one from the list""" + """Mutate a random gene of a child with another one from the list.""" child_list = list(child) if random.uniform(0, 1) < MUTATION_PROBABILITY: child_list[random.randint(0, len(child)) - 1] = random.choice(genes) return "".join(child_list) - # This is Selection + # This is selection for i in range(N_SELECTED): population.extend(select(population_score[int(i)])) # Check if the population has already reached the maximum value and if so, - # break the cycle. if this check is disabled the algorithm will take - # forever to compute large strings but will also calculate small string in - # a lot fewer generations + # break the cycle. If this check is disabled, the algorithm will take + # forever to compute large strings, but will also calculate small strings in + # a far fewer generations. if len(population) > N_POPULATION: break From a0cbc2056e9b9ff4f8c5da682061996e783b13e3 Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Sun, 23 Oct 2022 12:01:51 +0100 Subject: [PATCH 406/726] refactor: Make code more simple in maclaurin_series (#7522) --- maths/maclaurin_series.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/maths/maclaurin_series.py b/maths/maclaurin_series.py index 57edc90bf..a2619d4e6 100644 --- a/maths/maclaurin_series.py +++ b/maths/maclaurin_series.py @@ -52,8 +52,7 @@ def maclaurin_sin(theta: float, accuracy: int = 30) -> float: div = theta // (2 * pi) theta -= 2 * div * pi return sum( - (((-1) ** r) * ((theta ** (2 * r + 1)) / factorial(2 * r + 1))) - for r in range(accuracy) + (-1) ** r * theta ** (2 * r + 1) / factorial(2 * r + 1) for r in range(accuracy) ) @@ -104,12 +103,14 @@ def maclaurin_cos(theta: float, accuracy: int = 30) -> float: theta = float(theta) div = theta // (2 * pi) theta -= 2 * div * pi - return sum( - (((-1) ** r) * ((theta ** (2 * r)) / factorial(2 * r))) for r in range(accuracy) - ) + return sum((-1) ** r * theta ** (2 * r) / factorial(2 * r) for r in range(accuracy)) if __name__ == "__main__": + import doctest + + doctest.testmod() + print(maclaurin_sin(10)) print(maclaurin_sin(-10)) print(maclaurin_sin(10, 15)) From 1bbb0092f3fc311fac9e56e12c1fa223dbe16465 Mon Sep 17 00:00:00 2001 From: Arjit Arora <42044030+arjitarora26@users.noreply.github.com> Date: Sun, 23 Oct 2022 16:47:30 +0530 Subject: [PATCH 407/726] Add signum function (#7526) * Add signum function * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Add typehints for functions * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update signum.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- maths/signum.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 maths/signum.py diff --git a/maths/signum.py b/maths/signum.py new file mode 100644 index 000000000..148f93176 --- /dev/null +++ b/maths/signum.py @@ -0,0 +1,34 @@ +""" +Signum function -- https://en.wikipedia.org/wiki/Sign_function +""" + + +def signum(num: float) -> int: + """ + Applies signum function on the number + + >>> signum(-10) + -1 + >>> signum(10) + 1 + >>> signum(0) + 0 + """ + if num < 0: + return -1 + return 1 if num else 0 + + +def test_signum() -> None: + """ + Tests the signum function + """ + assert signum(5) == 1 + assert signum(-5) == -1 + assert signum(0) == 0 + + +if __name__ == "__main__": + print(signum(12)) + print(signum(-12)) + print(signum(0)) From b092f9979f5afd3bd86cb46e891eb1f318b351d9 Mon Sep 17 00:00:00 2001 From: Modassir Afzal <60973906+Moddy2024@users.noreply.github.com> Date: Sun, 23 Oct 2022 17:17:19 +0530 Subject: [PATCH 408/726] XGB Regressor (#7107) * Fixes: #{6551} * Fixes: #{6551} * Update xgboostclassifier.py * Delete xgboostclassifier.py * Update xgboostregressor.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixes: #{6551} * Fixes : {#6551} * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixes: {#6551] * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update xgboostregressor.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update xgboostregressor.py * Update xgboostregressor.py * Fixes: { #6551} * Update xgboostregressor.py * Fixes: { #6551} * Fixes: { #6551} * Update and rename xgboostregressor.py to xgboost_regressor.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- machine_learning/xgboost_regressor.py | 64 +++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 machine_learning/xgboost_regressor.py diff --git a/machine_learning/xgboost_regressor.py b/machine_learning/xgboost_regressor.py new file mode 100644 index 000000000..023984fc1 --- /dev/null +++ b/machine_learning/xgboost_regressor.py @@ -0,0 +1,64 @@ +# XGBoost Regressor Example +import numpy as np +from sklearn.datasets import fetch_california_housing +from sklearn.metrics import mean_absolute_error, mean_squared_error +from sklearn.model_selection import train_test_split +from xgboost import XGBRegressor + + +def data_handling(data: dict) -> tuple: + # Split dataset into features and target. Data is features. + """ + >>> data_handling(( + ... {'data':'[ 8.3252 41. 6.9841269 1.02380952 322. 2.55555556 37.88 -122.23 ]' + ... ,'target':([4.526])})) + ('[ 8.3252 41. 6.9841269 1.02380952 322. 2.55555556 37.88 -122.23 ]', [4.526]) + """ + return (data["data"], data["target"]) + + +def xgboost( + features: np.ndarray, target: np.ndarray, test_features: np.ndarray +) -> np.ndarray: + """ + >>> xgboost(np.array([[ 2.3571 , 52. , 6.00813008, 1.06775068, + ... 907. , 2.45799458, 40.58 , -124.26]]),np.array([1.114]), + ... np.array([[1.97840000e+00, 3.70000000e+01, 4.98858447e+00, 1.03881279e+00, + ... 1.14300000e+03, 2.60958904e+00, 3.67800000e+01, -1.19780000e+02]])) + array([[1.1139996]], dtype=float32) + """ + xgb = XGBRegressor(verbosity=0, random_state=42) + xgb.fit(features, target) + # Predict target for test data + predictions = xgb.predict(test_features) + predictions = predictions.reshape(len(predictions), 1) + return predictions + + +def main() -> None: + """ + >>> main() + Mean Absolute Error : 0.30957163379906033 + Mean Square Error : 0.22611560196662744 + + The URL for this algorithm + https://xgboost.readthedocs.io/en/stable/ + California house price dataset is used to demonstrate the algorithm. + """ + # Load California house price dataset + california = fetch_california_housing() + data, target = data_handling(california) + x_train, x_test, y_train, y_test = train_test_split( + data, target, test_size=0.25, random_state=1 + ) + predictions = xgboost(x_train, y_train, x_test) + # Error printing + print(f"Mean Absolute Error : {mean_absolute_error(y_test, predictions)}") + print(f"Mean Square Error : {mean_squared_error(y_test, predictions)}") + + +if __name__ == "__main__": + import doctest + + doctest.testmod(verbose=True) + main() From a3383ce3fd6bc30b01681503a4307df2462c8bd4 Mon Sep 17 00:00:00 2001 From: Pradyumn Singh Rahar Date: Sun, 23 Oct 2022 17:56:40 +0530 Subject: [PATCH 409/726] Reduced Time Complexity to O(sqrt(n)) (#7429) * Reduced Time Complexity to O(sqrt(n)) * Added testmod * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/factors.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/maths/factors.py b/maths/factors.py index e2fdc4063..ae2e5316c 100644 --- a/maths/factors.py +++ b/maths/factors.py @@ -1,3 +1,7 @@ +from doctest import testmod +from math import sqrt + + def factors_of_a_number(num: int) -> list: """ >>> factors_of_a_number(1) @@ -9,10 +13,22 @@ def factors_of_a_number(num: int) -> list: >>> factors_of_a_number(-24) [] """ - return [i for i in range(1, num + 1) if num % i == 0] + facs: list[int] = [] + if num < 1: + return facs + facs.append(1) + if num == 1: + return facs + facs.append(num) + for i in range(2, int(sqrt(num)) + 1): + if num % i == 0: # If i is a factor of num + facs.append(i) + d = num // i # num//i is the other factor of num + if d != i: # If d and i are distinct + facs.append(d) # we have found another factor + facs.sort() + return facs if __name__ == "__main__": - num = int(input("Enter a number to find its factors: ")) - factors = factors_of_a_number(num) - print(f"{num} has {len(factors)} factors: {', '.join(str(f) for f in factors)}") + testmod(name="factors_of_a_number", verbose=True) From a5362799a5e73e199cda7f1acec71d1e97addc97 Mon Sep 17 00:00:00 2001 From: Kevin Joven <59969678+KevinJoven11@users.noreply.github.com> Date: Sun, 23 Oct 2022 08:54:27 -0400 Subject: [PATCH 410/726] Create superdense_coding.py (#7349) * Create superdense_coding.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- quantum/superdense_coding.py | 102 +++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 quantum/superdense_coding.py diff --git a/quantum/superdense_coding.py b/quantum/superdense_coding.py new file mode 100644 index 000000000..c8eda3811 --- /dev/null +++ b/quantum/superdense_coding.py @@ -0,0 +1,102 @@ +""" +Build the superdense coding protocol. This quantum +circuit can send two classical bits using one quantum +bit. This circuit is designed using the Qiskit +framework. This experiment run in IBM Q simulator +with 1000 shots. +. +References: +https://qiskit.org/textbook/ch-algorithms/superdense-coding.html +https://en.wikipedia.org/wiki/Superdense_coding +""" + +import math + +import qiskit +from qiskit import Aer, ClassicalRegister, QuantumCircuit, QuantumRegister, execute + + +def superdense_coding(bit_1: int = 1, bit_2: int = 1) -> qiskit.result.counts.Counts: + """ + The input refer to the classical message + that you wants to send. {'00','01','10','11'} + result for default values: {11: 1000} + ┌───┐ ┌───┐ + qr_0: ─────┤ X ├──────────┤ X ├───── + ┌───┐└─┬─┘┌───┐┌───┐└─┬─┘┌───┐ + qr_1: ┤ H ├──■──┤ X ├┤ Z ├──■──┤ H ├ + └───┘ └───┘└───┘ └───┘ + cr: 2/══════════════════════════════ + Args: + bit_1: bit 1 of classical information to send. + bit_2: bit 2 of classical information to send. + Returns: + qiskit.result.counts.Counts: counts of send state. + >>> superdense_coding(0,0) + {'00': 1000} + >>> superdense_coding(0,1) + {'01': 1000} + >>> superdense_coding(-1,0) + Traceback (most recent call last): + ... + ValueError: inputs must be positive. + >>> superdense_coding(1,'j') + Traceback (most recent call last): + ... + TypeError: inputs must be integers. + >>> superdense_coding(1,0.5) + Traceback (most recent call last): + ... + ValueError: inputs must be exact integers. + >>> superdense_coding(2,1) + Traceback (most recent call last): + ... + ValueError: inputs must be less or equal to 1. + """ + if (type(bit_1) == str) or (type(bit_2) == str): + raise TypeError("inputs must be integers.") + if (bit_1 < 0) or (bit_2 < 0): + raise ValueError("inputs must be positive.") + if (math.floor(bit_1) != bit_1) or (math.floor(bit_2) != bit_2): + raise ValueError("inputs must be exact integers.") + if (bit_1 > 1) or (bit_2 > 1): + raise ValueError("inputs must be less or equal to 1.") + + # build registers + qr = QuantumRegister(2, "qr") + cr = ClassicalRegister(2, "cr") + + quantum_circuit = QuantumCircuit(qr, cr) + + # entanglement the qubits + quantum_circuit.h(1) + quantum_circuit.cx(1, 0) + + # send the information + c_information = str(bit_1) + str(bit_2) + + if c_information == "11": + quantum_circuit.x(1) + quantum_circuit.z(1) + elif c_information == "10": + quantum_circuit.z(1) + elif c_information == "01": + quantum_circuit.x(1) + else: + quantum_circuit.i(1) + + # unentangled the circuit + quantum_circuit.cx(1, 0) + quantum_circuit.h(1) + + # measure the circuit + quantum_circuit.measure(qr, cr) + + backend = Aer.get_backend("qasm_simulator") + job = execute(quantum_circuit, backend, shots=1000) + + return job.result().get_counts(quantum_circuit) + + +if __name__ == "__main__": + print(f"Counts for classical state send: {superdense_coding(1,1)}") From d5f322f5764f42fc846fbcdaefac238a9ab62c7f Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Sun, 23 Oct 2022 14:06:12 +0100 Subject: [PATCH 411/726] fix: Replace deprecated `qasm_simulator` with `aer_simulator` (#7308) (#7556) --- quantum/superdense_coding.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quantum/superdense_coding.py b/quantum/superdense_coding.py index c8eda3811..10ebc2d35 100644 --- a/quantum/superdense_coding.py +++ b/quantum/superdense_coding.py @@ -92,7 +92,7 @@ def superdense_coding(bit_1: int = 1, bit_2: int = 1) -> qiskit.result.counts.Co # measure the circuit quantum_circuit.measure(qr, cr) - backend = Aer.get_backend("qasm_simulator") + backend = Aer.get_backend("aer_simulator") job = execute(quantum_circuit, backend, shots=1000) return job.result().get_counts(quantum_circuit) From 81ccf54c75edbf52cd2b5bd4e139cba3b6e5e5ab Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sun, 23 Oct 2022 15:09:25 +0200 Subject: [PATCH 412/726] Rename xgboostclassifier.py to xgboost_classifier.py (#7550) Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 7 +++++-- .../{xgboostclassifier.py => xgboost_classifier.py} | 0 2 files changed, 5 insertions(+), 2 deletions(-) rename machine_learning/{xgboostclassifier.py => xgboost_classifier.py} (100%) diff --git a/DIRECTORY.md b/DIRECTORY.md index 70644d063..3fd1a3c38 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -461,7 +461,8 @@ * [Similarity Search](machine_learning/similarity_search.py) * [Support Vector Machines](machine_learning/support_vector_machines.py) * [Word Frequency Functions](machine_learning/word_frequency_functions.py) - * [Xgboostclassifier](machine_learning/xgboostclassifier.py) + * [Xgboost Classifier](machine_learning/xgboost_classifier.py) + * [Xgboost Regressor](machine_learning/xgboost_regressor.py) ## Maths * [3N Plus 1](maths/3n_plus_1.py) @@ -536,7 +537,7 @@ * [Line Length](maths/line_length.py) * [Lucas Lehmer Primality Test](maths/lucas_lehmer_primality_test.py) * [Lucas Series](maths/lucas_series.py) - * [Maclaurin Sin](maths/maclaurin_sin.py) + * [Maclaurin Series](maths/maclaurin_series.py) * [Matrix Exponentiation](maths/matrix_exponentiation.py) * [Max Sum Sliding Window](maths/max_sum_sliding_window.py) * [Median Of Two Arrays](maths/median_of_two_arrays.py) @@ -582,6 +583,7 @@ * [P Series](maths/series/p_series.py) * [Sieve Of Eratosthenes](maths/sieve_of_eratosthenes.py) * [Sigmoid](maths/sigmoid.py) + * [Signum](maths/signum.py) * [Simpson Rule](maths/simpson_rule.py) * [Sin](maths/sin.py) * [Sock Merchant](maths/sock_merchant.py) @@ -590,6 +592,7 @@ * [Sum Of Arithmetic Series](maths/sum_of_arithmetic_series.py) * [Sum Of Digits](maths/sum_of_digits.py) * [Sum Of Geometric Progression](maths/sum_of_geometric_progression.py) + * [Sum Of Harmonic Series](maths/sum_of_harmonic_series.py) * [Sylvester Sequence](maths/sylvester_sequence.py) * [Test Prime Check](maths/test_prime_check.py) * [Trapezoidal Rule](maths/trapezoidal_rule.py) diff --git a/machine_learning/xgboostclassifier.py b/machine_learning/xgboost_classifier.py similarity index 100% rename from machine_learning/xgboostclassifier.py rename to machine_learning/xgboost_classifier.py From 0f06a0b5ff43c4cfa98db33926d21ce688b69a10 Mon Sep 17 00:00:00 2001 From: Sagar Giri Date: Sun, 23 Oct 2022 23:35:27 +0900 Subject: [PATCH 413/726] Add web program to fetch top 10 real time billionaires using the forbes API. (#7538) * Add web program to fetch top 10 realtime billioners using forbes API. * Provide return type to function. * Use rich for tables and minor refactors. * Fix tiny typo. * Add the top {LIMIT} in rich table title. * Update web_programming/get_top_billioners.py Co-authored-by: Caeden Perelli-Harris * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Change the API path. * Update get_top_billioners.py Co-authored-by: Caeden Perelli-Harris Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- requirements.txt | 1 + web_programming/get_top_billioners.py | 84 +++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 web_programming/get_top_billioners.py diff --git a/requirements.txt b/requirements.txt index 25d2b4ef9..9ffe784c9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,6 +10,7 @@ pillow projectq qiskit requests +rich scikit-fuzzy sklearn statsmodels diff --git a/web_programming/get_top_billioners.py b/web_programming/get_top_billioners.py new file mode 100644 index 000000000..514ea1db9 --- /dev/null +++ b/web_programming/get_top_billioners.py @@ -0,0 +1,84 @@ +""" +CAUTION: You may get a json.decoding error. This works for some of us but fails for others. +""" + +from datetime import datetime + +import requests +from rich import box +from rich import console as rich_console +from rich import table as rich_table + +LIMIT = 10 +TODAY = datetime.now() + +API_URL = ( + "https://www.forbes.com/forbesapi/person/rtb/0/position/true.json" + "?fields=personName,gender,source,countryOfCitizenship,birthDate,finalWorth" + f"&limit={LIMIT}" +) + + +def calculate_age(unix_date: int) -> str: + """Calculates age from given unix time format. + + Returns: + Age as string + + >>> calculate_age(-657244800000) + '73' + >>> calculate_age(46915200000) + '51' + """ + birthdate = datetime.fromtimestamp(unix_date / 1000).date() + return str( + TODAY.year + - birthdate.year + - ((TODAY.month, TODAY.day) < (birthdate.month, birthdate.day)) + ) + + +def get_forbes_real_time_billionaires() -> list[dict[str, str]]: + """Get top 10 realtime billionaires using forbes API. + + Returns: + List of top 10 realtime billionaires data. + """ + response_json = requests.get(API_URL).json() + return [ + { + "Name": person["personName"], + "Source": person["source"], + "Country": person["countryOfCitizenship"], + "Gender": person["gender"], + "Worth ($)": f"{person['finalWorth'] / 1000:.1f} Billion", + "Age": calculate_age(person["birthDate"]), + } + for person in response_json["personList"]["personsLists"] + ] + + +def display_billionaires(forbes_billionaires: list[dict[str, str]]) -> None: + """Display Forbes real time billionaires in a rich table. + + Args: + forbes_billionaires (list): Forbes top 10 real time billionaires + """ + + table = rich_table.Table( + title=f"Forbes Top {LIMIT} Real Time Billionaires at {TODAY:%Y-%m-%d %H:%M}", + style="green", + highlight=True, + box=box.SQUARE, + ) + for key in forbes_billionaires[0]: + table.add_column(key) + + for billionaire in forbes_billionaires: + table.add_row(*billionaire.values()) + + rich_console.Console().print(table) + + +if __name__ == "__main__": + display_billionaires(get_forbes_real_time_billionaires()) From 393b9605259fe19e03bdaac2b0866151e1a2afc2 Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Sun, 23 Oct 2022 15:36:10 +0100 Subject: [PATCH 414/726] refactor: Replace doctest traceback with `...` (#7558) --- conversions/pressure_conversions.py | 6 +----- electronics/carrier_concentration.py | 8 ++++---- electronics/electric_power.py | 6 +++--- maths/nevilles_method.py | 3 +-- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/conversions/pressure_conversions.py b/conversions/pressure_conversions.py index 2018080b9..e0cd18d23 100644 --- a/conversions/pressure_conversions.py +++ b/conversions/pressure_conversions.py @@ -56,11 +56,7 @@ def pressure_conversion(value: float, from_type: str, to_type: str) -> float: 0.019336718261000002 >>> pressure_conversion(4, "wrongUnit", "atm") Traceback (most recent call last): - File "/usr/lib/python3.8/doctest.py", line 1336, in __run - exec(compile(example.source, filename, "single", - File "", line 1, in - pressure_conversion(4, "wrongUnit", "atm") - File "", line 67, in pressure_conversion + ... ValueError: Invalid 'from_type' value: 'wrongUnit' Supported values are: atm, pascal, bar, kilopascal, megapascal, psi, inHg, torr """ diff --git a/electronics/carrier_concentration.py b/electronics/carrier_concentration.py index 03482f1e3..1fb9f2430 100644 --- a/electronics/carrier_concentration.py +++ b/electronics/carrier_concentration.py @@ -25,19 +25,19 @@ def carrier_concentration( ('hole_conc', 1440.0) >>> carrier_concentration(electron_conc=1000, hole_conc=400, intrinsic_conc=1200) Traceback (most recent call last): - File "", line 37, in + ... ValueError: You cannot supply more or less than 2 values >>> carrier_concentration(electron_conc=-1000, hole_conc=0, intrinsic_conc=1200) Traceback (most recent call last): - File "", line 40, in + ... ValueError: Electron concentration cannot be negative in a semiconductor >>> carrier_concentration(electron_conc=0, hole_conc=-400, intrinsic_conc=1200) Traceback (most recent call last): - File "", line 44, in + ... ValueError: Hole concentration cannot be negative in a semiconductor >>> carrier_concentration(electron_conc=0, hole_conc=400, intrinsic_conc=-1200) Traceback (most recent call last): - File "", line 48, in + ... ValueError: Intrinsic concentration cannot be negative in a semiconductor """ if (electron_conc, hole_conc, intrinsic_conc).count(0) != 1: diff --git a/electronics/electric_power.py b/electronics/electric_power.py index ac673d7e3..e59795601 100644 --- a/electronics/electric_power.py +++ b/electronics/electric_power.py @@ -17,15 +17,15 @@ def electric_power(voltage: float, current: float, power: float) -> tuple: result(name='power', value=6.0) >>> electric_power(voltage=2, current=4, power=2) Traceback (most recent call last): - File "", line 15, in + ... ValueError: Only one argument must be 0 >>> electric_power(voltage=0, current=0, power=2) Traceback (most recent call last): - File "", line 19, in + ... ValueError: Only one argument must be 0 >>> electric_power(voltage=0, current=2, power=-4) Traceback (most recent call last): - File "", line 23, in >> electric_power(voltage=2.2, current=2.2, power=0) result(name='power', value=4.84) diff --git a/maths/nevilles_method.py b/maths/nevilles_method.py index 5583e4269..1f48b43fb 100644 --- a/maths/nevilles_method.py +++ b/maths/nevilles_method.py @@ -31,8 +31,7 @@ def neville_interpolate(x_points: list, y_points: list, x0: int) -> list: 104.0 >>> neville_interpolate((1,2,3,4,6), (6,7,8,9,11), '') Traceback (most recent call last): - File "", line 1, in - ... + ... TypeError: unsupported operand type(s) for -: 'str' and 'int' """ n = len(x_points) From 10b6e7a658c4664ce823cc1d0f159cd717b506db Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Sun, 23 Oct 2022 16:14:45 +0100 Subject: [PATCH 415/726] fix: Fix line too long in doctest (#7566) --- web_programming/get_top_billioners.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web_programming/get_top_billioners.py b/web_programming/get_top_billioners.py index 514ea1db9..6a8054e26 100644 --- a/web_programming/get_top_billioners.py +++ b/web_programming/get_top_billioners.py @@ -1,5 +1,6 @@ """ -CAUTION: You may get a json.decoding error. This works for some of us but fails for others. +CAUTION: You may get a json.decoding error. +This works for some of us but fails for others. """ from datetime import datetime From 0dc95c0a6be06f33153e8fcd84d2c854dac7a353 Mon Sep 17 00:00:00 2001 From: SwayamSahu <91021799+SwayamSahu@users.noreply.github.com> Date: Sun, 23 Oct 2022 21:30:59 +0530 Subject: [PATCH 416/726] Update comments in check_pangram.py script (#7564) * Update comments in check_pangram.py script * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update and rename check_pangram.py to is_pangram.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- strings/check_pangram.py | 74 ------------------------------- strings/is_pangram.py | 95 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 74 deletions(-) delete mode 100644 strings/check_pangram.py create mode 100644 strings/is_pangram.py diff --git a/strings/check_pangram.py b/strings/check_pangram.py deleted file mode 100644 index 81384bfd4..000000000 --- a/strings/check_pangram.py +++ /dev/null @@ -1,74 +0,0 @@ -""" -wiki: https://en.wikipedia.org/wiki/Pangram -""" - - -def check_pangram( - input_str: str = "The quick brown fox jumps over the lazy dog", -) -> bool: - """ - A Pangram String contains all the alphabets at least once. - >>> check_pangram("The quick brown fox jumps over the lazy dog") - True - >>> check_pangram("Waltz, bad nymph, for quick jigs vex.") - True - >>> check_pangram("Jived fox nymph grabs quick waltz.") - True - >>> check_pangram("My name is Unknown") - False - >>> check_pangram("The quick brown fox jumps over the la_y dog") - False - >>> check_pangram() - True - """ - frequency = set() - input_str = input_str.replace( - " ", "" - ) # Replacing all the Whitespaces in our sentence - for alpha in input_str: - if "a" <= alpha.lower() <= "z": - frequency.add(alpha.lower()) - - return True if len(frequency) == 26 else False - - -def check_pangram_faster( - input_str: str = "The quick brown fox jumps over the lazy dog", -) -> bool: - """ - >>> check_pangram_faster("The quick brown fox jumps over the lazy dog") - True - >>> check_pangram_faster("Waltz, bad nymph, for quick jigs vex.") - True - >>> check_pangram_faster("Jived fox nymph grabs quick waltz.") - True - >>> check_pangram_faster("The quick brown fox jumps over the la_y dog") - False - >>> check_pangram_faster() - True - """ - flag = [False] * 26 - for char in input_str: - if char.islower(): - flag[ord(char) - 97] = True - elif char.isupper(): - flag[ord(char) - 65] = True - return all(flag) - - -def benchmark() -> None: - """ - Benchmark code comparing different version. - """ - from timeit import timeit - - setup = "from __main__ import check_pangram, check_pangram_faster" - print(timeit("check_pangram()", setup=setup)) - print(timeit("check_pangram_faster()", setup=setup)) - - -if __name__ == "__main__": - import doctest - - doctest.testmod() - benchmark() diff --git a/strings/is_pangram.py b/strings/is_pangram.py new file mode 100644 index 000000000..c8b894b7e --- /dev/null +++ b/strings/is_pangram.py @@ -0,0 +1,95 @@ +""" +wiki: https://en.wikipedia.org/wiki/Pangram +""" + + +def is_pangram( + input_str: str = "The quick brown fox jumps over the lazy dog", +) -> bool: + """ + A Pangram String contains all the alphabets at least once. + >>> is_pangram("The quick brown fox jumps over the lazy dog") + True + >>> is_pangram("Waltz, bad nymph, for quick jigs vex.") + True + >>> is_pangram("Jived fox nymph grabs quick waltz.") + True + >>> is_pangram("My name is Unknown") + False + >>> is_pangram("The quick brown fox jumps over the la_y dog") + False + >>> is_pangram() + True + """ + # Declare frequency as a set to have unique occurrences of letters + frequency = set() + + # Replace all the whitespace in our sentence + input_str = input_str.replace(" ", "") + for alpha in input_str: + if "a" <= alpha.lower() <= "z": + frequency.add(alpha.lower()) + return len(frequency) == 26 + + +def is_pangram_faster( + input_str: str = "The quick brown fox jumps over the lazy dog", +) -> bool: + """ + >>> is_pangram_faster("The quick brown fox jumps over the lazy dog") + True + >>> is_pangram_faster("Waltz, bad nymph, for quick jigs vex.") + True + >>> is_pangram_faster("Jived fox nymph grabs quick waltz.") + True + >>> is_pangram_faster("The quick brown fox jumps over the la_y dog") + False + >>> is_pangram_faster() + True + """ + flag = [False] * 26 + for char in input_str: + if char.islower(): + flag[ord(char) - 97] = True + elif char.isupper(): + flag[ord(char) - 65] = True + return all(flag) + + +def is_pangram_fastest( + input_str: str = "The quick brown fox jumps over the lazy dog", +) -> bool: + """ + >>> is_pangram_fastest("The quick brown fox jumps over the lazy dog") + True + >>> is_pangram_fastest("Waltz, bad nymph, for quick jigs vex.") + True + >>> is_pangram_fastest("Jived fox nymph grabs quick waltz.") + True + >>> is_pangram_fastest("The quick brown fox jumps over the la_y dog") + False + >>> is_pangram_fastest() + True + """ + return len({char for char in input_str.lower() if char.isalpha()}) == 26 + + +def benchmark() -> None: + """ + Benchmark code comparing different version. + """ + from timeit import timeit + + setup = "from __main__ import is_pangram, is_pangram_faster, is_pangram_fastest" + print(timeit("is_pangram()", setup=setup)) + print(timeit("is_pangram_faster()", setup=setup)) + print(timeit("is_pangram_fastest()", setup=setup)) + # 5.348480500048026, 2.6477354579837993, 1.8470395830227062 + # 5.036091582966037, 2.644472333951853, 1.8869528750656173 + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + benchmark() From b8b63469efff57b8cb3c6e4aec4279c8e864b8db Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sun, 23 Oct 2022 18:12:49 +0200 Subject: [PATCH 417/726] My favorite palindrome (#7455) * My favorite palindrome * updating DIRECTORY.md * Update is_palindrome.py * Update is_palindrome.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update strings/is_palindrome.py Co-authored-by: Caeden Perelli-Harris * Update is_palindrome.py Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Caeden Perelli-Harris --- strings/is_palindrome.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/strings/is_palindrome.py b/strings/is_palindrome.py index 4776a5fc2..5758af0ce 100644 --- a/strings/is_palindrome.py +++ b/strings/is_palindrome.py @@ -1,9 +1,8 @@ def is_palindrome(s: str) -> bool: """ - Determine whether the string is palindrome - :param s: - :return: Boolean - >>> is_palindrome("a man a plan a canal panama".replace(" ", "")) + Determine if the string s is a palindrome. + + >>> is_palindrome("A man, A plan, A canal -- Panama!") True >>> is_palindrome("Hello") False @@ -14,15 +13,15 @@ def is_palindrome(s: str) -> bool: >>> is_palindrome("Mr. Owl ate my metal worm?") True """ - # Since Punctuation, capitalization, and spaces are usually ignored while checking - # Palindrome, we first remove them from our string. - s = "".join([character for character in s.lower() if character.isalnum()]) + # Since punctuation, capitalization, and spaces are often ignored while checking + # palindromes, we first remove them from our string. + s = "".join(character for character in s.lower() if character.isalnum()) return s == s[::-1] if __name__ == "__main__": - s = input("Enter string to determine whether its palindrome or not: ").strip() + s = input("Please enter a string to see if it is a palindrome: ") if is_palindrome(s): - print("Given string is palindrome") + print(f"'{s}' is a palindrome.") else: - print("Given string is not palindrome") + print(f"'{s}' is not a palindrome.") From 39a99b46f5e9b2c56951c22189a8ac3ea0730b01 Mon Sep 17 00:00:00 2001 From: Laukik Chahande <103280327+luciferx48@users.noreply.github.com> Date: Sun, 23 Oct 2022 22:56:22 +0530 Subject: [PATCH 418/726] check whether integer is even or odd using bit manupulation (#7099) * even_or_not file added * Updated DIRECTORY.md * modified DIRECTORY.md * Update bit_manipulation/even_or_not.py * updating DIRECTORY.md * Rename even_or_not.py to is_even.py * updating DIRECTORY.md Co-authored-by: luciferx48 Co-authored-by: Christian Clauss Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 1 + bit_manipulation/is_even.py | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 bit_manipulation/is_even.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 3fd1a3c38..10e78a92c 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -45,6 +45,7 @@ * [Count 1S Brian Kernighan Method](bit_manipulation/count_1s_brian_kernighan_method.py) * [Count Number Of One Bits](bit_manipulation/count_number_of_one_bits.py) * [Gray Code Sequence](bit_manipulation/gray_code_sequence.py) + * [Is Even](bit_manipulation/is_even.py) * [Reverse Bits](bit_manipulation/reverse_bits.py) * [Single Bit Manipulation Operations](bit_manipulation/single_bit_manipulation_operations.py) diff --git a/bit_manipulation/is_even.py b/bit_manipulation/is_even.py new file mode 100644 index 000000000..b7b0841a1 --- /dev/null +++ b/bit_manipulation/is_even.py @@ -0,0 +1,37 @@ +def is_even(number: int) -> bool: + """ + return true if the input integer is even + Explanation: Lets take a look at the following deicmal to binary conversions + 2 => 10 + 14 => 1110 + 100 => 1100100 + 3 => 11 + 13 => 1101 + 101 => 1100101 + from the above examples we can observe that + for all the odd integers there is always 1 set bit at the end + also, 1 in binary can be represented as 001, 00001, or 0000001 + so for any odd integer n => n&1 is always equlas 1 else the integer is even + + >>> is_even(1) + False + >>> is_even(4) + True + >>> is_even(9) + False + >>> is_even(15) + False + >>> is_even(40) + True + >>> is_even(100) + True + >>> is_even(101) + False + """ + return number & 1 == 0 + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From e2a83b3bc66630cb2667375fba9de5c5baac3aca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nadirhan=20=C5=9Eahin?= Date: Sun, 23 Oct 2022 22:28:11 +0300 Subject: [PATCH 419/726] Update knapsack.py (#7271) * Update knapsack.py * Update dynamic_programming/knapsack.py Co-authored-by: Christian Clauss * Update knapsack.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: Christian Clauss Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- dynamic_programming/knapsack.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dynamic_programming/knapsack.py b/dynamic_programming/knapsack.py index 093e15f49..b12d30313 100644 --- a/dynamic_programming/knapsack.py +++ b/dynamic_programming/knapsack.py @@ -1,9 +1,9 @@ """ Given weights and values of n items, put these items in a knapsack of - capacity W to get the maximum total value in the knapsack. +capacity W to get the maximum total value in the knapsack. Note that only the integer weights 0-1 knapsack problem is solvable - using dynamic programming. +using dynamic programming. """ @@ -27,7 +27,7 @@ def mf_knapsack(i, wt, val, j): def knapsack(w, wt, val, n): - dp = [[0 for i in range(w + 1)] for j in range(n + 1)] + dp = [[0] * (w + 1) for _ in range(n + 1)] for i in range(1, n + 1): for w_ in range(1, w + 1): @@ -108,7 +108,7 @@ def _construct_solution(dp: list, wt: list, i: int, j: int, optimal_set: set): dp: list of list, the table of a solved integer weight dynamic programming problem wt: list or tuple, the vector of weights of the items - i: int, the index of the item under consideration + i: int, the index of the item under consideration j: int, the current possible maximum weight optimal_set: set, the optimal subset so far. This gets modified by the function. @@ -136,7 +136,7 @@ if __name__ == "__main__": wt = [4, 3, 2, 3] n = 4 w = 6 - f = [[0] * (w + 1)] + [[0] + [-1 for i in range(w + 1)] for j in range(n + 1)] + f = [[0] * (w + 1)] + [[0] + [-1] * (w + 1) for _ in range(n + 1)] optimal_solution, _ = knapsack(w, wt, val, n) print(optimal_solution) print(mf_knapsack(n, wt, val, w)) # switched the n and w From bd490614a69cc9cdff367cb4a1775dd063c6e617 Mon Sep 17 00:00:00 2001 From: Arjit Arora <42044030+arjitarora26@users.noreply.github.com> Date: Mon, 24 Oct 2022 15:43:01 +0530 Subject: [PATCH 420/726] Add function for AND gate (#7593) --- boolean_algebra/and_gate.py | 48 +++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 boolean_algebra/and_gate.py diff --git a/boolean_algebra/and_gate.py b/boolean_algebra/and_gate.py new file mode 100644 index 000000000..cbbcfde79 --- /dev/null +++ b/boolean_algebra/and_gate.py @@ -0,0 +1,48 @@ +""" +An AND Gate is a logic gate in boolean algebra which results to 1 (True) if both the +inputs are 1, and 0 (False) otherwise. + +Following is the truth table of an AND Gate: + ------------------------------ + | Input 1 | Input 2 | Output | + ------------------------------ + | 0 | 0 | 0 | + | 0 | 1 | 0 | + | 1 | 0 | 0 | + | 1 | 1 | 1 | + ------------------------------ + +Refer - https://www.geeksforgeeks.org/logic-gates-in-python/ +""" + + +def and_gate(input_1: int, input_2: int) -> int: + """ + Calculate AND of the input values + + >>> and_gate(0, 0) + 0 + >>> and_gate(0, 1) + 0 + >>> and_gate(1, 0) + 0 + >>> and_gate(1, 1) + 1 + """ + return int((input_1, input_2).count(0) == 0) + + +def test_and_gate() -> None: + """ + Tests the and_gate function + """ + assert and_gate(0, 0) == 0 + assert and_gate(0, 1) == 0 + assert and_gate(1, 0) == 0 + assert and_gate(1, 1) == 1 + + +if __name__ == "__main__": + print(and_gate(0, 0)) + print(and_gate(0, 1)) + print(and_gate(1, 1)) From bb078541dd030b4957ee1b5ac87b7a31bf1a7235 Mon Sep 17 00:00:00 2001 From: JatinR05 <71865805+JatinR05@users.noreply.github.com> Date: Mon, 24 Oct 2022 15:43:39 +0530 Subject: [PATCH 421/726] Update count_number_of_one_bits.py (#7589) * Update count_number_of_one_bits.py removed the modulo operator as it is very time consuming in comparison to the and operator * Update count_number_of_one_bits.py Updated with the timeit library to compare. Moreover I have updated my code which helps us in reaching the output comparatively faster. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bit_manipulation/count_number_of_one_bits.py Co-authored-by: Christian Clauss * Update count_number_of_one_bits.py Updated the code * Update count_number_of_one_bits.py Updated code * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Run the tests before running the benchmarks * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * consistently Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- bit_manipulation/count_number_of_one_bits.py | 79 +++++++++++++++++--- 1 file changed, 68 insertions(+), 11 deletions(-) diff --git a/bit_manipulation/count_number_of_one_bits.py b/bit_manipulation/count_number_of_one_bits.py index 51fd2b630..a1687503a 100644 --- a/bit_manipulation/count_number_of_one_bits.py +++ b/bit_manipulation/count_number_of_one_bits.py @@ -1,34 +1,91 @@ -def get_set_bits_count(number: int) -> int: +from timeit import timeit + + +def get_set_bits_count_using_brian_kernighans_algorithm(number: int) -> int: """ Count the number of set bits in a 32 bit integer - >>> get_set_bits_count(25) + >>> get_set_bits_count_using_brian_kernighans_algorithm(25) 3 - >>> get_set_bits_count(37) + >>> get_set_bits_count_using_brian_kernighans_algorithm(37) 3 - >>> get_set_bits_count(21) + >>> get_set_bits_count_using_brian_kernighans_algorithm(21) 3 - >>> get_set_bits_count(58) + >>> get_set_bits_count_using_brian_kernighans_algorithm(58) 4 - >>> get_set_bits_count(0) + >>> get_set_bits_count_using_brian_kernighans_algorithm(0) 0 - >>> get_set_bits_count(256) + >>> get_set_bits_count_using_brian_kernighans_algorithm(256) 1 - >>> get_set_bits_count(-1) + >>> get_set_bits_count_using_brian_kernighans_algorithm(-1) Traceback (most recent call last): ... - ValueError: the value of input must be positive + ValueError: the value of input must not be negative """ if number < 0: - raise ValueError("the value of input must be positive") + raise ValueError("the value of input must not be negative") + result = 0 + while number: + number &= number - 1 + result += 1 + return result + + +def get_set_bits_count_using_modulo_operator(number: int) -> int: + """ + Count the number of set bits in a 32 bit integer + >>> get_set_bits_count_using_modulo_operator(25) + 3 + >>> get_set_bits_count_using_modulo_operator(37) + 3 + >>> get_set_bits_count_using_modulo_operator(21) + 3 + >>> get_set_bits_count_using_modulo_operator(58) + 4 + >>> get_set_bits_count_using_modulo_operator(0) + 0 + >>> get_set_bits_count_using_modulo_operator(256) + 1 + >>> get_set_bits_count_using_modulo_operator(-1) + Traceback (most recent call last): + ... + ValueError: the value of input must not be negative + """ + if number < 0: + raise ValueError("the value of input must not be negative") result = 0 while number: if number % 2 == 1: result += 1 - number = number >> 1 + number >>= 1 return result +def benchmark() -> None: + """ + Benchmark code for comparing 2 functions, with different length int values. + Brian Kernighan's algorithm is consistently faster than using modulo_operator. + """ + + def do_benchmark(number: int) -> None: + setup = "import __main__ as z" + print(f"Benchmark when {number = }:") + print(f"{get_set_bits_count_using_modulo_operator(number) = }") + timing = timeit("z.get_set_bits_count_using_modulo_operator(25)", setup=setup) + print(f"timeit() runs in {timing} seconds") + print(f"{get_set_bits_count_using_brian_kernighans_algorithm(number) = }") + timing = timeit( + "z.get_set_bits_count_using_brian_kernighans_algorithm(25)", + setup=setup, + ) + print(f"timeit() runs in {timing} seconds") + + for number in (25, 37, 58, 0): + do_benchmark(number) + print() + + if __name__ == "__main__": import doctest doctest.testmod() + benchmark() From d8ab8a0a0ebcb05783c93fe4ed04a940fc0b857f Mon Sep 17 00:00:00 2001 From: Carlos Villar Date: Mon, 24 Oct 2022 13:33:56 +0200 Subject: [PATCH 422/726] Add Spain National ID validator (#7574) (#7575) * Add Spain National ID validator (#7574) * is_spain_national_id() * Update is_spain_national_id.py * Some systems add a dash Co-authored-by: Christian Clauss --- strings/is_spain_national_id.py | 72 +++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 strings/is_spain_national_id.py diff --git a/strings/is_spain_national_id.py b/strings/is_spain_national_id.py new file mode 100644 index 000000000..67f49755f --- /dev/null +++ b/strings/is_spain_national_id.py @@ -0,0 +1,72 @@ +NUMBERS_PLUS_LETTER = "Input must be a string of 8 numbers plus letter" +LOOKUP_LETTERS = "TRWAGMYFPDXBNJZSQVHLCKE" + + +def is_spain_national_id(spanish_id: str) -> bool: + """ + Spain National Id is a string composed by 8 numbers plus a letter + The letter in fact is not part of the ID, it acts as a validator, + checking you didn't do a mistake when entering it on a system or + are giving a fake one. + + https://en.wikipedia.org/wiki/Documento_Nacional_de_Identidad_(Spain)#Number + + >>> is_spain_national_id("12345678Z") + True + >>> is_spain_national_id("12345678z") # It is case-insensitive + True + >>> is_spain_national_id("12345678x") + False + >>> is_spain_national_id("12345678I") + False + >>> is_spain_national_id("12345678-Z") # Some systems add a dash + True + >>> is_spain_national_id("12345678") + Traceback (most recent call last): + ... + ValueError: Input must be a string of 8 numbers plus letter + >>> is_spain_national_id("123456709") + Traceback (most recent call last): + ... + ValueError: Input must be a string of 8 numbers plus letter + >>> is_spain_national_id("1234567--Z") + Traceback (most recent call last): + ... + ValueError: Input must be a string of 8 numbers plus letter + >>> is_spain_national_id("1234Z") + Traceback (most recent call last): + ... + ValueError: Input must be a string of 8 numbers plus letter + >>> is_spain_national_id("1234ZzZZ") + Traceback (most recent call last): + ... + ValueError: Input must be a string of 8 numbers plus letter + >>> is_spain_national_id(12345678) + Traceback (most recent call last): + ... + TypeError: Expected string as input, found int + """ + + if not isinstance(spanish_id, str): + raise TypeError(f"Expected string as input, found {type(spanish_id).__name__}") + + spanish_id_clean = spanish_id.replace("-", "").upper() + if len(spanish_id_clean) != 9: + raise ValueError(NUMBERS_PLUS_LETTER) + + try: + number = int(spanish_id_clean[0:8]) + letter = spanish_id_clean[8] + except ValueError as ex: + raise ValueError(NUMBERS_PLUS_LETTER) from ex + + if letter.isdigit(): + raise ValueError(NUMBERS_PLUS_LETTER) + + return letter == LOOKUP_LETTERS[number % 23] + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From a041b64f7aaf7dd54f154ba1fb5cd10e3110c1eb Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Mon, 24 Oct 2022 16:29:49 +0300 Subject: [PATCH 423/726] feat: add Project Euler problem 073 solution 1 (#6273) Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- DIRECTORY.md | 2 ++ project_euler/problem_073/__init__.py | 0 project_euler/problem_073/sol1.py | 46 +++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 project_euler/problem_073/__init__.py create mode 100644 project_euler/problem_073/sol1.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 10e78a92c..16e6b7ae3 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -839,6 +839,8 @@ * Problem 072 * [Sol1](project_euler/problem_072/sol1.py) * [Sol2](project_euler/problem_072/sol2.py) + * Problem 073 + * [Sol1](project_euler/problem_073/sol1.py) * Problem 074 * [Sol1](project_euler/problem_074/sol1.py) * [Sol2](project_euler/problem_074/sol2.py) diff --git a/project_euler/problem_073/__init__.py b/project_euler/problem_073/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_073/sol1.py b/project_euler/problem_073/sol1.py new file mode 100644 index 000000000..2b66b7d87 --- /dev/null +++ b/project_euler/problem_073/sol1.py @@ -0,0 +1,46 @@ +""" +Project Euler Problem 73: https://projecteuler.net/problem=73 + +Consider the fraction, n/d, where n and d are positive integers. +If n int: + """ + Returns number of fractions lie between 1/3 and 1/2 in the sorted set + of reduced proper fractions for d ≤ max_d + + >>> solution(4) + 0 + + >>> solution(5) + 1 + + >>> solution(8) + 3 + """ + + fractions_number = 0 + for d in range(max_d + 1): + for n in range(d // 3 + 1, (d + 1) // 2): + if gcd(n, d) == 1: + fractions_number += 1 + return fractions_number + + +if __name__ == "__main__": + print(f"{solution() = }") From d407476531dd85db79e58aa2dd13d3b3031d8185 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Tue, 25 Oct 2022 03:57:03 +0300 Subject: [PATCH 424/726] fix: increase str conversion limit where required (#7604) Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 8 +++++++- project_euler/problem_104/{sol.py.FIXME => sol1.py} | 10 +++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) rename project_euler/problem_104/{sol.py.FIXME => sol1.py} (95%) diff --git a/DIRECTORY.md b/DIRECTORY.md index 16e6b7ae3..3e722a878 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -55,6 +55,7 @@ * [Modular Division](blockchain/modular_division.py) ## Boolean Algebra + * [And Gate](boolean_algebra/and_gate.py) * [Norgate](boolean_algebra/norgate.py) * [Quine Mc Cluskey](boolean_algebra/quine_mc_cluskey.py) @@ -876,6 +877,8 @@ * [Sol1](project_euler/problem_101/sol1.py) * Problem 102 * [Sol1](project_euler/problem_102/sol1.py) + * Problem 104 + * [Sol1](project_euler/problem_104/sol1.py) * Problem 107 * [Sol1](project_euler/problem_107/sol1.py) * Problem 109 @@ -948,6 +951,7 @@ * [Quantum Random](quantum/quantum_random.py) * [Ripple Adder Classic](quantum/ripple_adder_classic.py) * [Single Qubit Measure](quantum/single_qubit_measure.py) + * [Superdense Coding](quantum/superdense_coding.py) ## Scheduling * [First Come First Served](scheduling/first_come_first_served.py) @@ -1037,7 +1041,6 @@ * [Can String Be Rearranged As Palindrome](strings/can_string_be_rearranged_as_palindrome.py) * [Capitalize](strings/capitalize.py) * [Check Anagrams](strings/check_anagrams.py) - * [Check Pangram](strings/check_pangram.py) * [Credit Card Validator](strings/credit_card_validator.py) * [Detecting English Programmatically](strings/detecting_english_programmatically.py) * [Dna](strings/dna.py) @@ -1046,6 +1049,8 @@ * [Indian Phone Validator](strings/indian_phone_validator.py) * [Is Contains Unique Chars](strings/is_contains_unique_chars.py) * [Is Palindrome](strings/is_palindrome.py) + * [Is Pangram](strings/is_pangram.py) + * [Is Spain National Id](strings/is_spain_national_id.py) * [Jaro Winkler](strings/jaro_winkler.py) * [Join](strings/join.py) * [Knuth Morris Pratt](strings/knuth_morris_pratt.py) @@ -1090,6 +1095,7 @@ * [Fetch Well Rx Price](web_programming/fetch_well_rx_price.py) * [Get Imdb Top 250 Movies Csv](web_programming/get_imdb_top_250_movies_csv.py) * [Get Imdbtop](web_programming/get_imdbtop.py) + * [Get Top Billioners](web_programming/get_top_billioners.py) * [Get Top Hn Posts](web_programming/get_top_hn_posts.py) * [Get User Tweets](web_programming/get_user_tweets.py) * [Giphy](web_programming/giphy.py) diff --git a/project_euler/problem_104/sol.py.FIXME b/project_euler/problem_104/sol1.py similarity index 95% rename from project_euler/problem_104/sol.py.FIXME rename to project_euler/problem_104/sol1.py index 0818ac401..60fd6fe99 100644 --- a/project_euler/problem_104/sol.py.FIXME +++ b/project_euler/problem_104/sol1.py @@ -13,6 +13,10 @@ Given that Fk is the first Fibonacci number for which the first nine digits AND the last nine digits are 1-9 pandigital, find k. """ +import sys + +sys.set_int_max_str_digits(0) # type: ignore + def check(number: int) -> bool: """ @@ -34,7 +38,7 @@ def check(number: int) -> bool: check_front = [0] * 11 # mark last 9 numbers - for x in range(9): + for _ in range(9): check_last[int(number % 10)] = 1 number = number // 10 # flag @@ -51,7 +55,7 @@ def check(number: int) -> bool: # mark first 9 numbers number = int(str(number)[:9]) - for x in range(9): + for _ in range(9): check_front[int(number % 10)] = 1 number = number // 10 @@ -81,7 +85,7 @@ def check1(number: int) -> bool: check_last = [0] * 11 # mark last 9 numbers - for x in range(9): + for _ in range(9): check_last[int(number % 10)] = 1 number = number // 10 # flag From a662d96196d58c2415d6a6933fa78a59996cc3fa Mon Sep 17 00:00:00 2001 From: Arjit Arora <42044030+arjitarora26@users.noreply.github.com> Date: Wed, 26 Oct 2022 00:56:53 +0530 Subject: [PATCH 425/726] Add function for xor gate (#7588) * Add function for xor gate * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Add test case for xor functions * Update boolean_algebra/xor_gate.py Co-authored-by: Christian Clauss * Update boolean_algebra/xor_gate.py Co-authored-by: Christian Clauss * Split long comment line into two lines * 88 characters per line Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- boolean_algebra/xor_gate.py | 46 +++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 boolean_algebra/xor_gate.py diff --git a/boolean_algebra/xor_gate.py b/boolean_algebra/xor_gate.py new file mode 100644 index 000000000..db4f5b45c --- /dev/null +++ b/boolean_algebra/xor_gate.py @@ -0,0 +1,46 @@ +""" +A XOR Gate is a logic gate in boolean algebra which results to 1 (True) if only one of +the two inputs is 1, and 0 (False) if an even number of inputs are 1. +Following is the truth table of a XOR Gate: + ------------------------------ + | Input 1 | Input 2 | Output | + ------------------------------ + | 0 | 0 | 0 | + | 0 | 1 | 1 | + | 1 | 0 | 1 | + | 1 | 1 | 0 | + ------------------------------ + +Refer - https://www.geeksforgeeks.org/logic-gates-in-python/ +""" + + +def xor_gate(input_1: int, input_2: int) -> int: + """ + calculate xor of the input values + + >>> xor_gate(0, 0) + 0 + >>> xor_gate(0, 1) + 1 + >>> xor_gate(1, 0) + 1 + >>> xor_gate(1, 1) + 0 + """ + return (input_1, input_2).count(0) % 2 + + +def test_xor_gate() -> None: + """ + Tests the xor_gate function + """ + assert xor_gate(0, 0) == 0 + assert xor_gate(0, 1) == 1 + assert xor_gate(1, 0) == 1 + assert xor_gate(1, 1) == 0 + + +if __name__ == "__main__": + print(xor_gate(0, 0)) + print(xor_gate(0, 1)) From cbdbe07ffd07619f1c3c5ab63ae6b2775e3c235d Mon Sep 17 00:00:00 2001 From: SparshRastogi <75373475+SparshRastogi@users.noreply.github.com> Date: Wed, 26 Oct 2022 01:13:02 +0530 Subject: [PATCH 426/726] Create kinetic_energy.py (#7620) * Create kinetic_energy.py Finding the kinetic energy of an object,by taking its mass and velocity as input * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update kinetic_energy.py * Update kinetic_energy.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- physics/kinetic_energy.py | 47 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 physics/kinetic_energy.py diff --git a/physics/kinetic_energy.py b/physics/kinetic_energy.py new file mode 100644 index 000000000..535ffc219 --- /dev/null +++ b/physics/kinetic_energy.py @@ -0,0 +1,47 @@ +""" +Find the kinetic energy of an object, give its mass and velocity +Description : In physics, the kinetic energy of an object is the energy that it +possesses due to its motion. It is defined as the work needed to accelerate a body of a +given mass from rest to its stated velocity. Having gained this energy during its +acceleration, the body maintains this kinetic energy unless its speed changes. The same +amount of work is done by the body when decelerating from its current speed to a state +of rest. Formally, a kinetic energy is any term in a system's Lagrangian which includes +a derivative with respect to time. + +In classical mechanics, the kinetic energy of a non-rotating object of mass m traveling +at a speed v is ½mv². In relativistic mechanics, this is a good approximation only when +v is much less than the speed of light. The standard unit of kinetic energy is the +joule, while the English unit of kinetic energy is the foot-pound. + +Reference : https://en.m.wikipedia.org/wiki/Kinetic_energy +""" + + +def kinetic_energy(mass: float, velocity: float) -> float: + """ + The kinetic energy of a non-rotating object of mass m traveling at a speed v is ½mv² + + >>> kinetic_energy(10,10) + 500.0 + >>> kinetic_energy(0,10) + 0.0 + >>> kinetic_energy(10,0) + 0.0 + >>> kinetic_energy(20,-20) + 4000.0 + >>> kinetic_energy(0,0) + 0.0 + >>> kinetic_energy(2,2) + 4.0 + >>> kinetic_energy(100,100) + 500000.0 + """ + if mass < 0: + raise ValueError("The mass of a body cannot be negative") + return 0.5 * mass * abs(velocity) * abs(velocity) + + +if __name__ == "__main__": + import doctest + + doctest.testmod(verbose=True) From 450842321d30ab072a84aee15dfdbf199f9914dc Mon Sep 17 00:00:00 2001 From: Havish <100441982+havishs9@users.noreply.github.com> Date: Tue, 25 Oct 2022 12:47:52 -0700 Subject: [PATCH 427/726] Arc Length Algorithm (#7610) * Create decimal_conversions.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Create arc_length.py * Delete decimal_conversions.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Removed redundant statement, fixed line overflow * Update arc_length.py Changed rad to radius as not to get confused with radians * Update arc_length.py * Update arc_length.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> --- maths/arc_length.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 maths/arc_length.py diff --git a/maths/arc_length.py b/maths/arc_length.py new file mode 100644 index 000000000..9e87ca38c --- /dev/null +++ b/maths/arc_length.py @@ -0,0 +1,15 @@ +from math import pi + + +def arc_length(angle: int, radius: int) -> float: + """ + >>> arc_length(45, 5) + 3.9269908169872414 + >>> arc_length(120, 15) + 31.415926535897928 + """ + return 2 * pi * radius * (angle / 360) + + +if __name__ == "__main__": + print(arc_length(90, 10)) From 103c9e0876490d6cf683ba2d3f89e5198647bc32 Mon Sep 17 00:00:00 2001 From: Karthik S <73390717+karthiks2611@users.noreply.github.com> Date: Wed, 26 Oct 2022 01:23:21 +0530 Subject: [PATCH 428/726] Added Implementation of NAND, OR ,XNOR and NOT gates in python (#7596) * Added Implementation for XNOR gate * Added Implementation for OR gate * Added implementation of NAND gate * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Added Implementation of NAND gate * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Updated nand_gate.py * updated xnor_gate.py after some changes * Delete due to duplicate file * Updated xnor_gate.py * Added Implementation of NOT gate in python * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fixed a typo error * Updated to a new logic * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Updated nand_gate.py file Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- boolean_algebra/nand_gate.py | 47 +++++++++++++++++++++++++++++++++++ boolean_algebra/not_gate.py | 37 +++++++++++++++++++++++++++ boolean_algebra/or_gate.py | 46 ++++++++++++++++++++++++++++++++++ boolean_algebra/xnor_gate.py | 48 ++++++++++++++++++++++++++++++++++++ 4 files changed, 178 insertions(+) create mode 100644 boolean_algebra/nand_gate.py create mode 100644 boolean_algebra/not_gate.py create mode 100644 boolean_algebra/or_gate.py create mode 100644 boolean_algebra/xnor_gate.py diff --git a/boolean_algebra/nand_gate.py b/boolean_algebra/nand_gate.py new file mode 100644 index 000000000..ea3303d16 --- /dev/null +++ b/boolean_algebra/nand_gate.py @@ -0,0 +1,47 @@ +""" +A NAND Gate is a logic gate in boolean algebra which results to 0 (False) if both +the inputs are 1, and 1 (True) otherwise. It's similar to adding +a NOT gate along with an AND gate. +Following is the truth table of a NAND Gate: + ------------------------------ + | Input 1 | Input 2 | Output | + ------------------------------ + | 0 | 0 | 1 | + | 0 | 1 | 1 | + | 1 | 0 | 1 | + | 1 | 1 | 0 | + ------------------------------ +Refer - https://www.geeksforgeeks.org/logic-gates-in-python/ +""" + + +def nand_gate(input_1: int, input_2: int) -> int: + """ + Calculate NAND of the input values + >>> nand_gate(0, 0) + 1 + >>> nand_gate(0, 1) + 1 + >>> nand_gate(1, 0) + 1 + >>> nand_gate(1, 1) + 0 + """ + return int((input_1, input_2).count(0) != 0) + + +def test_nand_gate() -> None: + """ + Tests the nand_gate function + """ + assert nand_gate(0, 0) == 1 + assert nand_gate(0, 1) == 1 + assert nand_gate(1, 0) == 1 + assert nand_gate(1, 1) == 0 + + +if __name__ == "__main__": + print(nand_gate(0, 0)) + print(nand_gate(0, 1)) + print(nand_gate(1, 0)) + print(nand_gate(1, 1)) diff --git a/boolean_algebra/not_gate.py b/boolean_algebra/not_gate.py new file mode 100644 index 000000000..b41da602d --- /dev/null +++ b/boolean_algebra/not_gate.py @@ -0,0 +1,37 @@ +""" +A NOT Gate is a logic gate in boolean algebra which results to 0 (False) if the +input is high, and 1 (True) if the input is low. +Following is the truth table of a XOR Gate: + ------------------------------ + | Input | Output | + ------------------------------ + | 0 | 1 | + | 1 | 0 | + ------------------------------ +Refer - https://www.geeksforgeeks.org/logic-gates-in-python/ +""" + + +def not_gate(input_1: int) -> int: + """ + Calculate NOT of the input values + >>> not_gate(0) + 1 + >>> not_gate(1) + 0 + """ + + return 1 if input_1 == 0 else 0 + + +def test_not_gate() -> None: + """ + Tests the not_gate function + """ + assert not_gate(0) == 1 + assert not_gate(1) == 0 + + +if __name__ == "__main__": + print(not_gate(0)) + print(not_gate(1)) diff --git a/boolean_algebra/or_gate.py b/boolean_algebra/or_gate.py new file mode 100644 index 000000000..aa7e6645e --- /dev/null +++ b/boolean_algebra/or_gate.py @@ -0,0 +1,46 @@ +""" +An OR Gate is a logic gate in boolean algebra which results to 0 (False) if both the +inputs are 0, and 1 (True) otherwise. +Following is the truth table of an AND Gate: + ------------------------------ + | Input 1 | Input 2 | Output | + ------------------------------ + | 0 | 0 | 0 | + | 0 | 1 | 1 | + | 1 | 0 | 1 | + | 1 | 1 | 1 | + ------------------------------ +Refer - https://www.geeksforgeeks.org/logic-gates-in-python/ +""" + + +def or_gate(input_1: int, input_2: int) -> int: + """ + Calculate OR of the input values + >>> or_gate(0, 0) + 0 + >>> or_gate(0, 1) + 1 + >>> or_gate(1, 0) + 1 + >>> or_gate(1, 1) + 1 + """ + return int((input_1, input_2).count(1) != 0) + + +def test_or_gate() -> None: + """ + Tests the or_gate function + """ + assert or_gate(0, 0) == 0 + assert or_gate(0, 1) == 1 + assert or_gate(1, 0) == 1 + assert or_gate(1, 1) == 1 + + +if __name__ == "__main__": + print(or_gate(0, 1)) + print(or_gate(1, 0)) + print(or_gate(0, 0)) + print(or_gate(1, 1)) diff --git a/boolean_algebra/xnor_gate.py b/boolean_algebra/xnor_gate.py new file mode 100644 index 000000000..45ab2700e --- /dev/null +++ b/boolean_algebra/xnor_gate.py @@ -0,0 +1,48 @@ +""" +A XNOR Gate is a logic gate in boolean algebra which results to 0 (False) if both the +inputs are different, and 1 (True), if the inputs are same. +It's similar to adding a NOT gate to an XOR gate + +Following is the truth table of a XNOR Gate: + ------------------------------ + | Input 1 | Input 2 | Output | + ------------------------------ + | 0 | 0 | 1 | + | 0 | 1 | 0 | + | 1 | 0 | 0 | + | 1 | 1 | 1 | + ------------------------------ +Refer - https://www.geeksforgeeks.org/logic-gates-in-python/ +""" + + +def xnor_gate(input_1: int, input_2: int) -> int: + """ + Calculate XOR of the input values + >>> xnor_gate(0, 0) + 1 + >>> xnor_gate(0, 1) + 0 + >>> xnor_gate(1, 0) + 0 + >>> xnor_gate(1, 1) + 1 + """ + return 1 if input_1 == input_2 else 0 + + +def test_xnor_gate() -> None: + """ + Tests the xnor_gate function + """ + assert xnor_gate(0, 0) == 1 + assert xnor_gate(0, 1) == 0 + assert xnor_gate(1, 0) == 0 + assert xnor_gate(1, 1) == 1 + + +if __name__ == "__main__": + print(xnor_gate(0, 0)) + print(xnor_gate(0, 1)) + print(xnor_gate(1, 0)) + print(xnor_gate(1, 1)) From d25187eb7f27227381a03ba800890af7848b57d5 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Tue, 25 Oct 2022 16:34:46 -0400 Subject: [PATCH 429/726] Remove type cast in combinations algorithm (#7607) * Remove commented-out print statements in algorithmic functions * Encapsulate non-algorithmic code in __main__ * Remove unused print_matrix function * Remove print statement in __init__ * Remove print statement from doctest * Encapsulate non-algorithmic code in __main__ * Modify algorithm to return instead of print * Encapsulate non-algorithmic code in __main__ * Refactor data_safety_checker to return instead of print * updating DIRECTORY.md * updating DIRECTORY.md * Apply suggestions from code review * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * updating DIRECTORY.md * Remove int cast and change float division to int division * Move new-line chars * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/combinations.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/maths/combinations.py b/maths/combinations.py index 40f4f7a9f..6db1d773f 100644 --- a/maths/combinations.py +++ b/maths/combinations.py @@ -35,18 +35,18 @@ def combinations(n: int, k: int) -> int: # to calculate a factorial of a negative number, which is not possible if n < k or k < 0: raise ValueError("Please enter positive integers for n and k where n >= k") - return int(factorial(n) / ((factorial(k)) * (factorial(n - k)))) + return factorial(n) // (factorial(k) * factorial(n - k)) if __name__ == "__main__": print( - "\nThe number of five-card hands possible from a standard", - f"fifty-two card deck is: {combinations(52, 5)}", + "The number of five-card hands possible from a standard", + f"fifty-two card deck is: {combinations(52, 5)}\n", ) print( - "\nIf a class of 40 students must be arranged into groups of", + "If a class of 40 students must be arranged into groups of", f"4 for group projects, there are {combinations(40, 4)} ways", "to arrange them.\n", ) @@ -54,5 +54,5 @@ if __name__ == "__main__": print( "If 10 teams are competing in a Formula One race, there", f"are {combinations(10, 3)} ways that first, second and", - "third place can be awarded.\n", + "third place can be awarded.", ) From 7e3dff17c5046aad1c67fa689e5146a13e8cc052 Mon Sep 17 00:00:00 2001 From: Arya Samik <90042953+AryaSamik@users.noreply.github.com> Date: Wed, 26 Oct 2022 03:12:49 +0530 Subject: [PATCH 430/726] Docs: correct the shape of trajectory (#6255) The shape of the trajectory of projectile is a parabola. --- physics/horizontal_projectile_motion.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/physics/horizontal_projectile_motion.py b/physics/horizontal_projectile_motion.py index a747acd72..dbde3660f 100644 --- a/physics/horizontal_projectile_motion.py +++ b/physics/horizontal_projectile_motion.py @@ -3,13 +3,13 @@ Horizontal Projectile Motion problem in physics. This algorithm solves a specific problem in which the motion starts from the ground as can be seen below: (v = 0) - ** - * * - * * - * * - * * - * * -GROUND GROUND + * * + * * + * * + * * + * * + * * +GROUND GROUND For more info: https://en.wikipedia.org/wiki/Projectile_motion """ From 2c959a749163365705a53b049aa1a3e093ee4e7a Mon Sep 17 00:00:00 2001 From: harshyadavcs <108284583+harshyadavcs@users.noreply.github.com> Date: Wed, 26 Oct 2022 03:13:45 +0530 Subject: [PATCH 431/726] Update documentation of cnn_classification.py (#7486) * Updated documentation of cnn_classification.py for much better understanding * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update computer_vision/cnn_classification.py Co-authored-by: Caeden Perelli-Harris Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Caeden Perelli-Harris --- computer_vision/cnn_classification.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/computer_vision/cnn_classification.py b/computer_vision/cnn_classification.py index 6d4f19639..59e4556e0 100644 --- a/computer_vision/cnn_classification.py +++ b/computer_vision/cnn_classification.py @@ -30,9 +30,12 @@ from tensorflow.keras import layers, models if __name__ == "__main__": # Initialising the CNN + # (Sequential- Building the model layer by layer) classifier = models.Sequential() # Step 1 - Convolution + # Here 64,64 is the length & breadth of dataset images and 3 is for the RGB channel + # (3,3) is the kernel size (filter matrix) classifier.add( layers.Conv2D(32, (3, 3), input_shape=(64, 64, 3), activation="relu") ) From c3bcfbf19d43e20e9145d8968659101c1fd8b747 Mon Sep 17 00:00:00 2001 From: Karthik Ayangar <66073214+kituuu@users.noreply.github.com> Date: Wed, 26 Oct 2022 03:25:31 +0530 Subject: [PATCH 432/726] Add Cramer's rule for solving system of linear equations in two variables (#7547) * added script for solving system of linear equations in two variables * implemented all the suggested changes * changed RuntimeError to ValueError * Update matrix/system_of_linear_equation_in_2_variables.py * Update matrix/system_of_linear_equation_in_2_variables.py * Update and rename system_of_linear_equation_in_2_variables.py to cramers_rule_2x2.py Co-authored-by: Christian Clauss --- matrix/cramers_rule_2x2.py | 82 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 matrix/cramers_rule_2x2.py diff --git a/matrix/cramers_rule_2x2.py b/matrix/cramers_rule_2x2.py new file mode 100644 index 000000000..a635d66fb --- /dev/null +++ b/matrix/cramers_rule_2x2.py @@ -0,0 +1,82 @@ +# https://www.chilimath.com/lessons/advanced-algebra/cramers-rule-with-two-variables +# https://en.wikipedia.org/wiki/Cramer%27s_rule + + +def cramers_rule_2x2(equation1: list[int], equation2: list[int]) -> str: + """ + Solves the system of linear equation in 2 variables. + :param: equation1: list of 3 numbers + :param: equation2: list of 3 numbers + :return: String of result + input format : [a1, b1, d1], [a2, b2, d2] + determinant = [[a1, b1], [a2, b2]] + determinant_x = [[d1, b1], [d2, b2]] + determinant_y = [[a1, d1], [a2, d2]] + + >>> cramers_rule_2x2([2, 3, 0], [5, 1, 0]) + 'Trivial solution. (Consistent system) x = 0 and y = 0' + >>> cramers_rule_2x2([0, 4, 50], [2, 0, 26]) + 'Non-Trivial Solution (Consistent system) x = 13.0, y = 12.5' + >>> cramers_rule_2x2([11, 2, 30], [1, 0, 4]) + 'Non-Trivial Solution (Consistent system) x = 4.0, y = -7.0' + >>> cramers_rule_2x2([4, 7, 1], [1, 2, 0]) + 'Non-Trivial Solution (Consistent system) x = 2.0, y = -1.0' + + >>> cramers_rule_2x2([1, 2, 3], [2, 4, 6]) + Traceback (most recent call last): + ... + ValueError: Infinite solutions. (Consistent system) + >>> cramers_rule_2x2([1, 2, 3], [2, 4, 7]) + Traceback (most recent call last): + ... + ValueError: No solution. (Inconsistent system) + >>> cramers_rule_2x2([1, 2, 3], [11, 22]) + Traceback (most recent call last): + ... + ValueError: Please enter a valid equation. + >>> cramers_rule_2x2([0, 1, 6], [0, 0, 3]) + Traceback (most recent call last): + ... + ValueError: No solution. (Inconsistent system) + >>> cramers_rule_2x2([0, 0, 6], [0, 0, 3]) + Traceback (most recent call last): + ... + ValueError: Both a & b of two equations can't be zero. + >>> cramers_rule_2x2([1, 2, 3], [1, 2, 3]) + Traceback (most recent call last): + ... + ValueError: Infinite solutions. (Consistent system) + >>> cramers_rule_2x2([0, 4, 50], [0, 3, 99]) + Traceback (most recent call last): + ... + ValueError: No solution. (Inconsistent system) + """ + + # Check if the input is valid + if not len(equation1) == len(equation2) == 3: + raise ValueError("Please enter a valid equation.") + if equation1[0] == equation1[1] == equation2[0] == equation2[1] == 0: + raise ValueError("Both a & b of two equations can't be zero.") + + # Extract the coefficients + a1, b1, c1 = equation1 + a2, b2, c2 = equation2 + + # Calculate the determinants of the matrices + determinant = a1 * b2 - a2 * b1 + determinant_x = c1 * b2 - c2 * b1 + determinant_y = a1 * c2 - a2 * c1 + + # Check if the system of linear equations has a solution (using Cramer's rule) + if determinant == 0: + if determinant_x == determinant_y == 0: + raise ValueError("Infinite solutions. (Consistent system)") + else: + raise ValueError("No solution. (Inconsistent system)") + else: + if determinant_x == determinant_y == 0: + return "Trivial solution. (Consistent system) x = 0 and y = 0" + else: + x = determinant_x / determinant + y = determinant_y / determinant + return f"Non-Trivial Solution (Consistent system) x = {x}, y = {y}" From c31ef5e7782803b07e6d7eb4dca3b038cbdb095d Mon Sep 17 00:00:00 2001 From: RohitSingh107 <64142943+RohitSingh107@users.noreply.github.com> Date: Wed, 26 Oct 2022 03:25:48 +0530 Subject: [PATCH 433/726] Add longest common substring (#7488) * added longest common substring * added retrun type hint * Update dynamic_programming/longest_common_substring.py Co-authored-by: Caeden Perelli-Harris * Update dynamic_programming/longest_common_substring.py Co-authored-by: Caeden Perelli-Harris * Update dynamic_programming/longest_common_substring.py Co-authored-by: Caeden Perelli-Harris * Update dynamic_programming/longest_common_substring.py Co-authored-by: Caeden Perelli-Harris * Update dynamic_programming/longest_common_substring.py Co-authored-by: Caeden Perelli-Harris * Update dynamic_programming/longest_common_substring.py Co-authored-by: Caeden Perelli-Harris * Update dynamic_programming/longest_common_substring.py Co-authored-by: Caeden Perelli-Harris * Update dynamic_programming/longest_common_substring.py Co-authored-by: Caeden Perelli-Harris * Update dynamic_programming/longest_common_substring.py Co-authored-by: Caeden Perelli-Harris * Update dynamic_programming/longest_common_substring.py Co-authored-by: Caeden Perelli-Harris * Update dynamic_programming/longest_common_substring.py Co-authored-by: Caeden Perelli-Harris * changed t1, t2 to text1, text2 * Update longest_common_substring.py * Update dynamic_programming/longest_common_substring.py Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> * Update dynamic_programming/longest_common_substring.py Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * applied suggested changes * Update dynamic_programming/longest_common_substring.py Co-authored-by: Caeden Perelli-Harris * removed space between line * return longest common substring * Update dynamic_programming/longest_common_substring.py Co-authored-by: Christian Clauss * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: Caeden Perelli-Harris Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .../longest_common_substring.py | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 dynamic_programming/longest_common_substring.py diff --git a/dynamic_programming/longest_common_substring.py b/dynamic_programming/longest_common_substring.py new file mode 100644 index 000000000..84a9f1860 --- /dev/null +++ b/dynamic_programming/longest_common_substring.py @@ -0,0 +1,63 @@ +""" +Longest Common Substring Problem Statement: Given two sequences, find the +longest common substring present in both of them. A substring is +necessarily continuous. +Example: "abcdef" and "xabded" have two longest common substrings, "ab" or "de". +Therefore, algorithm should return any one of them. +""" + + +def longest_common_substring(text1: str, text2: str) -> str: + """ + Finds the longest common substring between two strings. + >>> longest_common_substring("", "") + '' + >>> longest_common_substring("a","") + '' + >>> longest_common_substring("", "a") + '' + >>> longest_common_substring("a", "a") + 'a' + >>> longest_common_substring("abcdef", "bcd") + 'bcd' + >>> longest_common_substring("abcdef", "xabded") + 'ab' + >>> longest_common_substring("GeeksforGeeks", "GeeksQuiz") + 'Geeks' + >>> longest_common_substring("abcdxyz", "xyzabcd") + 'abcd' + >>> longest_common_substring("zxabcdezy", "yzabcdezx") + 'abcdez' + >>> longest_common_substring("OldSite:GeeksforGeeks.org", "NewSite:GeeksQuiz.com") + 'Site:Geeks' + >>> longest_common_substring(1, 1) + Traceback (most recent call last): + ... + ValueError: longest_common_substring() takes two strings for inputs + """ + + if not (isinstance(text1, str) and isinstance(text2, str)): + raise ValueError("longest_common_substring() takes two strings for inputs") + + text1_length = len(text1) + text2_length = len(text2) + + dp = [[0] * (text2_length + 1) for _ in range(text1_length + 1)] + ans_index = 0 + ans_length = 0 + + for i in range(1, text1_length + 1): + for j in range(1, text2_length + 1): + if text1[i - 1] == text2[j - 1]: + dp[i][j] = 1 + dp[i - 1][j - 1] + if dp[i][j] > ans_length: + ans_index = i + ans_length = dp[i][j] + + return text1[ans_index - ans_length : ans_index] + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 505c5e20fa7efec9f6c4cb5b8bafd8ff2001e3b7 Mon Sep 17 00:00:00 2001 From: Mislah <76743829+mislah@users.noreply.github.com> Date: Wed, 26 Oct 2022 03:56:05 +0530 Subject: [PATCH 434/726] Included area of n sided regular polygon (#7438) * Included area of n sided regular polygon Added a function to calculate the area of n sided regular polygons * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * code standard fixes as per PR comments * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/area.py | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/maths/area.py b/maths/area.py index abbf7aa85..5db7dac38 100644 --- a/maths/area.py +++ b/maths/area.py @@ -1,12 +1,14 @@ """ Find the area of various geometric shapes +Wikipedia reference: https://en.wikipedia.org/wiki/Area """ -from math import pi, sqrt +from math import pi, sqrt, tan def surface_area_cube(side_length: float) -> float: """ Calculate the Surface Area of a Cube. + >>> surface_area_cube(1) 6 >>> surface_area_cube(1.6) @@ -28,6 +30,7 @@ def surface_area_cube(side_length: float) -> float: def surface_area_cuboid(length: float, breadth: float, height: float) -> float: """ Calculate the Surface Area of a Cuboid. + >>> surface_area_cuboid(1, 2, 3) 22 >>> surface_area_cuboid(0, 0, 0) @@ -57,6 +60,7 @@ def surface_area_sphere(radius: float) -> float: Calculate the Surface Area of a Sphere. Wikipedia reference: https://en.wikipedia.org/wiki/Sphere Formula: 4 * pi * r^2 + >>> surface_area_sphere(5) 314.1592653589793 >>> surface_area_sphere(1) @@ -79,6 +83,7 @@ def surface_area_hemisphere(radius: float) -> float: """ Calculate the Surface Area of a Hemisphere. Formula: 3 * pi * r^2 + >>> surface_area_hemisphere(5) 235.61944901923448 >>> surface_area_hemisphere(1) @@ -102,6 +107,7 @@ def surface_area_cone(radius: float, height: float) -> float: Calculate the Surface Area of a Cone. Wikipedia reference: https://en.wikipedia.org/wiki/Cone Formula: pi * r * (r + (h ** 2 + r ** 2) ** 0.5) + >>> surface_area_cone(10, 24) 1130.9733552923256 >>> surface_area_cone(6, 8) @@ -133,6 +139,7 @@ def surface_area_conical_frustum( ) -> float: """ Calculate the Surface Area of a Conical Frustum. + >>> surface_area_conical_frustum(1, 2, 3) 45.511728065337266 >>> surface_area_conical_frustum(4, 5, 6) @@ -167,6 +174,7 @@ def surface_area_cylinder(radius: float, height: float) -> float: Calculate the Surface Area of a Cylinder. Wikipedia reference: https://en.wikipedia.org/wiki/Cylinder Formula: 2 * pi * r * (h + r) + >>> surface_area_cylinder(7, 10) 747.6990515543707 >>> surface_area_cylinder(1.6, 2.6) @@ -196,6 +204,7 @@ def surface_area_cylinder(radius: float, height: float) -> float: def area_rectangle(length: float, width: float) -> float: """ Calculate the area of a rectangle. + >>> area_rectangle(10, 20) 200 >>> area_rectangle(1.6, 2.6) @@ -223,6 +232,7 @@ def area_rectangle(length: float, width: float) -> float: def area_square(side_length: float) -> float: """ Calculate the area of a square. + >>> area_square(10) 100 >>> area_square(0) @@ -242,6 +252,7 @@ def area_square(side_length: float) -> float: def area_triangle(base: float, height: float) -> float: """ Calculate the area of a triangle given the base and height. + >>> area_triangle(10, 10) 50.0 >>> area_triangle(1.6, 2.6) @@ -270,6 +281,7 @@ def area_triangle_three_sides(side1: float, side2: float, side3: float) -> float """ Calculate area of triangle when the length of 3 sides are known. This function uses Heron's formula: https://en.wikipedia.org/wiki/Heron%27s_formula + >>> area_triangle_three_sides(5, 12, 13) 30.0 >>> area_triangle_three_sides(10, 11, 12) @@ -316,6 +328,7 @@ def area_triangle_three_sides(side1: float, side2: float, side3: float) -> float def area_parallelogram(base: float, height: float) -> float: """ Calculate the area of a parallelogram. + >>> area_parallelogram(10, 20) 200 >>> area_parallelogram(1.6, 2.6) @@ -343,6 +356,7 @@ def area_parallelogram(base: float, height: float) -> float: def area_trapezium(base1: float, base2: float, height: float) -> float: """ Calculate the area of a trapezium. + >>> area_trapezium(10, 20, 30) 450.0 >>> area_trapezium(1.6, 2.6, 3.6) @@ -386,6 +400,7 @@ def area_trapezium(base1: float, base2: float, height: float) -> float: def area_circle(radius: float) -> float: """ Calculate the area of a circle. + >>> area_circle(20) 1256.6370614359173 >>> area_circle(1.6) @@ -405,6 +420,7 @@ def area_circle(radius: float) -> float: def area_ellipse(radius_x: float, radius_y: float) -> float: """ Calculate the area of a ellipse. + >>> area_ellipse(10, 10) 314.1592653589793 >>> area_ellipse(10, 20) @@ -434,6 +450,7 @@ def area_ellipse(radius_x: float, radius_y: float) -> float: def area_rhombus(diagonal_1: float, diagonal_2: float) -> float: """ Calculate the area of a rhombus. + >>> area_rhombus(10, 20) 100.0 >>> area_rhombus(1.6, 2.6) @@ -458,6 +475,51 @@ def area_rhombus(diagonal_1: float, diagonal_2: float) -> float: return 1 / 2 * diagonal_1 * diagonal_2 +def area_reg_polygon(sides: int, length: float) -> float: + """ + Calculate the area of a regular polygon. + Wikipedia reference: https://en.wikipedia.org/wiki/Polygon#Regular_polygons + Formula: (n*s^2*cot(pi/n))/4 + + >>> area_reg_polygon(3, 10) + 43.301270189221945 + >>> area_reg_polygon(4, 10) + 100.00000000000001 + >>> area_reg_polygon(0, 0) + Traceback (most recent call last): + ... + ValueError: area_reg_polygon() only accepts integers greater than or equal to \ +three as number of sides + >>> area_reg_polygon(-1, -2) + Traceback (most recent call last): + ... + ValueError: area_reg_polygon() only accepts integers greater than or equal to \ +three as number of sides + >>> area_reg_polygon(5, -2) + Traceback (most recent call last): + ... + ValueError: area_reg_polygon() only accepts non-negative values as \ +length of a side + >>> area_reg_polygon(-1, 2) + Traceback (most recent call last): + ... + ValueError: area_reg_polygon() only accepts integers greater than or equal to \ +three as number of sides + """ + if not isinstance(sides, int) or sides < 3: + raise ValueError( + "area_reg_polygon() only accepts integers greater than or \ +equal to three as number of sides" + ) + elif length < 0: + raise ValueError( + "area_reg_polygon() only accepts non-negative values as \ +length of a side" + ) + return (sides * length**2) / (4 * tan(pi / sides)) + return (sides * length**2) / (4 * tan(pi / sides)) + + if __name__ == "__main__": import doctest @@ -481,3 +543,6 @@ if __name__ == "__main__": print(f"Cone: {surface_area_cone(10, 20) = }") print(f"Conical Frustum: {surface_area_conical_frustum(10, 20, 30) = }") print(f"Cylinder: {surface_area_cylinder(10, 20) = }") + print(f"Equilateral Triangle: {area_reg_polygon(3, 10) = }") + print(f"Square: {area_reg_polygon(4, 10) = }") + print(f"Reqular Pentagon: {area_reg_polygon(5, 10) = }") From 68f6e9ac305b75a7aa8455977e35eeb942051959 Mon Sep 17 00:00:00 2001 From: M3talM0nk3y Date: Tue, 25 Oct 2022 23:31:16 -0400 Subject: [PATCH 435/726] Added function that checks if a string is an isogram (#7608) * Added function that checks if a string is an isogram. * Added wiki reference and fixed comments. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Made function name more self-documenting. Raise ValueError if string contains 1 or more digits. Renamed file. Lowercase string inside function. * Removed check_isogram.py (file renamed). * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixed test failure. * Raise ValueError when string has non-alpha characters. Removed import. Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- strings/is_isogram.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 strings/is_isogram.py diff --git a/strings/is_isogram.py b/strings/is_isogram.py new file mode 100644 index 000000000..a9d9acc81 --- /dev/null +++ b/strings/is_isogram.py @@ -0,0 +1,30 @@ +""" +wiki: https://en.wikipedia.org/wiki/Heterogram_(literature)#Isograms +""" + + +def is_isogram(string: str) -> bool: + """ + An isogram is a word in which no letter is repeated. + Examples of isograms are uncopyrightable and ambidextrously. + >>> is_isogram('Uncopyrightable') + True + >>> is_isogram('allowance') + False + >>> is_isogram('copy1') + Traceback (most recent call last): + ... + ValueError: String must only contain alphabetic characters. + """ + if not all(x.isalpha() for x in string): + raise ValueError("String must only contain alphabetic characters.") + + letters = sorted(string.lower()) + return len(letters) == len(set(letters)) + + +if __name__ == "__main__": + input_str = input("Enter a string ").strip() + + isogram = is_isogram(input_str) + print(f"{input_str} is {'an' if isogram else 'not an'} isogram.") From abf0909b6877d64c3adc9d666b85aa38bcd98566 Mon Sep 17 00:00:00 2001 From: CenTdemeern1 Date: Tue, 25 Oct 2022 23:09:28 -0700 Subject: [PATCH 436/726] Write a proper implementation for base16 (#6909) According to CONTRIBUTING.md: "Algorithms in this repo should not be how-to examples for existing Python packages." --- ciphers/base16.py | 83 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 27 deletions(-) diff --git a/ciphers/base16.py b/ciphers/base16.py index a149a6d8c..6cd62846f 100644 --- a/ciphers/base16.py +++ b/ciphers/base16.py @@ -1,34 +1,63 @@ -import base64 - - -def base16_encode(inp: str) -> bytes: +def base16_encode(data: bytes) -> str: """ - Encodes a given utf-8 string into base-16. + Encodes the given bytes into base16. - >>> base16_encode('Hello World!') - b'48656C6C6F20576F726C6421' - >>> base16_encode('HELLO WORLD!') - b'48454C4C4F20574F524C4421' - >>> base16_encode('') - b'' - """ - # encode the input into a bytes-like object and then encode b16encode that - return base64.b16encode(inp.encode("utf-8")) - - -def base16_decode(b16encoded: bytes) -> str: - """ - Decodes from base-16 to a utf-8 string. - - >>> base16_decode(b'48656C6C6F20576F726C6421') - 'Hello World!' - >>> base16_decode(b'48454C4C4F20574F524C4421') - 'HELLO WORLD!' - >>> base16_decode(b'') + >>> base16_encode(b'Hello World!') + '48656C6C6F20576F726C6421' + >>> base16_encode(b'HELLO WORLD!') + '48454C4C4F20574F524C4421' + >>> base16_encode(b'') '' """ - # b16decode the input into bytes and decode that into a human readable string - return base64.b16decode(b16encoded).decode("utf-8") + # Turn the data into a list of integers (where each integer is a byte), + # Then turn each byte into its hexadecimal representation, make sure + # it is uppercase, and then join everything together and return it. + return "".join([hex(byte)[2:].zfill(2).upper() for byte in list(data)]) + + +def base16_decode(data: str) -> bytes: + """ + Decodes the given base16 encoded data into bytes. + + >>> base16_decode('48656C6C6F20576F726C6421') + b'Hello World!' + >>> base16_decode('48454C4C4F20574F524C4421') + b'HELLO WORLD!' + >>> base16_decode('') + b'' + >>> base16_decode('486') + Traceback (most recent call last): + ... + ValueError: Base16 encoded data is invalid: + Data does not have an even number of hex digits. + >>> base16_decode('48656c6c6f20576f726c6421') + Traceback (most recent call last): + ... + ValueError: Base16 encoded data is invalid: + Data is not uppercase hex or it contains invalid characters. + >>> base16_decode('This is not base64 encoded data.') + Traceback (most recent call last): + ... + ValueError: Base16 encoded data is invalid: + Data is not uppercase hex or it contains invalid characters. + """ + # Check data validity, following RFC3548 + # https://www.ietf.org/rfc/rfc3548.txt + if (len(data) % 2) != 0: + raise ValueError( + """Base16 encoded data is invalid: +Data does not have an even number of hex digits.""" + ) + # Check the character set - the standard base16 alphabet + # is uppercase according to RFC3548 section 6 + if not set(data) <= set("0123456789ABCDEF"): + raise ValueError( + """Base16 encoded data is invalid: +Data is not uppercase hex or it contains invalid characters.""" + ) + # For every two hexadecimal digits (= a byte), turn it into an integer. + # Then, string the result together into bytes, and return it. + return bytes(int(data[i] + data[i + 1], 16) for i in range(0, len(data), 2)) if __name__ == "__main__": From 93905653506c684e393d984ad814af66af8ee0e9 Mon Sep 17 00:00:00 2001 From: Karthik Ayangar <66073214+kituuu@users.noreply.github.com> Date: Wed, 26 Oct 2022 14:06:40 +0530 Subject: [PATCH 437/726] added support for inverse of 3x3 matrix (#7355) * added support for inverse of 3x3 matrix * Modified Docstring and improved code * fixed an error * Modified docstring * Apply all suggestions from code review Co-authored-by: Caeden Perelli-Harris Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> Co-authored-by: Christian Clauss Co-authored-by: Caeden Perelli-Harris Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> --- matrix/inverse_of_matrix.py | 137 ++++++++++++++++++++++++++++++++---- 1 file changed, 122 insertions(+), 15 deletions(-) diff --git a/matrix/inverse_of_matrix.py b/matrix/inverse_of_matrix.py index 770ce39b5..e53d90df8 100644 --- a/matrix/inverse_of_matrix.py +++ b/matrix/inverse_of_matrix.py @@ -2,22 +2,25 @@ from __future__ import annotations from decimal import Decimal +from numpy import array + def inverse_of_matrix(matrix: list[list[float]]) -> list[list[float]]: """ A matrix multiplied with its inverse gives the identity matrix. - This function finds the inverse of a 2x2 matrix. + This function finds the inverse of a 2x2 and 3x3 matrix. If the determinant of a matrix is 0, its inverse does not exist. Sources for fixing inaccurate float arithmetic: https://stackoverflow.com/questions/6563058/how-do-i-use-accurate-float-arithmetic-in-python https://docs.python.org/3/library/decimal.html + Doctests for 2x2 >>> inverse_of_matrix([[2, 5], [2, 0]]) [[0.0, 0.5], [0.2, -0.2]] >>> inverse_of_matrix([[2.5, 5], [1, 2]]) Traceback (most recent call last): - ... + ... ValueError: This matrix has no inverse. >>> inverse_of_matrix([[12, -16], [-9, 0]]) [[0.0, -0.1111111111111111], [-0.0625, -0.08333333333333333]] @@ -25,24 +28,128 @@ def inverse_of_matrix(matrix: list[list[float]]) -> list[list[float]]: [[0.16666666666666666, -0.0625], [-0.3333333333333333, 0.25]] >>> inverse_of_matrix([[10, 5], [3, 2.5]]) [[0.25, -0.5], [-0.3, 1.0]] + + Doctests for 3x3 + >>> inverse_of_matrix([[2, 5, 7], [2, 0, 1], [1, 2, 3]]) + [[2.0, 5.0, -4.0], [1.0, 1.0, -1.0], [-5.0, -12.0, 10.0]] + >>> inverse_of_matrix([[1, 2, 2], [1, 2, 2], [3, 2, -1]]) + Traceback (most recent call last): + ... + ValueError: This matrix has no inverse. + + >>> inverse_of_matrix([[],[]]) + Traceback (most recent call last): + ... + ValueError: Please provide a matrix of size 2x2 or 3x3. + + >>> inverse_of_matrix([[1, 2], [3, 4], [5, 6]]) + Traceback (most recent call last): + ... + ValueError: Please provide a matrix of size 2x2 or 3x3. + + >>> inverse_of_matrix([[1, 2, 1], [0,3, 4]]) + Traceback (most recent call last): + ... + ValueError: Please provide a matrix of size 2x2 or 3x3. + + >>> inverse_of_matrix([[1, 2, 3], [7, 8, 9], [7, 8, 9]]) + Traceback (most recent call last): + ... + ValueError: This matrix has no inverse. + + >>> inverse_of_matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]] """ - d = Decimal # An abbreviation for conciseness + d = Decimal # Check if the provided matrix has 2 rows and 2 columns # since this implementation only works for 2x2 matrices - if len(matrix) != 2 or len(matrix[0]) != 2 or len(matrix[1]) != 2: - raise ValueError("Please provide a matrix of size 2x2.") + if len(matrix) == 2 and len(matrix[0]) == 2 and len(matrix[1]) == 2: + # Calculate the determinant of the matrix + determinant = float( + d(matrix[0][0]) * d(matrix[1][1]) - d(matrix[1][0]) * d(matrix[0][1]) + ) + if determinant == 0: + raise ValueError("This matrix has no inverse.") - # Calculate the determinant of the matrix - determinant = d(matrix[0][0]) * d(matrix[1][1]) - d(matrix[1][0]) * d(matrix[0][1]) - if determinant == 0: - raise ValueError("This matrix has no inverse.") + # Creates a copy of the matrix with swapped positions of the elements + swapped_matrix = [[0.0, 0.0], [0.0, 0.0]] + swapped_matrix[0][0], swapped_matrix[1][1] = matrix[1][1], matrix[0][0] + swapped_matrix[1][0], swapped_matrix[0][1] = -matrix[1][0], -matrix[0][1] - # Creates a copy of the matrix with swapped positions of the elements - swapped_matrix = [[0.0, 0.0], [0.0, 0.0]] - swapped_matrix[0][0], swapped_matrix[1][1] = matrix[1][1], matrix[0][0] - swapped_matrix[1][0], swapped_matrix[0][1] = -matrix[1][0], -matrix[0][1] + # Calculate the inverse of the matrix + return [ + [(float(d(n)) / determinant) or 0.0 for n in row] for row in swapped_matrix + ] + elif ( + len(matrix) == 3 + and len(matrix[0]) == 3 + and len(matrix[1]) == 3 + and len(matrix[2]) == 3 + ): + # Calculate the determinant of the matrix using Sarrus rule + determinant = float( + ( + (d(matrix[0][0]) * d(matrix[1][1]) * d(matrix[2][2])) + + (d(matrix[0][1]) * d(matrix[1][2]) * d(matrix[2][0])) + + (d(matrix[0][2]) * d(matrix[1][0]) * d(matrix[2][1])) + ) + - ( + (d(matrix[0][2]) * d(matrix[1][1]) * d(matrix[2][0])) + + (d(matrix[0][1]) * d(matrix[1][0]) * d(matrix[2][2])) + + (d(matrix[0][0]) * d(matrix[1][2]) * d(matrix[2][1])) + ) + ) + if determinant == 0: + raise ValueError("This matrix has no inverse.") - # Calculate the inverse of the matrix - return [[float(d(n) / determinant) or 0.0 for n in row] for row in swapped_matrix] + # Creating cofactor matrix + cofactor_matrix = [ + [d(0.0), d(0.0), d(0.0)], + [d(0.0), d(0.0), d(0.0)], + [d(0.0), d(0.0), d(0.0)], + ] + cofactor_matrix[0][0] = (d(matrix[1][1]) * d(matrix[2][2])) - ( + d(matrix[1][2]) * d(matrix[2][1]) + ) + cofactor_matrix[0][1] = -( + (d(matrix[1][0]) * d(matrix[2][2])) - (d(matrix[1][2]) * d(matrix[2][0])) + ) + cofactor_matrix[0][2] = (d(matrix[1][0]) * d(matrix[2][1])) - ( + d(matrix[1][1]) * d(matrix[2][0]) + ) + cofactor_matrix[1][0] = -( + (d(matrix[0][1]) * d(matrix[2][2])) - (d(matrix[0][2]) * d(matrix[2][1])) + ) + cofactor_matrix[1][1] = (d(matrix[0][0]) * d(matrix[2][2])) - ( + d(matrix[0][2]) * d(matrix[2][0]) + ) + cofactor_matrix[1][2] = -( + (d(matrix[0][0]) * d(matrix[2][1])) - (d(matrix[0][1]) * d(matrix[2][0])) + ) + cofactor_matrix[2][0] = (d(matrix[0][1]) * d(matrix[1][2])) - ( + d(matrix[0][2]) * d(matrix[1][1]) + ) + cofactor_matrix[2][1] = -( + (d(matrix[0][0]) * d(matrix[1][2])) - (d(matrix[0][2]) * d(matrix[1][0])) + ) + cofactor_matrix[2][2] = (d(matrix[0][0]) * d(matrix[1][1])) - ( + d(matrix[0][1]) * d(matrix[1][0]) + ) + + # Transpose the cofactor matrix (Adjoint matrix) + adjoint_matrix = array(cofactor_matrix) + for i in range(3): + for j in range(3): + adjoint_matrix[i][j] = cofactor_matrix[j][i] + + # Inverse of the matrix using the formula (1/determinant) * adjoint matrix + inverse_matrix = array(cofactor_matrix) + for i in range(3): + for j in range(3): + inverse_matrix[i][j] /= d(determinant) + + # Calculate the inverse of the matrix + return [[float(d(n)) or 0.0 for n in row] for row in inverse_matrix] + raise ValueError("Please provide a matrix of size 2x2 or 3x3.") From 8fd06efe22ec3e870ac1fa375bd4600cb30baad4 Mon Sep 17 00:00:00 2001 From: JatinR05 <71865805+JatinR05@users.noreply.github.com> Date: Wed, 26 Oct 2022 20:13:01 +0530 Subject: [PATCH 438/726] Create minimums_squares_to_represent_a_number.py (#7595) * Create minimums_squares_to_represent_a_number.py added a dynamic programming approach of finding the minimum number of square to represent a number. eg : 25 = 5*5 37 = 6*6 + 1*1 21 = 4*4 + 2*2 + 1*1 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update and rename minimums_squares_to_represent_a_number.py to minimum_squares_to_represent_a_number.py updated the code * Update minimum_squares_to_represent_a_number.py I have added the appropriate checks for 0 and 12.34. It would be great if you could suggest a name for the dp array * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update minimum_squares_to_represent_a_number.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update minimum_squares_to_represent_a_number.py updated * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update minimum_squares_to_represent_a_number.py updated * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .../minimum_squares_to_represent_a_number.py | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 dynamic_programming/minimum_squares_to_represent_a_number.py diff --git a/dynamic_programming/minimum_squares_to_represent_a_number.py b/dynamic_programming/minimum_squares_to_represent_a_number.py new file mode 100644 index 000000000..bf5849f5b --- /dev/null +++ b/dynamic_programming/minimum_squares_to_represent_a_number.py @@ -0,0 +1,48 @@ +import math +import sys + + +def minimum_squares_to_represent_a_number(number: int) -> int: + """ + Count the number of minimum squares to represent a number + >>> minimum_squares_to_represent_a_number(25) + 1 + >>> minimum_squares_to_represent_a_number(37) + 2 + >>> minimum_squares_to_represent_a_number(21) + 3 + >>> minimum_squares_to_represent_a_number(58) + 2 + >>> minimum_squares_to_represent_a_number(-1) + Traceback (most recent call last): + ... + ValueError: the value of input must not be a negative number + >>> minimum_squares_to_represent_a_number(0) + 1 + >>> minimum_squares_to_represent_a_number(12.34) + Traceback (most recent call last): + ... + ValueError: the value of input must be a natural number + """ + if number != int(number): + raise ValueError("the value of input must be a natural number") + if number < 0: + raise ValueError("the value of input must not be a negative number") + if number == 0: + return 1 + answers = [-1] * (number + 1) + answers[0] = 0 + for i in range(1, number + 1): + answer = sys.maxsize + root = int(math.sqrt(i)) + for j in range(1, root + 1): + current_answer = 1 + answers[i - (j**2)] + answer = min(answer, current_answer) + answers[i] = answer + return answers[number] + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 5c8a939c5a51104fce4b22ef56d29720c6ce47bb Mon Sep 17 00:00:00 2001 From: Shubham Kondekar <40213815+kondekarshubham123@users.noreply.github.com> Date: Wed, 26 Oct 2022 20:36:15 +0530 Subject: [PATCH 439/726] Create largest_square_area_in_matrix.py (#7673) * Create largest_square_area_in_matrix.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update matrix/largest_square_area_in_matrix.py Co-authored-by: Caeden Perelli-Harris * Update matrix/largest_square_area_in_matrix.py Co-authored-by: Caeden Perelli-Harris * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update largest_square_area_in_matrix.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Caeden Perelli-Harris --- matrix/largest_square_area_in_matrix.py | 191 ++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 matrix/largest_square_area_in_matrix.py diff --git a/matrix/largest_square_area_in_matrix.py b/matrix/largest_square_area_in_matrix.py new file mode 100644 index 000000000..cf975cb7c --- /dev/null +++ b/matrix/largest_square_area_in_matrix.py @@ -0,0 +1,191 @@ +""" +Question: +Given a binary matrix mat of size n * m, find out the maximum size square +sub-matrix with all 1s. + +--- +Example 1: + +Input: +n = 2, m = 2 +mat = [[1, 1], + [1, 1]] + +Output: +2 + +Explanation: The maximum size of the square +sub-matrix is 2. The matrix itself is the +maximum sized sub-matrix in this case. +--- +Example 2 + +Input: +n = 2, m = 2 +mat = [[0, 0], + [0, 0]] +Output: 0 + +Explanation: There is no 1 in the matrix. + + +Approach: +We initialize another matrix (dp) with the same dimensions +as the original one initialized with all 0’s. + +dp_array(i,j) represents the side length of the maximum square whose +bottom right corner is the cell with index (i,j) in the original matrix. + +Starting from index (0,0), for every 1 found in the original matrix, +we update the value of the current element as + +dp_array(i,j)=dp_array(dp(i−1,j),dp_array(i−1,j−1),dp_array(i,j−1)) + 1. +""" + + +def largest_square_area_in_matrix_top_down_approch( + rows: int, cols: int, mat: list[list[int]] +) -> int: + """ + Function updates the largest_square_area[0], if recursive call found + square with maximum area. + + We aren't using dp_array here, so the time complexity would be exponential. + + >>> largest_square_area_in_matrix_top_down_approch(2, 2, [[1,1], [1,1]]) + 2 + >>> largest_square_area_in_matrix_top_down_approch(2, 2, [[0,0], [0,0]]) + 0 + """ + + def update_area_of_max_square(row: int, col: int) -> int: + + # BASE CASE + if row >= rows or col >= cols: + return 0 + + right = update_area_of_max_square(row, col + 1) + diagonal = update_area_of_max_square(row + 1, col + 1) + down = update_area_of_max_square(row + 1, col) + + if mat[row][col]: + sub_problem_sol = 1 + min([right, diagonal, down]) + largest_square_area[0] = max(largest_square_area[0], sub_problem_sol) + return sub_problem_sol + else: + return 0 + + largest_square_area = [0] + update_area_of_max_square(0, 0) + return largest_square_area[0] + + +def largest_square_area_in_matrix_top_down_approch_with_dp( + rows: int, cols: int, mat: list[list[int]] +) -> int: + """ + Function updates the largest_square_area[0], if recursive call found + square with maximum area. + + We are using dp_array here, so the time complexity would be O(N^2). + + >>> largest_square_area_in_matrix_top_down_approch_with_dp(2, 2, [[1,1], [1,1]]) + 2 + >>> largest_square_area_in_matrix_top_down_approch_with_dp(2, 2, [[0,0], [0,0]]) + 0 + """ + + def update_area_of_max_square_using_dp_array( + row: int, col: int, dp_array: list[list[int]] + ) -> int: + if row >= rows or col >= cols: + return 0 + if dp_array[row][col] != -1: + return dp_array[row][col] + + right = update_area_of_max_square_using_dp_array(row, col + 1, dp_array) + diagonal = update_area_of_max_square_using_dp_array(row + 1, col + 1, dp_array) + down = update_area_of_max_square_using_dp_array(row + 1, col, dp_array) + + if mat[row][col]: + sub_problem_sol = 1 + min([right, diagonal, down]) + largest_square_area[0] = max(largest_square_area[0], sub_problem_sol) + dp_array[row][col] = sub_problem_sol + return sub_problem_sol + else: + return 0 + + largest_square_area = [0] + dp_array = [[-1] * cols for _ in range(rows)] + update_area_of_max_square_using_dp_array(0, 0, dp_array) + + return largest_square_area[0] + + +def largest_square_area_in_matrix_bottom_up( + rows: int, cols: int, mat: list[list[int]] +) -> int: + """ + Function updates the largest_square_area, using bottom up approach. + + >>> largest_square_area_in_matrix_bottom_up(2, 2, [[1,1], [1,1]]) + 2 + >>> largest_square_area_in_matrix_bottom_up(2, 2, [[0,0], [0,0]]) + 0 + + """ + dp_array = [[0] * (cols + 1) for _ in range(rows + 1)] + largest_square_area = 0 + for row in range(rows - 1, -1, -1): + for col in range(cols - 1, -1, -1): + + right = dp_array[row][col + 1] + diagonal = dp_array[row + 1][col + 1] + bottom = dp_array[row + 1][col] + + if mat[row][col] == 1: + dp_array[row][col] = 1 + min(right, diagonal, bottom) + largest_square_area = max(dp_array[row][col], largest_square_area) + else: + dp_array[row][col] = 0 + + return largest_square_area + + +def largest_square_area_in_matrix_bottom_up_space_optimization( + rows: int, cols: int, mat: list[list[int]] +) -> int: + """ + Function updates the largest_square_area, using bottom up + approach. with space optimization. + + >>> largest_square_area_in_matrix_bottom_up_space_optimization(2, 2, [[1,1], [1,1]]) + 2 + >>> largest_square_area_in_matrix_bottom_up_space_optimization(2, 2, [[0,0], [0,0]]) + 0 + """ + current_row = [0] * (cols + 1) + next_row = [0] * (cols + 1) + largest_square_area = 0 + for row in range(rows - 1, -1, -1): + for col in range(cols - 1, -1, -1): + + right = current_row[col + 1] + diagonal = next_row[col + 1] + bottom = next_row[col] + + if mat[row][col] == 1: + current_row[col] = 1 + min(right, diagonal, bottom) + largest_square_area = max(current_row[col], largest_square_area) + else: + current_row[col] = 0 + next_row = current_row + + return largest_square_area + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + print(largest_square_area_in_matrix_bottom_up(2, 2, [[1, 1], [1, 1]])) From 614274a9dc996f64dd470d2029847cc229f19346 Mon Sep 17 00:00:00 2001 From: Shubham Kondekar <40213815+kondekarshubham123@users.noreply.github.com> Date: Wed, 26 Oct 2022 22:28:33 +0530 Subject: [PATCH 440/726] Update spiral_print.py (#7674) * Update spiral_print.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update matrix/spiral_print.py Co-authored-by: Caeden Perelli-Harris * Update matrix/spiral_print.py Co-authored-by: Caeden Perelli-Harris * Update matrix/spiral_print.py Co-authored-by: Caeden Perelli-Harris * Update matrix/spiral_print.py Co-authored-by: Caeden Perelli-Harris * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update spiral_print.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update spiral_print.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update spiral_print.py * Update spiral_print.py * Update spiral_print.py * Update spiral_print.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Caeden Perelli-Harris --- matrix/spiral_print.py | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/matrix/spiral_print.py b/matrix/spiral_print.py index 0cf732d60..0d0be1527 100644 --- a/matrix/spiral_print.py +++ b/matrix/spiral_print.py @@ -76,7 +76,56 @@ def spiral_print_clockwise(a: list[list[int]]) -> None: return +# Other Easy to understand Approach + + +def spiral_traversal(matrix: list[list]) -> list[int]: + """ + >>> spiral_traversal([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]) + [1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7] + + Example: + matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]] + Algorithm: + Step 1. first pop the 0 index list. (which is [1,2,3,4] and concatenate the + output of [step 2]) + Step 2. Now perform matrix’s Transpose operation (Change rows to column + and vice versa) and reverse the resultant matrix. + Step 3. Pass the output of [2nd step], to same recursive function till + base case hits. + Dry Run: + Stage 1. + [1, 2, 3, 4] + spiral_traversal([ + [8, 12], [7, 11], [6, 10], [5, 9]] + ]) + Stage 2. + [1, 2, 3, 4, 8, 12] + spiral_traversal([ + [11, 10, 9], [7, 6, 5] + ]) + Stage 3. + [1, 2, 3, 4, 8, 12, 11, 10, 9] + spiral_traversal([ + [5], [6], [7] + ]) + Stage 4. + [1, 2, 3, 4, 8, 12, 11, 10, 9, 5] + spiral_traversal([ + [5], [6], [7] + ]) + Stage 5. + [1, 2, 3, 4, 8, 12, 11, 10, 9, 5] + spiral_traversal([[6, 7]]) + Stage 6. + [1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7] + spiral_traversal([]) + """ + if matrix: + return list(matrix.pop(0)) + spiral_traversal(list(zip(*matrix))[::-1]) + else: + return [] + + # driver code if __name__ == "__main__": + import doctest + + doctest.testmod() + a = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]] spiral_print_clockwise(a) From 74325d079cf4394f7b75c26b334a81e98b7e25b1 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 26 Oct 2022 22:08:53 +0200 Subject: [PATCH 441/726] Rename quantum_random.py to quantum_random.py.DISABLED.txt (#7683) * Rename quantum_random.py to quantum_random.py.DISABLED.txt #7682 * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 13 ++++++++++++- ...tum_random.py => quantum_random.py.DISABLED.txt} | 0 2 files changed, 12 insertions(+), 1 deletion(-) rename quantum/{quantum_random.py => quantum_random.py.DISABLED.txt} (100%) diff --git a/DIRECTORY.md b/DIRECTORY.md index 3e722a878..ba7d3e62a 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -56,8 +56,13 @@ ## Boolean Algebra * [And Gate](boolean_algebra/and_gate.py) + * [Nand Gate](boolean_algebra/nand_gate.py) * [Norgate](boolean_algebra/norgate.py) + * [Not Gate](boolean_algebra/not_gate.py) + * [Or Gate](boolean_algebra/or_gate.py) * [Quine Mc Cluskey](boolean_algebra/quine_mc_cluskey.py) + * [Xnor Gate](boolean_algebra/xnor_gate.py) + * [Xor Gate](boolean_algebra/xor_gate.py) ## Cellular Automata * [Conways Game Of Life](cellular_automata/conways_game_of_life.py) @@ -288,6 +293,7 @@ * [Iterating Through Submasks](dynamic_programming/iterating_through_submasks.py) * [Knapsack](dynamic_programming/knapsack.py) * [Longest Common Subsequence](dynamic_programming/longest_common_subsequence.py) + * [Longest Common Substring](dynamic_programming/longest_common_substring.py) * [Longest Increasing Subsequence](dynamic_programming/longest_increasing_subsequence.py) * [Longest Increasing Subsequence O(Nlogn)](dynamic_programming/longest_increasing_subsequence_o(nlogn).py) * [Longest Sub Array](dynamic_programming/longest_sub_array.py) @@ -298,6 +304,7 @@ * [Minimum Coin Change](dynamic_programming/minimum_coin_change.py) * [Minimum Cost Path](dynamic_programming/minimum_cost_path.py) * [Minimum Partition](dynamic_programming/minimum_partition.py) + * [Minimum Squares To Represent A Number](dynamic_programming/minimum_squares_to_represent_a_number.py) * [Minimum Steps To One](dynamic_programming/minimum_steps_to_one.py) * [Optimal Binary Search Tree](dynamic_programming/optimal_binary_search_tree.py) * [Rod Cutting](dynamic_programming/rod_cutting.py) @@ -474,6 +481,7 @@ * [Add](maths/add.py) * [Aliquot Sum](maths/aliquot_sum.py) * [Allocation Number](maths/allocation_number.py) + * [Arc Length](maths/arc_length.py) * [Area](maths/area.py) * [Area Under Curve](maths/area_under_curve.py) * [Armstrong Numbers](maths/armstrong_numbers.py) @@ -609,7 +617,9 @@ ## Matrix * [Binary Search Matrix](matrix/binary_search_matrix.py) * [Count Islands In Matrix](matrix/count_islands_in_matrix.py) + * [Cramers Rule 2X2](matrix/cramers_rule_2x2.py) * [Inverse Of Matrix](matrix/inverse_of_matrix.py) + * [Largest Square Area In Matrix](matrix/largest_square_area_in_matrix.py) * [Matrix Class](matrix/matrix_class.py) * [Matrix Operation](matrix/matrix_operation.py) * [Max Area Of Island](matrix/max_area_of_island.py) @@ -657,6 +667,7 @@ ## Physics * [Casimir Effect](physics/casimir_effect.py) * [Horizontal Projectile Motion](physics/horizontal_projectile_motion.py) + * [Kinetic Energy](physics/kinetic_energy.py) * [Lorentz Transformation Four Vector](physics/lorentz_transformation_four_vector.py) * [N Body Simulation](physics/n_body_simulation.py) * [Newtons Law Of Gravitation](physics/newtons_law_of_gravitation.py) @@ -948,7 +959,6 @@ * [Not Gate](quantum/not_gate.py) * [Q Full Adder](quantum/q_full_adder.py) * [Quantum Entanglement](quantum/quantum_entanglement.py) - * [Quantum Random](quantum/quantum_random.py) * [Ripple Adder Classic](quantum/ripple_adder_classic.py) * [Single Qubit Measure](quantum/single_qubit_measure.py) * [Superdense Coding](quantum/superdense_coding.py) @@ -1048,6 +1058,7 @@ * [Hamming Distance](strings/hamming_distance.py) * [Indian Phone Validator](strings/indian_phone_validator.py) * [Is Contains Unique Chars](strings/is_contains_unique_chars.py) + * [Is Isogram](strings/is_isogram.py) * [Is Palindrome](strings/is_palindrome.py) * [Is Pangram](strings/is_pangram.py) * [Is Spain National Id](strings/is_spain_national_id.py) diff --git a/quantum/quantum_random.py b/quantum/quantum_random.py.DISABLED.txt similarity index 100% rename from quantum/quantum_random.py rename to quantum/quantum_random.py.DISABLED.txt From b46b92a9160360ea09848893b90dd6022f371ffe Mon Sep 17 00:00:00 2001 From: Arjit Arora <42044030+arjitarora26@users.noreply.github.com> Date: Thu, 27 Oct 2022 01:39:23 +0530 Subject: [PATCH 442/726] Add function for highest set bit location (#7586) * Add function for highest set bit location * Address review comments --- bit_manipulation/highest_set_bit.py | 34 +++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 bit_manipulation/highest_set_bit.py diff --git a/bit_manipulation/highest_set_bit.py b/bit_manipulation/highest_set_bit.py new file mode 100644 index 000000000..21d92dcb9 --- /dev/null +++ b/bit_manipulation/highest_set_bit.py @@ -0,0 +1,34 @@ +def get_highest_set_bit_position(number: int) -> int: + """ + Returns position of the highest set bit of a number. + Ref - https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious + >>> get_highest_set_bit_position(25) + 5 + >>> get_highest_set_bit_position(37) + 6 + >>> get_highest_set_bit_position(1) + 1 + >>> get_highest_set_bit_position(4) + 3 + >>> get_highest_set_bit_position(0) + 0 + >>> get_highest_set_bit_position(0.8) + Traceback (most recent call last): + ... + TypeError: Input value must be an 'int' type + """ + if not isinstance(number, int): + raise TypeError("Input value must be an 'int' type") + + position = 0 + while number: + position += 1 + number >>= 1 + + return position + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 71c7c0bd3592225c027d07a10d1c71946c0f677a Mon Sep 17 00:00:00 2001 From: SwayamSahu <91021799+SwayamSahu@users.noreply.github.com> Date: Thu, 27 Oct 2022 01:50:00 +0530 Subject: [PATCH 443/726] Updated a typo in print statement (#7696) * Updated a typo in print statement * Apply suggestions from code review Co-authored-by: Caeden Perelli-Harris Co-authored-by: Christian Clauss Co-authored-by: Caeden Perelli-Harris --- strings/barcode_validator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/strings/barcode_validator.py b/strings/barcode_validator.py index 056700076..2e1ea8703 100644 --- a/strings/barcode_validator.py +++ b/strings/barcode_validator.py @@ -83,6 +83,6 @@ if __name__ == "__main__": barcode = get_barcode(input("Barcode: ").strip()) if is_valid(barcode): - print(f"'{barcode}' is a valid Barcode") + print(f"'{barcode}' is a valid barcode.") else: - print(f"'{barcode}' is NOT is valid Barcode.") + print(f"'{barcode}' is NOT a valid barcode.") From d33f9b31fe96acf5201c39f565015444526a3e38 Mon Sep 17 00:00:00 2001 From: Sushant Srivastav <63559772+sushant4191@users.noreply.github.com> Date: Thu, 27 Oct 2022 02:45:02 +0530 Subject: [PATCH 444/726] Calculate GST Amount (#7694) * Calculate GST Amount The program helps to get the net amount after GST is added to it. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update financial/calculating GST.py Thanks! Co-authored-by: Christian Clauss * Update and rename calculating GST.py to price_plus_tax.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update price_plus_tax.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- financial/price_plus_tax.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 financial/price_plus_tax.py diff --git a/financial/price_plus_tax.py b/financial/price_plus_tax.py new file mode 100644 index 000000000..43876d35e --- /dev/null +++ b/financial/price_plus_tax.py @@ -0,0 +1,18 @@ +""" +Calculate price plus tax of a good or service given its price and a tax rate. +""" + + +def price_plus_tax(price: float, tax_rate: float) -> float: + """ + >>> price_plus_tax(100, 0.25) + 125.0 + >>> price_plus_tax(125.50, 0.05) + 131.775 + """ + return price * (1 + tax_rate) + + +if __name__ == "__main__": + print(f"{price_plus_tax(100, 0.25) = }") + print(f"{price_plus_tax(125.50, 0.05) = }") From e906a5149a0a9c116e1a3dbade6eb6ea659ac68a Mon Sep 17 00:00:00 2001 From: SparshRastogi <75373475+SparshRastogi@users.noreply.github.com> Date: Thu, 27 Oct 2022 16:52:10 +0530 Subject: [PATCH 445/726] Create malus_law.py (#7710) * Create malus_law.py Finding the intensity of light transmitted through a polariser using Malus Law and by taking initial intensity and angle between polariser and axis as input * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update physics/malus_law.py Co-authored-by: Caeden Perelli-Harris * Update physics/malus_law.py Co-authored-by: Caeden Perelli-Harris * Update physics/malus_law.py Co-authored-by: Caeden Perelli-Harris * Update physics/malus_law.py Co-authored-by: Caeden Perelli-Harris * Update malus_law.py Made some changes in the error messages and the docstring testcases * Update malus_law.py Made changes for the passing the precommit * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Caeden Perelli-Harris --- physics/malus_law.py | 80 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 physics/malus_law.py diff --git a/physics/malus_law.py b/physics/malus_law.py new file mode 100644 index 000000000..ae77d45cf --- /dev/null +++ b/physics/malus_law.py @@ -0,0 +1,80 @@ +import math + +""" +Finding the intensity of light transmitted through a polariser using Malus Law +and by taking initial intensity and angle between polariser and axis as input + +Description : Malus's law, which is named after Étienne-Louis Malus, +says that when a perfect polarizer is placed in a polarized +beam of light, the irradiance, I, of the light that passes +through is given by + I=I'cos²θ +where I' is the initial intensity and θ is the angle between the light's +initial polarization direction and the axis of the polarizer. +A beam of unpolarized light can be thought of as containing a +uniform mixture of linear polarizations at all possible angles. +Since the average value of cos²θ is 1/2, the transmission coefficient becomes +I/I' = 1/2 +In practice, some light is lost in the polarizer and the actual transmission +will be somewhat lower than this, around 38% for Polaroid-type polarizers but +considerably higher (>49.9%) for some birefringent prism types. +If two polarizers are placed one after another (the second polarizer is +generally called an analyzer), the mutual angle between their polarizing axes +gives the value of θ in Malus's law. If the two axes are orthogonal, the +polarizers are crossed and in theory no light is transmitted, though again +practically speaking no polarizer is perfect and the transmission is not exactly +zero (for example, crossed Polaroid sheets appear slightly blue in colour because +their extinction ratio is better in the red). If a transparent object is placed +between the crossed polarizers, any polarization effects present in the sample +(such as birefringence) will be shown as an increase in transmission. +This effect is used in polarimetry to measure the optical activity of a sample. +Real polarizers are also not perfect blockers of the polarization orthogonal to +their polarization axis; the ratio of the transmission of the unwanted component +to the wanted component is called the extinction ratio, and varies from around +1:500 for Polaroid to about 1:106 for Glan–Taylor prism polarizers. + +Reference : "https://en.wikipedia.org/wiki/Polarizer#Malus's_law_and_other_properties" +""" + + +def malus_law(initial_intensity: float, angle: float) -> float: + """ + >>> round(malus_law(10,45),2) + 5.0 + >>> round(malus_law(100,60),2) + 25.0 + >>> round(malus_law(50,150),2) + 37.5 + >>> round(malus_law(75,270),2) + 0.0 + >>> round(malus_law(10,-900),2) + Traceback (most recent call last): + ... + ValueError: In Malus Law, the angle is in the range 0-360 degrees + >>> round(malus_law(10,900),2) + Traceback (most recent call last): + ... + ValueError: In Malus Law, the angle is in the range 0-360 degrees + >>> round(malus_law(-100,900),2) + Traceback (most recent call last): + ... + ValueError: The value of intensity cannot be negative + >>> round(malus_law(100,180),2) + 100.0 + >>> round(malus_law(100,360),2) + 100.0 + """ + + if initial_intensity < 0: + raise ValueError("The value of intensity cannot be negative") + # handling of negative values of initial intensity + if angle < 0 or angle > 360: + raise ValueError("In Malus Law, the angle is in the range 0-360 degrees") + # handling of values out of allowed range + return initial_intensity * (math.cos(math.radians(angle)) ** 2) + + +if __name__ == "__main__": + import doctest + + doctest.testmod(name="malus_law") From e8915097c4a632419acc77c1ce08aae3e3c3b864 Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Thu, 27 Oct 2022 14:15:15 +0100 Subject: [PATCH 446/726] refactor: Fix matrix display deprecation (#7729) --- machine_learning/xgboost_classifier.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/machine_learning/xgboost_classifier.py b/machine_learning/xgboost_classifier.py index bb5b48b7a..62a1b331b 100644 --- a/machine_learning/xgboost_classifier.py +++ b/machine_learning/xgboost_classifier.py @@ -2,7 +2,7 @@ import numpy as np from matplotlib import pyplot as plt from sklearn.datasets import load_iris -from sklearn.metrics import plot_confusion_matrix +from sklearn.metrics import ConfusionMatrixDisplay from sklearn.model_selection import train_test_split from xgboost import XGBClassifier @@ -63,7 +63,7 @@ def main() -> None: xgboost_classifier = xgboost(x_train, y_train) # Display the confusion matrix of the classifier with both training and test sets - plot_confusion_matrix( + ConfusionMatrixDisplay.from_estimator( xgboost_classifier, x_test, y_test, From 9bba42eca8c679a32f99984bbb5bb53795f4e71f Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Thu, 27 Oct 2022 18:42:30 +0100 Subject: [PATCH 447/726] refactor: Indent ... for visual purposes (#7744) --- arithmetic_analysis/bisection.py | 4 +-- arithmetic_analysis/intersection.py | 4 +-- .../jacobi_iteration_method.py | 10 +++--- arithmetic_analysis/lu_decomposition.py | 2 +- arithmetic_analysis/newton_method.py | 2 +- arithmetic_analysis/newton_raphson_new.py | 2 +- backtracking/knight_tour.py | 2 +- conversions/binary_to_decimal.py | 6 ++-- conversions/binary_to_hexadecimal.py | 4 +-- conversions/binary_to_octal.py | 4 +-- conversions/decimal_to_any.py | 12 +++---- conversions/decimal_to_binary.py | 4 +-- conversions/decimal_to_binary_recursion.py | 6 ++-- conversions/decimal_to_hexadecimal.py | 4 +-- conversions/hex_to_bin.py | 4 +-- conversions/hexadecimal_to_decimal.py | 6 ++-- conversions/octal_to_decimal.py | 20 ++++++------ conversions/temperature_conversions.py | 32 +++++++++---------- .../binary_tree/binary_search_tree.py | 2 +- .../binary_tree/binary_tree_mirror.py | 4 +-- .../number_of_possible_binary_trees.py | 2 +- .../linked_list/doubly_linked_list.py | 10 +++--- .../linked_list/singly_linked_list.py | 16 +++++----- data_structures/queue/linked_queue.py | 4 +-- .../queue/priority_queue_using_list.py | 2 +- .../stacks/infix_to_postfix_conversion.py | 2 +- .../stacks/stack_with_singly_linked_list.py | 2 +- .../longest_common_substring.py | 2 +- genetic_algorithm/basic_string.py | 6 ++-- linear_algebra/src/lib.py | 4 +-- machine_learning/similarity_search.py | 6 ++-- maths/bisection.py | 2 +- maths/catalan_number.py | 6 ++-- maths/fibonacci.py | 10 +++--- maths/maclaurin_series.py | 16 +++++----- maths/proth_number.py | 6 ++-- maths/sylvester_sequence.py | 4 +-- maths/zellers_congruence.py | 4 +-- neural_network/perceptron.py | 6 ++-- project_euler/problem_004/sol1.py | 2 +- project_euler/problem_010/sol3.py | 6 ++-- searches/interpolation_search.py | 2 +- sorts/bead_sort.py | 4 +-- sorts/msd_radix_sort.py | 4 +-- strings/barcode_validator.py | 4 +-- strings/join.py | 2 +- 46 files changed, 134 insertions(+), 134 deletions(-) diff --git a/arithmetic_analysis/bisection.py b/arithmetic_analysis/bisection.py index 640913a7a..e359cc170 100644 --- a/arithmetic_analysis/bisection.py +++ b/arithmetic_analysis/bisection.py @@ -8,7 +8,7 @@ def bisection(function: Callable[[float], float], a: float, b: float) -> float: 1.0000000149011612 >>> bisection(lambda x: x ** 3 - 1, 2, 1000) Traceback (most recent call last): - ... + ... ValueError: could not find root in given interval. >>> bisection(lambda x: x ** 2 - 4 * x + 3, 0, 2) 1.0 @@ -16,7 +16,7 @@ def bisection(function: Callable[[float], float], a: float, b: float) -> float: 3.0 >>> bisection(lambda x: x ** 2 - 4 * x + 3, 4, 1000) Traceback (most recent call last): - ... + ... ValueError: could not find root in given interval. """ start: float = a diff --git a/arithmetic_analysis/intersection.py b/arithmetic_analysis/intersection.py index 49213dd05..826c0ead0 100644 --- a/arithmetic_analysis/intersection.py +++ b/arithmetic_analysis/intersection.py @@ -10,7 +10,7 @@ def intersection(function: Callable[[float], float], x0: float, x1: float) -> fl 0.9999999999954654 >>> intersection(lambda x: x ** 3 - 1, 5, 5) Traceback (most recent call last): - ... + ... ZeroDivisionError: float division by zero, could not find root >>> intersection(lambda x: x ** 3 - 1, 100, 200) 1.0000000000003888 @@ -24,7 +24,7 @@ def intersection(function: Callable[[float], float], x0: float, x1: float) -> fl 0.0 >>> intersection(math.cos, -math.pi, math.pi) Traceback (most recent call last): - ... + ... ZeroDivisionError: float division by zero, could not find root """ x_n: float = x0 diff --git a/arithmetic_analysis/jacobi_iteration_method.py b/arithmetic_analysis/jacobi_iteration_method.py index 3087309e8..fe506a94a 100644 --- a/arithmetic_analysis/jacobi_iteration_method.py +++ b/arithmetic_analysis/jacobi_iteration_method.py @@ -42,7 +42,7 @@ def jacobi_iteration_method( >>> iterations = 3 >>> jacobi_iteration_method(coefficient, constant, init_val, iterations) Traceback (most recent call last): - ... + ... ValueError: Coefficient matrix dimensions must be nxn but received 2x3 >>> coefficient = np.array([[4, 1, 1], [1, 5, 2], [1, 2, 4]]) @@ -51,7 +51,7 @@ def jacobi_iteration_method( >>> iterations = 3 >>> jacobi_iteration_method(coefficient, constant, init_val, iterations) Traceback (most recent call last): - ... + ... ValueError: Coefficient and constant matrices dimensions must be nxn and nx1 but received 3x3 and 2x1 @@ -61,7 +61,7 @@ def jacobi_iteration_method( >>> iterations = 3 >>> jacobi_iteration_method(coefficient, constant, init_val, iterations) Traceback (most recent call last): - ... + ... ValueError: Number of initial values must be equal to number of rows in coefficient matrix but received 2 and 3 @@ -71,7 +71,7 @@ def jacobi_iteration_method( >>> iterations = 0 >>> jacobi_iteration_method(coefficient, constant, init_val, iterations) Traceback (most recent call last): - ... + ... ValueError: Iterations must be at least 1 """ @@ -138,7 +138,7 @@ def strictly_diagonally_dominant(table: NDArray[float64]) -> bool: >>> table = np.array([[4, 1, 1, 2], [1, 5, 2, -6], [1, 2, 3, -4]]) >>> strictly_diagonally_dominant(table) Traceback (most recent call last): - ... + ... ValueError: Coefficient matrix is not strictly diagonally dominant """ diff --git a/arithmetic_analysis/lu_decomposition.py b/arithmetic_analysis/lu_decomposition.py index 1e98b9066..217719cf4 100644 --- a/arithmetic_analysis/lu_decomposition.py +++ b/arithmetic_analysis/lu_decomposition.py @@ -31,7 +31,7 @@ def lower_upper_decomposition( >>> matrix = np.array([[2, -2, 1], [0, 1, 2]]) >>> lower_upper_decomposition(matrix) Traceback (most recent call last): - ... + ... ValueError: 'table' has to be of square shaped array but got a 2x3 array: [[ 2 -2 1] [ 0 1 2]] diff --git a/arithmetic_analysis/newton_method.py b/arithmetic_analysis/newton_method.py index c4018a0f2..5127bfcaf 100644 --- a/arithmetic_analysis/newton_method.py +++ b/arithmetic_analysis/newton_method.py @@ -28,7 +28,7 @@ def newton( 1.5707963267948966 >>> newton(math.cos, lambda x: -math.sin(x), 0) Traceback (most recent call last): - ... + ... ZeroDivisionError: Could not find root """ prev_guess = float(starting_int) diff --git a/arithmetic_analysis/newton_raphson_new.py b/arithmetic_analysis/newton_raphson_new.py index 19ea4ce21..dd1d7e092 100644 --- a/arithmetic_analysis/newton_raphson_new.py +++ b/arithmetic_analysis/newton_raphson_new.py @@ -32,7 +32,7 @@ def newton_raphson( 1.2186556186174883e-10 >>> newton_raphson('cos(x)', 0) Traceback (most recent call last): - ... + ... ZeroDivisionError: Could not find root """ diff --git a/backtracking/knight_tour.py b/backtracking/knight_tour.py index 6e9b31bd1..bb650ece3 100644 --- a/backtracking/knight_tour.py +++ b/backtracking/knight_tour.py @@ -78,7 +78,7 @@ def open_knight_tour(n: int) -> list[list[int]]: >>> open_knight_tour(2) Traceback (most recent call last): - ... + ... ValueError: Open Kight Tour cannot be performed on a board of size 2 """ diff --git a/conversions/binary_to_decimal.py b/conversions/binary_to_decimal.py index a7625e475..914a9318c 100644 --- a/conversions/binary_to_decimal.py +++ b/conversions/binary_to_decimal.py @@ -12,15 +12,15 @@ def bin_to_decimal(bin_string: str) -> int: 0 >>> bin_to_decimal("a") Traceback (most recent call last): - ... + ... ValueError: Non-binary value was passed to the function >>> bin_to_decimal("") Traceback (most recent call last): - ... + ... ValueError: Empty string was passed to the function >>> bin_to_decimal("39") Traceback (most recent call last): - ... + ... ValueError: Non-binary value was passed to the function """ bin_string = str(bin_string).strip() diff --git a/conversions/binary_to_hexadecimal.py b/conversions/binary_to_hexadecimal.py index 89f7af696..a3855bb70 100644 --- a/conversions/binary_to_hexadecimal.py +++ b/conversions/binary_to_hexadecimal.py @@ -30,11 +30,11 @@ def bin_to_hexadecimal(binary_str: str) -> str: '-0x1d' >>> bin_to_hexadecimal('a') Traceback (most recent call last): - ... + ... ValueError: Non-binary value was passed to the function >>> bin_to_hexadecimal('') Traceback (most recent call last): - ... + ... ValueError: Empty string was passed to the function """ # Sanitising parameter diff --git a/conversions/binary_to_octal.py b/conversions/binary_to_octal.py index 35ede95b1..82f81e062 100644 --- a/conversions/binary_to_octal.py +++ b/conversions/binary_to_octal.py @@ -9,11 +9,11 @@ The function below will convert any binary string to the octal equivalent. >>> bin_to_octal("") Traceback (most recent call last): -... + ... ValueError: Empty string was passed to the function >>> bin_to_octal("a-1") Traceback (most recent call last): -... + ... ValueError: Non-binary value was passed to the function """ diff --git a/conversions/decimal_to_any.py b/conversions/decimal_to_any.py index 908c89e8f..11a2af294 100644 --- a/conversions/decimal_to_any.py +++ b/conversions/decimal_to_any.py @@ -29,32 +29,32 @@ def decimal_to_any(num: int, base: int) -> str: >>> # negatives will error >>> decimal_to_any(-45, 8) # doctest: +ELLIPSIS Traceback (most recent call last): - ... + ... ValueError: parameter must be positive int >>> # floats will error >>> decimal_to_any(34.4, 6) # doctest: +ELLIPSIS Traceback (most recent call last): - ... + ... TypeError: int() can't convert non-string with explicit base >>> # a float base will error >>> decimal_to_any(5, 2.5) # doctest: +ELLIPSIS Traceback (most recent call last): - ... + ... TypeError: 'float' object cannot be interpreted as an integer >>> # a str base will error >>> decimal_to_any(10, '16') # doctest: +ELLIPSIS Traceback (most recent call last): - ... + ... TypeError: 'str' object cannot be interpreted as an integer >>> # a base less than 2 will error >>> decimal_to_any(7, 0) # doctest: +ELLIPSIS Traceback (most recent call last): - ... + ... ValueError: base must be >= 2 >>> # a base greater than 36 will error >>> decimal_to_any(34, 37) # doctest: +ELLIPSIS Traceback (most recent call last): - ... + ... ValueError: base must be <= 36 """ if isinstance(num, float): diff --git a/conversions/decimal_to_binary.py b/conversions/decimal_to_binary.py index c21cdbcae..cfda57ca7 100644 --- a/conversions/decimal_to_binary.py +++ b/conversions/decimal_to_binary.py @@ -19,12 +19,12 @@ def decimal_to_binary(num: int) -> str: >>> # other floats will error >>> decimal_to_binary(16.16) # doctest: +ELLIPSIS Traceback (most recent call last): - ... + ... TypeError: 'float' object cannot be interpreted as an integer >>> # strings will error as well >>> decimal_to_binary('0xfffff') # doctest: +ELLIPSIS Traceback (most recent call last): - ... + ... TypeError: 'str' object cannot be interpreted as an integer """ diff --git a/conversions/decimal_to_binary_recursion.py b/conversions/decimal_to_binary_recursion.py index c149ea865..05833ca67 100644 --- a/conversions/decimal_to_binary_recursion.py +++ b/conversions/decimal_to_binary_recursion.py @@ -7,7 +7,7 @@ def binary_recursive(decimal: int) -> str: '1001000' >>> binary_recursive("number") Traceback (most recent call last): - ... + ... ValueError: invalid literal for int() with base 10: 'number' """ decimal = int(decimal) @@ -30,11 +30,11 @@ def main(number: str) -> str: '-0b101000' >>> main(40.8) Traceback (most recent call last): - ... + ... ValueError: Input value is not an integer >>> main("forty") Traceback (most recent call last): - ... + ... ValueError: Input value is not an integer """ number = str(number).strip() diff --git a/conversions/decimal_to_hexadecimal.py b/conversions/decimal_to_hexadecimal.py index 2389c6d1f..5ea48401f 100644 --- a/conversions/decimal_to_hexadecimal.py +++ b/conversions/decimal_to_hexadecimal.py @@ -46,12 +46,12 @@ def decimal_to_hexadecimal(decimal: float) -> str: >>> # other floats will error >>> decimal_to_hexadecimal(16.16) # doctest: +ELLIPSIS Traceback (most recent call last): - ... + ... AssertionError >>> # strings will error as well >>> decimal_to_hexadecimal('0xfffff') # doctest: +ELLIPSIS Traceback (most recent call last): - ... + ... AssertionError >>> # results are the same when compared to Python's default hex function >>> decimal_to_hexadecimal(-256) == hex(-256) diff --git a/conversions/hex_to_bin.py b/conversions/hex_to_bin.py index e358d810b..b872ab5cb 100644 --- a/conversions/hex_to_bin.py +++ b/conversions/hex_to_bin.py @@ -21,11 +21,11 @@ def hex_to_bin(hex_num: str) -> int: -1111111111111111 >>> hex_to_bin("F-f") Traceback (most recent call last): - ... + ... ValueError: Invalid value was passed to the function >>> hex_to_bin("") Traceback (most recent call last): - ... + ... ValueError: No value was passed to the function """ diff --git a/conversions/hexadecimal_to_decimal.py b/conversions/hexadecimal_to_decimal.py index beb1c2c3d..209e4aebb 100644 --- a/conversions/hexadecimal_to_decimal.py +++ b/conversions/hexadecimal_to_decimal.py @@ -18,15 +18,15 @@ def hex_to_decimal(hex_string: str) -> int: -255 >>> hex_to_decimal("F-f") Traceback (most recent call last): - ... + ... ValueError: Non-hexadecimal value was passed to the function >>> hex_to_decimal("") Traceback (most recent call last): - ... + ... ValueError: Empty string was passed to the function >>> hex_to_decimal("12m") Traceback (most recent call last): - ... + ... ValueError: Non-hexadecimal value was passed to the function """ hex_string = hex_string.strip().lower() diff --git a/conversions/octal_to_decimal.py b/conversions/octal_to_decimal.py index 551311e26..7f006f20e 100644 --- a/conversions/octal_to_decimal.py +++ b/conversions/octal_to_decimal.py @@ -4,27 +4,27 @@ def oct_to_decimal(oct_string: str) -> int: >>> oct_to_decimal("") Traceback (most recent call last): - ... + ... ValueError: Empty string was passed to the function >>> oct_to_decimal("-") Traceback (most recent call last): - ... + ... ValueError: Non-octal value was passed to the function >>> oct_to_decimal("e") Traceback (most recent call last): - ... + ... ValueError: Non-octal value was passed to the function >>> oct_to_decimal("8") Traceback (most recent call last): - ... + ... ValueError: Non-octal value was passed to the function >>> oct_to_decimal("-e") Traceback (most recent call last): - ... + ... ValueError: Non-octal value was passed to the function >>> oct_to_decimal("-8") Traceback (most recent call last): - ... + ... ValueError: Non-octal value was passed to the function >>> oct_to_decimal("1") 1 @@ -38,7 +38,7 @@ def oct_to_decimal(oct_string: str) -> int: -37 >>> oct_to_decimal("-") Traceback (most recent call last): - ... + ... ValueError: Non-octal value was passed to the function >>> oct_to_decimal("0") 0 @@ -46,15 +46,15 @@ def oct_to_decimal(oct_string: str) -> int: -2093 >>> oct_to_decimal("2-0Fm") Traceback (most recent call last): - ... + ... ValueError: Non-octal value was passed to the function >>> oct_to_decimal("") Traceback (most recent call last): - ... + ... ValueError: Empty string was passed to the function >>> oct_to_decimal("19") Traceback (most recent call last): - ... + ... ValueError: Non-octal value was passed to the function """ oct_string = str(oct_string).strip() diff --git a/conversions/temperature_conversions.py b/conversions/temperature_conversions.py index 167c9dc64..e5af46556 100644 --- a/conversions/temperature_conversions.py +++ b/conversions/temperature_conversions.py @@ -23,7 +23,7 @@ def celsius_to_fahrenheit(celsius: float, ndigits: int = 2) -> float: 104.0 >>> celsius_to_fahrenheit("celsius") Traceback (most recent call last): - ... + ... ValueError: could not convert string to float: 'celsius' """ return round((float(celsius) * 9 / 5) + 32, ndigits) @@ -47,7 +47,7 @@ def celsius_to_kelvin(celsius: float, ndigits: int = 2) -> float: 313.15 >>> celsius_to_kelvin("celsius") Traceback (most recent call last): - ... + ... ValueError: could not convert string to float: 'celsius' """ return round(float(celsius) + 273.15, ndigits) @@ -71,7 +71,7 @@ def celsius_to_rankine(celsius: float, ndigits: int = 2) -> float: 563.67 >>> celsius_to_rankine("celsius") Traceback (most recent call last): - ... + ... ValueError: could not convert string to float: 'celsius' """ return round((float(celsius) * 9 / 5) + 491.67, ndigits) @@ -101,7 +101,7 @@ def fahrenheit_to_celsius(fahrenheit: float, ndigits: int = 2) -> float: 37.78 >>> fahrenheit_to_celsius("fahrenheit") Traceback (most recent call last): - ... + ... ValueError: could not convert string to float: 'fahrenheit' """ return round((float(fahrenheit) - 32) * 5 / 9, ndigits) @@ -131,7 +131,7 @@ def fahrenheit_to_kelvin(fahrenheit: float, ndigits: int = 2) -> float: 310.93 >>> fahrenheit_to_kelvin("fahrenheit") Traceback (most recent call last): - ... + ... ValueError: could not convert string to float: 'fahrenheit' """ return round(((float(fahrenheit) - 32) * 5 / 9) + 273.15, ndigits) @@ -161,7 +161,7 @@ def fahrenheit_to_rankine(fahrenheit: float, ndigits: int = 2) -> float: 559.67 >>> fahrenheit_to_rankine("fahrenheit") Traceback (most recent call last): - ... + ... ValueError: could not convert string to float: 'fahrenheit' """ return round(float(fahrenheit) + 459.67, ndigits) @@ -185,7 +185,7 @@ def kelvin_to_celsius(kelvin: float, ndigits: int = 2) -> float: 42.35 >>> kelvin_to_celsius("kelvin") Traceback (most recent call last): - ... + ... ValueError: could not convert string to float: 'kelvin' """ return round(float(kelvin) - 273.15, ndigits) @@ -209,7 +209,7 @@ def kelvin_to_fahrenheit(kelvin: float, ndigits: int = 2) -> float: 108.23 >>> kelvin_to_fahrenheit("kelvin") Traceback (most recent call last): - ... + ... ValueError: could not convert string to float: 'kelvin' """ return round(((float(kelvin) - 273.15) * 9 / 5) + 32, ndigits) @@ -233,7 +233,7 @@ def kelvin_to_rankine(kelvin: float, ndigits: int = 2) -> float: 72.0 >>> kelvin_to_rankine("kelvin") Traceback (most recent call last): - ... + ... ValueError: could not convert string to float: 'kelvin' """ return round((float(kelvin) * 9 / 5), ndigits) @@ -257,7 +257,7 @@ def rankine_to_celsius(rankine: float, ndigits: int = 2) -> float: -97.87 >>> rankine_to_celsius("rankine") Traceback (most recent call last): - ... + ... ValueError: could not convert string to float: 'rankine' """ return round((float(rankine) - 491.67) * 5 / 9, ndigits) @@ -277,7 +277,7 @@ def rankine_to_fahrenheit(rankine: float, ndigits: int = 2) -> float: -144.17 >>> rankine_to_fahrenheit("rankine") Traceback (most recent call last): - ... + ... ValueError: could not convert string to float: 'rankine' """ return round(float(rankine) - 459.67, ndigits) @@ -297,7 +297,7 @@ def rankine_to_kelvin(rankine: float, ndigits: int = 2) -> float: 22.22 >>> rankine_to_kelvin("rankine") Traceback (most recent call last): - ... + ... ValueError: could not convert string to float: 'rankine' """ return round((float(rankine) * 5 / 9), ndigits) @@ -316,7 +316,7 @@ def reaumur_to_kelvin(reaumur: float, ndigits: int = 2) -> float: 323.15 >>> reaumur_to_kelvin("reaumur") Traceback (most recent call last): - ... + ... ValueError: could not convert string to float: 'reaumur' """ return round((float(reaumur) * 1.25 + 273.15), ndigits) @@ -335,7 +335,7 @@ def reaumur_to_fahrenheit(reaumur: float, ndigits: int = 2) -> float: 122.0 >>> reaumur_to_fahrenheit("reaumur") Traceback (most recent call last): - ... + ... ValueError: could not convert string to float: 'reaumur' """ return round((float(reaumur) * 2.25 + 32), ndigits) @@ -354,7 +354,7 @@ def reaumur_to_celsius(reaumur: float, ndigits: int = 2) -> float: 50.0 >>> reaumur_to_celsius("reaumur") Traceback (most recent call last): - ... + ... ValueError: could not convert string to float: 'reaumur' """ return round((float(reaumur) * 1.25), ndigits) @@ -373,7 +373,7 @@ def reaumur_to_rankine(reaumur: float, ndigits: int = 2) -> float: 581.67 >>> reaumur_to_rankine("reaumur") Traceback (most recent call last): - ... + ... ValueError: could not convert string to float: 'reaumur' """ return round((float(reaumur) * 2.25 + 32 + 459.67), ndigits) diff --git a/data_structures/binary_tree/binary_search_tree.py b/data_structures/binary_tree/binary_search_tree.py index fc60540a1..fc512944e 100644 --- a/data_structures/binary_tree/binary_search_tree.py +++ b/data_structures/binary_tree/binary_search_tree.py @@ -196,7 +196,7 @@ def binary_search_tree() -> None: 1 4 7 6 3 13 14 10 8 >>> BinarySearchTree().search(6) Traceback (most recent call last): - ... + ... IndexError: Warning: Tree is empty! please use another. """ testlist = (8, 3, 6, 1, 10, 14, 13, 4, 7) diff --git a/data_structures/binary_tree/binary_tree_mirror.py b/data_structures/binary_tree/binary_tree_mirror.py index cdd56e35d..1ef950ad6 100644 --- a/data_structures/binary_tree/binary_tree_mirror.py +++ b/data_structures/binary_tree/binary_tree_mirror.py @@ -21,11 +21,11 @@ def binary_tree_mirror(binary_tree: dict, root: int = 1) -> dict: {1: [3, 2], 2: [5, 4], 3: [7, 6], 4: [11, 10]} >>> binary_tree_mirror({ 1: [2,3], 2: [4,5], 3: [6,7], 4: [10,11]}, 5) Traceback (most recent call last): - ... + ... ValueError: root 5 is not present in the binary_tree >>> binary_tree_mirror({}, 5) Traceback (most recent call last): - ... + ... ValueError: binary tree cannot be empty """ if not binary_tree: diff --git a/data_structures/binary_tree/number_of_possible_binary_trees.py b/data_structures/binary_tree/number_of_possible_binary_trees.py index 1ad8f2ed4..684c518b1 100644 --- a/data_structures/binary_tree/number_of_possible_binary_trees.py +++ b/data_structures/binary_tree/number_of_possible_binary_trees.py @@ -67,7 +67,7 @@ def factorial(n: int) -> int: True >>> factorial(-5) # doctest: +ELLIPSIS Traceback (most recent call last): - ... + ... ValueError: factorial() not defined for negative values """ if n < 0: diff --git a/data_structures/linked_list/doubly_linked_list.py b/data_structures/linked_list/doubly_linked_list.py index 9e996ef0f..90b6b6eb2 100644 --- a/data_structures/linked_list/doubly_linked_list.py +++ b/data_structures/linked_list/doubly_linked_list.py @@ -64,11 +64,11 @@ class DoublyLinkedList: >>> linked_list = DoublyLinkedList() >>> linked_list.insert_at_nth(-1, 666) Traceback (most recent call last): - .... + .... IndexError: list index out of range >>> linked_list.insert_at_nth(1, 666) Traceback (most recent call last): - .... + .... IndexError: list index out of range >>> linked_list.insert_at_nth(0, 2) >>> linked_list.insert_at_nth(0, 1) @@ -78,7 +78,7 @@ class DoublyLinkedList: '1->2->3->4' >>> linked_list.insert_at_nth(5, 5) Traceback (most recent call last): - .... + .... IndexError: list index out of range """ if not 0 <= index <= len(self): @@ -114,7 +114,7 @@ class DoublyLinkedList: >>> linked_list = DoublyLinkedList() >>> linked_list.delete_at_nth(0) Traceback (most recent call last): - .... + .... IndexError: list index out of range >>> for i in range(0, 5): ... linked_list.insert_at_nth(i, i + 1) @@ -128,7 +128,7 @@ class DoublyLinkedList: '2->4' >>> linked_list.delete_at_nth(2) Traceback (most recent call last): - .... + .... IndexError: list index out of range """ if not 0 <= index <= len(self) - 1: diff --git a/data_structures/linked_list/singly_linked_list.py b/data_structures/linked_list/singly_linked_list.py index 89a05ae81..3e52c7e43 100644 --- a/data_structures/linked_list/singly_linked_list.py +++ b/data_structures/linked_list/singly_linked_list.py @@ -95,11 +95,11 @@ class LinkedList: True >>> linked_list[-10] Traceback (most recent call last): - ... + ... ValueError: list index out of range. >>> linked_list[len(linked_list)] Traceback (most recent call last): - ... + ... ValueError: list index out of range. """ if not 0 <= index < len(self): @@ -122,11 +122,11 @@ class LinkedList: -666 >>> linked_list[-10] = 666 Traceback (most recent call last): - ... + ... ValueError: list index out of range. >>> linked_list[len(linked_list)] = 666 Traceback (most recent call last): - ... + ... ValueError: list index out of range. """ if not 0 <= index < len(self): @@ -233,7 +233,7 @@ class LinkedList: 'third' >>> linked_list.delete_head() Traceback (most recent call last): - ... + ... IndexError: List index out of range. """ return self.delete_nth(0) @@ -260,7 +260,7 @@ class LinkedList: 'first' >>> linked_list.delete_tail() Traceback (most recent call last): - ... + ... IndexError: List index out of range. """ return self.delete_nth(len(self) - 1) @@ -281,11 +281,11 @@ class LinkedList: first->third >>> linked_list.delete_nth(5) # this raises error Traceback (most recent call last): - ... + ... IndexError: List index out of range. >>> linked_list.delete_nth(-1) # this also raises error Traceback (most recent call last): - ... + ... IndexError: List index out of range. """ if not 0 <= index <= len(self) - 1: # test if index is valid diff --git a/data_structures/queue/linked_queue.py b/data_structures/queue/linked_queue.py index 3675da7db..3af97d28e 100644 --- a/data_structures/queue/linked_queue.py +++ b/data_structures/queue/linked_queue.py @@ -96,7 +96,7 @@ class LinkedQueue: >>> queue = LinkedQueue() >>> queue.get() Traceback (most recent call last): - ... + ... IndexError: dequeue from empty queue >>> for i in range(1, 6): ... queue.put(i) @@ -116,7 +116,7 @@ class LinkedQueue: >>> queue = LinkedQueue() >>> queue.get() Traceback (most recent call last): - ... + ... IndexError: dequeue from empty queue >>> queue = LinkedQueue() >>> for i in range(1, 6): diff --git a/data_structures/queue/priority_queue_using_list.py b/data_structures/queue/priority_queue_using_list.py index c5cf26433..f61b5e8e6 100644 --- a/data_structures/queue/priority_queue_using_list.py +++ b/data_structures/queue/priority_queue_using_list.py @@ -58,7 +58,7 @@ class FixedPriorityQueue: 4 >>> fpq.dequeue() Traceback (most recent call last): - ... + ... data_structures.queue.priority_queue_using_list.UnderFlowError: All queues are empty >>> print(fpq) Priority 0: [] diff --git a/data_structures/stacks/infix_to_postfix_conversion.py b/data_structures/stacks/infix_to_postfix_conversion.py index b812d108e..901744309 100644 --- a/data_structures/stacks/infix_to_postfix_conversion.py +++ b/data_structures/stacks/infix_to_postfix_conversion.py @@ -21,7 +21,7 @@ def infix_to_postfix(expression_str: str) -> str: """ >>> infix_to_postfix("(1*(2+3)+4))") Traceback (most recent call last): - ... + ... ValueError: Mismatched parentheses >>> infix_to_postfix("") '' diff --git a/data_structures/stacks/stack_with_singly_linked_list.py b/data_structures/stacks/stack_with_singly_linked_list.py index 903ae39db..f5ce83b86 100644 --- a/data_structures/stacks/stack_with_singly_linked_list.py +++ b/data_structures/stacks/stack_with_singly_linked_list.py @@ -109,7 +109,7 @@ class LinkedStack(Generic[T]): >>> stack = LinkedStack() >>> stack.pop() Traceback (most recent call last): - ... + ... IndexError: pop from empty stack >>> stack.push("c") >>> stack.push("b") diff --git a/dynamic_programming/longest_common_substring.py b/dynamic_programming/longest_common_substring.py index 84a9f1860..e2f944a5e 100644 --- a/dynamic_programming/longest_common_substring.py +++ b/dynamic_programming/longest_common_substring.py @@ -32,7 +32,7 @@ def longest_common_substring(text1: str, text2: str) -> str: 'Site:Geeks' >>> longest_common_substring(1, 1) Traceback (most recent call last): - ... + ... ValueError: longest_common_substring() takes two strings for inputs """ diff --git a/genetic_algorithm/basic_string.py b/genetic_algorithm/basic_string.py index 3227adf53..5cf8d691b 100644 --- a/genetic_algorithm/basic_string.py +++ b/genetic_algorithm/basic_string.py @@ -32,17 +32,17 @@ def basic(target: str, genes: list[str], debug: bool = True) -> tuple[int, int, >>> genes.remove("e") >>> basic("test", genes) Traceback (most recent call last): - ... + ... ValueError: ['e'] is not in genes list, evolution cannot converge >>> genes.remove("s") >>> basic("test", genes) Traceback (most recent call last): - ... + ... ValueError: ['e', 's'] is not in genes list, evolution cannot converge >>> genes.remove("t") >>> basic("test", genes) Traceback (most recent call last): - ... + ... ValueError: ['e', 's', 't'] is not in genes list, evolution cannot converge """ diff --git a/linear_algebra/src/lib.py b/linear_algebra/src/lib.py index b9791c860..079731487 100644 --- a/linear_algebra/src/lib.py +++ b/linear_algebra/src/lib.py @@ -168,7 +168,7 @@ class Vector: 9.539392014169456 >>> Vector([]).euclidean_length() Traceback (most recent call last): - ... + ... Exception: Vector is empty """ if len(self.__components) == 0: @@ -186,7 +186,7 @@ class Vector: 85.40775111366095 >>> Vector([3, 4, -1]).angle(Vector([2, -1])) Traceback (most recent call last): - ... + ... Exception: invalid operand! """ num = self * other diff --git a/machine_learning/similarity_search.py b/machine_learning/similarity_search.py index ec1b9f9e3..2f5fc46c0 100644 --- a/machine_learning/similarity_search.py +++ b/machine_learning/similarity_search.py @@ -70,7 +70,7 @@ def similarity_search( >>> value_array = np.array([1]) >>> similarity_search(dataset, value_array) Traceback (most recent call last): - ... + ... ValueError: Wrong input data's dimensions... dataset : 2, value_array : 1 2. If data's shapes are different. @@ -80,7 +80,7 @@ def similarity_search( >>> value_array = np.array([[0, 0, 0], [0, 0, 1]]) >>> similarity_search(dataset, value_array) Traceback (most recent call last): - ... + ... ValueError: Wrong input data's shape... dataset : 2, value_array : 3 3. If data types are different. @@ -90,7 +90,7 @@ def similarity_search( >>> value_array = np.array([[0, 0], [0, 1]], dtype=np.int32) >>> similarity_search(dataset, value_array) # doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): - ... + ... TypeError: Input data have different datatype... dataset : float32, value_array : int32 """ diff --git a/maths/bisection.py b/maths/bisection.py index 93cc2247b..45f26d8d8 100644 --- a/maths/bisection.py +++ b/maths/bisection.py @@ -32,7 +32,7 @@ def bisection(a: float, b: float) -> float: 3.158203125 >>> bisection(2, 3) Traceback (most recent call last): - ... + ... ValueError: Wrong space! """ # Bolzano theory in order to find if there is a root between a and b diff --git a/maths/catalan_number.py b/maths/catalan_number.py index 4a1280a45..85607dc1e 100644 --- a/maths/catalan_number.py +++ b/maths/catalan_number.py @@ -18,15 +18,15 @@ def catalan(number: int) -> int: 14 >>> catalan(0) Traceback (most recent call last): - ... + ... ValueError: Input value of [number=0] must be > 0 >>> catalan(-1) Traceback (most recent call last): - ... + ... ValueError: Input value of [number=-1] must be > 0 >>> catalan(5.0) Traceback (most recent call last): - ... + ... TypeError: Input value of [number=5.0] must be an integer """ diff --git a/maths/fibonacci.py b/maths/fibonacci.py index 07bd6d2ec..e0da66ee5 100644 --- a/maths/fibonacci.py +++ b/maths/fibonacci.py @@ -47,7 +47,7 @@ def fib_iterative(n: int) -> list[int]: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55] >>> fib_iterative(-1) Traceback (most recent call last): - ... + ... Exception: n is negative """ if n < 0: @@ -73,7 +73,7 @@ def fib_recursive(n: int) -> list[int]: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55] >>> fib_iterative(-1) Traceback (most recent call last): - ... + ... Exception: n is negative """ @@ -105,7 +105,7 @@ def fib_memoization(n: int) -> list[int]: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55] >>> fib_iterative(-1) Traceback (most recent call last): - ... + ... Exception: n is negative """ if n < 0: @@ -146,11 +146,11 @@ def fib_binet(n: int) -> list[int]: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55] >>> fib_binet(-1) Traceback (most recent call last): - ... + ... Exception: n is negative >>> fib_binet(1475) Traceback (most recent call last): - ... + ... Exception: n is too large """ if n < 0: diff --git a/maths/maclaurin_series.py b/maths/maclaurin_series.py index a2619d4e6..e55839bc1 100644 --- a/maths/maclaurin_series.py +++ b/maths/maclaurin_series.py @@ -26,19 +26,19 @@ def maclaurin_sin(theta: float, accuracy: int = 30) -> float: 0.5440211108893703 >>> maclaurin_sin("10") Traceback (most recent call last): - ... + ... ValueError: maclaurin_sin() requires either an int or float for theta >>> maclaurin_sin(10, -30) Traceback (most recent call last): - ... + ... ValueError: maclaurin_sin() requires a positive int for accuracy >>> maclaurin_sin(10, 30.5) Traceback (most recent call last): - ... + ... ValueError: maclaurin_sin() requires a positive int for accuracy >>> maclaurin_sin(10, "30") Traceback (most recent call last): - ... + ... ValueError: maclaurin_sin() requires a positive int for accuracy """ @@ -78,19 +78,19 @@ def maclaurin_cos(theta: float, accuracy: int = 30) -> float: -0.8390715290764521 >>> maclaurin_cos("10") Traceback (most recent call last): - ... + ... ValueError: maclaurin_cos() requires either an int or float for theta >>> maclaurin_cos(10, -30) Traceback (most recent call last): - ... + ... ValueError: maclaurin_cos() requires a positive int for accuracy >>> maclaurin_cos(10, 30.5) Traceback (most recent call last): - ... + ... ValueError: maclaurin_cos() requires a positive int for accuracy >>> maclaurin_cos(10, "30") Traceback (most recent call last): - ... + ... ValueError: maclaurin_cos() requires a positive int for accuracy """ diff --git a/maths/proth_number.py b/maths/proth_number.py index 6b1519024..ce911473a 100644 --- a/maths/proth_number.py +++ b/maths/proth_number.py @@ -16,15 +16,15 @@ def proth(number: int) -> int: 25 >>> proth(0) Traceback (most recent call last): - ... + ... ValueError: Input value of [number=0] must be > 0 >>> proth(-1) Traceback (most recent call last): - ... + ... ValueError: Input value of [number=-1] must be > 0 >>> proth(6.0) Traceback (most recent call last): - ... + ... TypeError: Input value of [number=6.0] must be an integer """ diff --git a/maths/sylvester_sequence.py b/maths/sylvester_sequence.py index 0cd99affe..114c9dd58 100644 --- a/maths/sylvester_sequence.py +++ b/maths/sylvester_sequence.py @@ -18,12 +18,12 @@ def sylvester(number: int) -> int: >>> sylvester(-1) Traceback (most recent call last): - ... + ... ValueError: The input value of [n=-1] has to be > 0 >>> sylvester(8.0) Traceback (most recent call last): - ... + ... AssertionError: The input value of [n=8.0] is not an integer """ assert isinstance(number, int), f"The input value of [n={number}] is not an integer" diff --git a/maths/zellers_congruence.py b/maths/zellers_congruence.py index 2d4a22a0a..624bbfe10 100644 --- a/maths/zellers_congruence.py +++ b/maths/zellers_congruence.py @@ -14,11 +14,11 @@ def zeller(date_input: str) -> str: Validate out of range month >>> zeller('13-31-2010') Traceback (most recent call last): - ... + ... ValueError: Month must be between 1 - 12 >>> zeller('.2-31-2010') Traceback (most recent call last): - ... + ... ValueError: invalid literal for int() with base 10: '.2' Validate out of range date: diff --git a/neural_network/perceptron.py b/neural_network/perceptron.py index f04c81424..487842067 100644 --- a/neural_network/perceptron.py +++ b/neural_network/perceptron.py @@ -29,15 +29,15 @@ class Perceptron: >>> p = Perceptron([], (0, 1, 2)) Traceback (most recent call last): - ... + ... ValueError: Sample data can not be empty >>> p = Perceptron(([0], 1, 2), []) Traceback (most recent call last): - ... + ... ValueError: Target data can not be empty >>> p = Perceptron(([0], 1, 2), (0, 1)) Traceback (most recent call last): - ... + ... ValueError: Sample data and Target data do not have matching lengths """ self.sample = sample diff --git a/project_euler/problem_004/sol1.py b/project_euler/problem_004/sol1.py index db6133a1a..b1e229289 100644 --- a/project_euler/problem_004/sol1.py +++ b/project_euler/problem_004/sol1.py @@ -26,7 +26,7 @@ def solution(n: int = 998001) -> int: 39893 >>> solution(10000) Traceback (most recent call last): - ... + ... ValueError: That number is larger than our acceptable range. """ diff --git a/project_euler/problem_010/sol3.py b/project_euler/problem_010/sol3.py index 72e2894df..60abbd571 100644 --- a/project_euler/problem_010/sol3.py +++ b/project_euler/problem_010/sol3.py @@ -30,15 +30,15 @@ def solution(n: int = 2000000) -> int: 10 >>> solution(7.1) # doctest: +ELLIPSIS Traceback (most recent call last): - ... + ... TypeError: 'float' object cannot be interpreted as an integer >>> solution(-7) # doctest: +ELLIPSIS Traceback (most recent call last): - ... + ... IndexError: list assignment index out of range >>> solution("seven") # doctest: +ELLIPSIS Traceback (most recent call last): - ... + ... TypeError: can only concatenate str (not "int") to str """ diff --git a/searches/interpolation_search.py b/searches/interpolation_search.py index f4fa8e120..35e6bc506 100644 --- a/searches/interpolation_search.py +++ b/searches/interpolation_search.py @@ -101,7 +101,7 @@ def __assert_sorted(collection): True >>> __assert_sorted([10, -1, 5]) Traceback (most recent call last): - ... + ... ValueError: Collection must be ascending sorted """ if collection != sorted(collection): diff --git a/sorts/bead_sort.py b/sorts/bead_sort.py index d22367c52..e51173643 100644 --- a/sorts/bead_sort.py +++ b/sorts/bead_sort.py @@ -20,12 +20,12 @@ def bead_sort(sequence: list) -> list: >>> bead_sort([1, .9, 0.0, 0, -1, -.9]) Traceback (most recent call last): - ... + ... TypeError: Sequence must be list of non-negative integers >>> bead_sort("Hello world") Traceback (most recent call last): - ... + ... TypeError: Sequence must be list of non-negative integers """ if any(not isinstance(x, int) or x < 0 for x in sequence): diff --git a/sorts/msd_radix_sort.py b/sorts/msd_radix_sort.py index 7430fc5a6..84460e47b 100644 --- a/sorts/msd_radix_sort.py +++ b/sorts/msd_radix_sort.py @@ -23,7 +23,7 @@ def msd_radix_sort(list_of_ints: list[int]) -> list[int]: [1, 45, 1209, 540402, 834598] >>> msd_radix_sort([-1, 34, 45]) Traceback (most recent call last): - ... + ... ValueError: All numbers must be positive """ if not list_of_ints: @@ -93,7 +93,7 @@ def msd_radix_sort_inplace(list_of_ints: list[int]): >>> lst = [-1, 34, 23, 4, -42] >>> msd_radix_sort_inplace(lst) Traceback (most recent call last): - ... + ... ValueError: All numbers must be positive """ diff --git a/strings/barcode_validator.py b/strings/barcode_validator.py index 2e1ea8703..e050cd337 100644 --- a/strings/barcode_validator.py +++ b/strings/barcode_validator.py @@ -47,7 +47,7 @@ def is_valid(barcode: int) -> bool: False >>> is_valid(dwefgiweuf) Traceback (most recent call last): - ... + ... NameError: name 'dwefgiweuf' is not defined """ return len(str(barcode)) == 13 and get_check_digit(barcode) == barcode % 10 @@ -61,7 +61,7 @@ def get_barcode(barcode: str) -> int: 8718452538119 >>> get_barcode("dwefgiweuf") Traceback (most recent call last): - ... + ... ValueError: Barcode 'dwefgiweuf' has alphabetic characters. """ if str(barcode).isalpha(): diff --git a/strings/join.py b/strings/join.py index c17ddd144..739856c1a 100644 --- a/strings/join.py +++ b/strings/join.py @@ -15,7 +15,7 @@ def join(separator: str, separated: list[str]) -> str: 'You are amazing!' >>> join("#", ["a", "b", "c", 1]) Traceback (most recent call last): - ... + ... Exception: join() accepts only strings to be joined """ joined = "" From 71e8ed81aeb24820a03b968633884ac10b047ad4 Mon Sep 17 00:00:00 2001 From: Matteo Messmer <40521259+matteomessmer@users.noreply.github.com> Date: Thu, 27 Oct 2022 19:45:58 +0200 Subject: [PATCH 448/726] Added spheres union (#6879) * Spheres union * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update volume.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update volume.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * f-strings * Update maths/volume.py Co-authored-by: Christian Clauss * more tests * fix non negative * fix 0 radius * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix tests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix tests * fix print * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix comment * fix comment * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update volume.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- maths/volume.py | 52 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/maths/volume.py b/maths/volume.py index a594e1b90..da4054646 100644 --- a/maths/volume.py +++ b/maths/volume.py @@ -108,6 +108,51 @@ def vol_spheres_intersect( return vol_spherical_cap(h1, radius_2) + vol_spherical_cap(h2, radius_1) +def vol_spheres_union( + radius_1: float, radius_2: float, centers_distance: float +) -> float: + """ + Calculate the volume of the union of two spheres that possibly intersect. + It is the sum of sphere A and sphere B minus their intersection. + First, it calculates the volumes (v1, v2) of the spheres, + then the volume of the intersection (i) and it returns the sum v1+v2-i. + If centers_distance is 0 then it returns the volume of the larger sphere + :return vol_sphere(radius_1) + vol_sphere(radius_2) + - vol_spheres_intersect(radius_1, radius_2, centers_distance) + + >>> vol_spheres_union(2, 2, 1) + 45.814892864851146 + >>> vol_spheres_union(1.56, 2.2, 1.4) + 48.77802773671288 + >>> vol_spheres_union(0, 2, 1) + Traceback (most recent call last): + ... + ValueError: vol_spheres_union() only accepts non-negative values, non-zero radius + >>> vol_spheres_union('1.56', '2.2', '1.4') + Traceback (most recent call last): + ... + TypeError: '<=' not supported between instances of 'str' and 'int' + >>> vol_spheres_union(1, None, 1) + Traceback (most recent call last): + ... + TypeError: '<=' not supported between instances of 'NoneType' and 'int' + """ + + if radius_1 <= 0 or radius_2 <= 0 or centers_distance < 0: + raise ValueError( + "vol_spheres_union() only accepts non-negative values, non-zero radius" + ) + + if centers_distance == 0: + return vol_sphere(max(radius_1, radius_2)) + + return ( + vol_sphere(radius_1) + + vol_sphere(radius_2) + - vol_spheres_intersect(radius_1, radius_2, centers_distance) + ) + + def vol_cuboid(width: float, height: float, length: float) -> float: """ Calculate the Volume of a Cuboid. @@ -408,12 +453,13 @@ def main(): print(f"Sphere: {vol_sphere(2) = }") # ~= 33.5 print(f"Hemisphere: {vol_hemisphere(2) = }") # ~= 16.75 print(f"Circular Cylinder: {vol_circular_cylinder(2, 2) = }") # ~= 25.1 - print( - f"Hollow Circular Cylinder: {vol_hollow_circular_cylinder(1, 2, 3) = }" - ) # ~= 28.3 print(f"Conical Frustum: {vol_conical_frustum(2, 2, 4) = }") # ~= 58.6 print(f"Spherical cap: {vol_spherical_cap(1, 2) = }") # ~= 5.24 print(f"Spheres intersetion: {vol_spheres_intersect(2, 2, 1) = }") # ~= 21.21 + print(f"Spheres union: {vol_spheres_union(2, 2, 1) = }") # ~= 45.81 + print( + f"Hollow Circular Cylinder: {vol_hollow_circular_cylinder(1, 2, 3) = }" + ) # ~= 28.3 if __name__ == "__main__": From 501a1cf0c7b31773fb02bc2966f5c1db99311b36 Mon Sep 17 00:00:00 2001 From: Alexandre Velloso <4320811+AlexandreVelloso@users.noreply.github.com> Date: Thu, 27 Oct 2022 21:51:14 +0100 Subject: [PATCH 449/726] Remove unnecessary else statement (#7759) * Remove unnecessary else statement * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/karatsuba.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/maths/karatsuba.py b/maths/karatsuba.py index b772c0d77..4bf4aecdc 100644 --- a/maths/karatsuba.py +++ b/maths/karatsuba.py @@ -10,18 +10,18 @@ def karatsuba(a, b): """ if len(str(a)) == 1 or len(str(b)) == 1: return a * b - else: - m1 = max(len(str(a)), len(str(b))) - m2 = m1 // 2 - a1, a2 = divmod(a, 10**m2) - b1, b2 = divmod(b, 10**m2) + m1 = max(len(str(a)), len(str(b))) + m2 = m1 // 2 - x = karatsuba(a2, b2) - y = karatsuba((a1 + a2), (b1 + b2)) - z = karatsuba(a1, b1) + a1, a2 = divmod(a, 10**m2) + b1, b2 = divmod(b, 10**m2) - return (z * 10 ** (2 * m2)) + ((y - z - x) * 10 ** (m2)) + (x) + x = karatsuba(a2, b2) + y = karatsuba((a1 + a2), (b1 + b2)) + z = karatsuba(a1, b1) + + return (z * 10 ** (2 * m2)) + ((y - z - x) * 10 ** (m2)) + (x) def main(): From 61eedc16c392823e46ef37cc2a86864fa15e89fe Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Thu, 27 Oct 2022 21:52:00 +0100 Subject: [PATCH 450/726] Remove useless code in doctests (#7733) * refactor: Fix matrix display deprecation * refactor: Remove useless `print` and `pass` statements * revert: Replace broken doctests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * revert: Fix failing doctests * chore: Satisfy pre-commit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- backtracking/hamiltonian_cycle.py | 4 ++-- computer_vision/flip_augmentation.py | 3 --- computer_vision/mosaic_augmentation.py | 3 --- data_structures/heap/binomial_heap.py | 4 ++-- data_structures/heap/heap.py | 8 ++++---- data_structures/heap/min_heap.py | 2 +- data_structures/linked_list/skip_list.py | 3 +++ graphs/gale_shapley_bigraph.py | 2 +- graphs/graph_list.py | 6 +++--- graphs/minimum_spanning_tree_prims2.py | 8 ++++---- graphs/random_graph_generator.py | 2 +- .../local_weighted_learning.py | 2 -- maths/polynomial_evaluation.py | 2 +- maths/radix2_fft.py | 2 +- matrix/matrix_class.py | 6 +++--- searches/simple_binary_search.py | 20 +++++++++---------- sorts/bitonic_sort.py | 12 +++++------ sorts/normal_distribution_quick_sort.md | 4 ++-- sorts/recursive_insertion_sort.py | 12 +++++------ web_programming/reddit.py | 2 -- web_programming/search_books_by_isbn.py | 5 +---- 21 files changed, 51 insertions(+), 61 deletions(-) diff --git a/backtracking/hamiltonian_cycle.py b/backtracking/hamiltonian_cycle.py index 4c6ae4679..4a4156d70 100644 --- a/backtracking/hamiltonian_cycle.py +++ b/backtracking/hamiltonian_cycle.py @@ -71,7 +71,7 @@ def util_hamilton_cycle(graph: list[list[int]], path: list[int], curr_ind: int) >>> curr_ind = 1 >>> util_hamilton_cycle(graph, path, curr_ind) True - >>> print(path) + >>> path [0, 1, 2, 4, 3, 0] Case 2: Use exact graph as in previous case, but in the properties taken from @@ -85,7 +85,7 @@ def util_hamilton_cycle(graph: list[list[int]], path: list[int], curr_ind: int) >>> curr_ind = 3 >>> util_hamilton_cycle(graph, path, curr_ind) True - >>> print(path) + >>> path [0, 1, 2, 4, 3, 0] """ diff --git a/computer_vision/flip_augmentation.py b/computer_vision/flip_augmentation.py index 1272357fd..93b4e3f6d 100644 --- a/computer_vision/flip_augmentation.py +++ b/computer_vision/flip_augmentation.py @@ -22,7 +22,6 @@ def main() -> None: Get images list and annotations list from input dir. Update new images and annotations. Save images and annotations in output dir. - >>> pass # A doctest is not possible for this function. """ img_paths, annos = get_dataset(LABEL_DIR, IMAGE_DIR) print("Processing...") @@ -48,7 +47,6 @@ def get_dataset(label_dir: str, img_dir: str) -> tuple[list, list]: - label_dir : Path to label include annotation of images - img_dir : Path to folder contain images Return : List of images path and labels - >>> pass # A doctest is not possible for this function. """ img_paths = [] labels = [] @@ -88,7 +86,6 @@ def update_image_and_anno( - new_imgs_list : image after resize - new_annos_lists : list of new annotation after scale - path_list : list the name of image file - >>> pass # A doctest is not possible for this function. """ new_annos_lists = [] path_list = [] diff --git a/computer_vision/mosaic_augmentation.py b/computer_vision/mosaic_augmentation.py index 4fd81957c..e29537497 100644 --- a/computer_vision/mosaic_augmentation.py +++ b/computer_vision/mosaic_augmentation.py @@ -23,7 +23,6 @@ def main() -> None: Get images list and annotations list from input dir. Update new images and annotations. Save images and annotations in output dir. - >>> pass # A doctest is not possible for this function. """ img_paths, annos = get_dataset(LABEL_DIR, IMG_DIR) for index in range(NUMBER_IMAGES): @@ -60,7 +59,6 @@ def get_dataset(label_dir: str, img_dir: str) -> tuple[list, list]: - label_dir : Path to label include annotation of images - img_dir : Path to folder contain images Return : List of images path and labels - >>> pass # A doctest is not possible for this function. """ img_paths = [] labels = [] @@ -105,7 +103,6 @@ def update_image_and_anno( - output_img : image after resize - new_anno : list of new annotation after scale - path[0] : get the name of image file - >>> pass # A doctest is not possible for this function. """ output_img = np.zeros([output_size[0], output_size[1], 3], dtype=np.uint8) scale_x = scale_range[0] + random.random() * (scale_range[1] - scale_range[0]) diff --git a/data_structures/heap/binomial_heap.py b/data_structures/heap/binomial_heap.py index 334b444ea..6398c9943 100644 --- a/data_structures/heap/binomial_heap.py +++ b/data_structures/heap/binomial_heap.py @@ -71,7 +71,7 @@ class BinomialHeap: ... first_heap.insert(number) Size test - >>> print(first_heap.size) + >>> first_heap.size 30 Deleting - delete() test @@ -97,7 +97,7 @@ class BinomialHeap: # # # # preOrder() test - >>> print(second_heap.preOrder()) + >>> second_heap.preOrder() [(17, 0), ('#', 1), (31, 1), (20, 2), ('#', 3), ('#', 3), (34, 2), ('#', 3), ('#', 3)] printing Heap - __str__() test diff --git a/data_structures/heap/heap.py b/data_structures/heap/heap.py index 4c19747ec..071790d18 100644 --- a/data_structures/heap/heap.py +++ b/data_structures/heap/heap.py @@ -9,20 +9,20 @@ class Heap: >>> unsorted = [103, 9, 1, 7, 11, 15, 25, 201, 209, 107, 5] >>> h = Heap() >>> h.build_max_heap(unsorted) - >>> print(h) + >>> h [209, 201, 25, 103, 107, 15, 1, 9, 7, 11, 5] >>> >>> h.extract_max() 209 - >>> print(h) + >>> h [201, 107, 25, 103, 11, 15, 1, 9, 7, 5] >>> >>> h.insert(100) - >>> print(h) + >>> h [201, 107, 25, 103, 100, 15, 1, 9, 7, 5, 11] >>> >>> h.heap_sort() - >>> print(h) + >>> h [1, 5, 7, 9, 11, 15, 25, 100, 103, 107, 201] """ diff --git a/data_structures/heap/min_heap.py b/data_structures/heap/min_heap.py index d8975eb2d..0403624f2 100644 --- a/data_structures/heap/min_heap.py +++ b/data_structures/heap/min_heap.py @@ -27,7 +27,7 @@ class MinHeap: >>> myMinHeap.decrease_key(b, -17) >>> print(b) Node(B, -17) - >>> print(myMinHeap["B"]) + >>> myMinHeap["B"] -17 """ diff --git a/data_structures/linked_list/skip_list.py b/data_structures/linked_list/skip_list.py index a667e3e9b..96b0db7c8 100644 --- a/data_structures/linked_list/skip_list.py +++ b/data_structures/linked_list/skip_list.py @@ -443,4 +443,7 @@ def main(): if __name__ == "__main__": + import doctest + + doctest.testmod() main() diff --git a/graphs/gale_shapley_bigraph.py b/graphs/gale_shapley_bigraph.py index 56b8c6c77..f4b315381 100644 --- a/graphs/gale_shapley_bigraph.py +++ b/graphs/gale_shapley_bigraph.py @@ -17,7 +17,7 @@ def stable_matching( >>> donor_pref = [[0, 1, 3, 2], [0, 2, 3, 1], [1, 0, 2, 3], [0, 3, 1, 2]] >>> recipient_pref = [[3, 1, 2, 0], [3, 1, 0, 2], [0, 3, 1, 2], [1, 0, 3, 2]] - >>> print(stable_matching(donor_pref, recipient_pref)) + >>> stable_matching(donor_pref, recipient_pref) [1, 2, 3, 0] """ assert len(donor_pref) == len(recipient_pref) diff --git a/graphs/graph_list.py b/graphs/graph_list.py index f04b7a923..e871f3b8a 100644 --- a/graphs/graph_list.py +++ b/graphs/graph_list.py @@ -18,7 +18,7 @@ class GraphAdjacencyList(Generic[T]): Directed graph example: >>> d_graph = GraphAdjacencyList() - >>> d_graph + >>> print(d_graph) {} >>> d_graph.add_edge(0, 1) {0: [1], 1: []} @@ -26,7 +26,7 @@ class GraphAdjacencyList(Generic[T]): {0: [1], 1: [2, 4, 5], 2: [], 4: [], 5: []} >>> d_graph.add_edge(2, 0).add_edge(2, 6).add_edge(2, 7) {0: [1], 1: [2, 4, 5], 2: [0, 6, 7], 4: [], 5: [], 6: [], 7: []} - >>> print(d_graph) + >>> d_graph {0: [1], 1: [2, 4, 5], 2: [0, 6, 7], 4: [], 5: [], 6: [], 7: []} >>> print(repr(d_graph)) {0: [1], 1: [2, 4, 5], 2: [0, 6, 7], 4: [], 5: [], 6: [], 7: []} @@ -68,7 +68,7 @@ class GraphAdjacencyList(Generic[T]): {'a': ['b'], 'b': ['a']} >>> char_graph.add_edge('b', 'c').add_edge('b', 'e').add_edge('b', 'f') {'a': ['b'], 'b': ['a', 'c', 'e', 'f'], 'c': ['b'], 'e': ['b'], 'f': ['b']} - >>> print(char_graph) + >>> char_graph {'a': ['b'], 'b': ['a', 'c', 'e', 'f'], 'c': ['b'], 'e': ['b'], 'f': ['b']} """ diff --git a/graphs/minimum_spanning_tree_prims2.py b/graphs/minimum_spanning_tree_prims2.py index d924ee3db..707be783d 100644 --- a/graphs/minimum_spanning_tree_prims2.py +++ b/graphs/minimum_spanning_tree_prims2.py @@ -69,16 +69,16 @@ class MinPriorityQueue(Generic[T]): >>> queue.push(3, 4000) >>> queue.push(4, 3000) - >>> print(queue.extract_min()) + >>> queue.extract_min() 2 >>> queue.update_key(4, 50) - >>> print(queue.extract_min()) + >>> queue.extract_min() 4 - >>> print(queue.extract_min()) + >>> queue.extract_min() 1 - >>> print(queue.extract_min()) + >>> queue.extract_min() 3 """ diff --git a/graphs/random_graph_generator.py b/graphs/random_graph_generator.py index 15ccee5b3..0e7e18bc8 100644 --- a/graphs/random_graph_generator.py +++ b/graphs/random_graph_generator.py @@ -53,7 +53,7 @@ def complete_graph(vertices_number: int) -> dict: @input: vertices_number (number of vertices), directed (False if the graph is undirected, True otherwise) @example: - >>> print(complete_graph(3)) + >>> complete_graph(3) {0: [1, 2], 1: [0, 2], 2: [0, 1]} """ return { diff --git a/machine_learning/local_weighted_learning/local_weighted_learning.py b/machine_learning/local_weighted_learning/local_weighted_learning.py index 6c542ab82..df03fe0a1 100644 --- a/machine_learning/local_weighted_learning/local_weighted_learning.py +++ b/machine_learning/local_weighted_learning/local_weighted_learning.py @@ -71,7 +71,6 @@ def local_weight_regression( def load_data(dataset_name: str, cola_name: str, colb_name: str) -> np.mat: """ Function used for loading data from the seaborn splitting into x and y points - >>> pass # this function has no doctest """ import seaborn as sns @@ -112,7 +111,6 @@ def plot_preds( ) -> plt.plot: """ This function used to plot predictions and display the graph - >>> pass #this function has no doctest """ xsort = training_data_x.copy() xsort.sort(axis=0) diff --git a/maths/polynomial_evaluation.py b/maths/polynomial_evaluation.py index 8ee82467e..90a51f521 100644 --- a/maths/polynomial_evaluation.py +++ b/maths/polynomial_evaluation.py @@ -45,7 +45,7 @@ if __name__ == "__main__": >>> poly = (0.0, 0.0, 5.0, 9.3, 7.0) # f(x) = 7.0x^4 + 9.3x^3 + 5.0x^2 >>> x = -13.0 >>> # f(-13) = 7.0(-13)^4 + 9.3(-13)^3 + 5.0(-13)^2 = 180339.9 - >>> print(evaluate_poly(poly, x)) + >>> evaluate_poly(poly, x) 180339.9 """ poly = (0.0, 0.0, 5.0, 9.3, 7.0) diff --git a/maths/radix2_fft.py b/maths/radix2_fft.py index 52442134d..1def58e1f 100644 --- a/maths/radix2_fft.py +++ b/maths/radix2_fft.py @@ -39,7 +39,7 @@ class FFT: >>> x = FFT(A, B) Print product - >>> print(x.product) # 2x + 3x^2 + 8x^3 + 4x^4 + 6x^5 + >>> x.product # 2x + 3x^2 + 8x^3 + 4x^4 + 6x^5 [(-0+0j), (2+0j), (3+0j), (8+0j), (6+0j), (8+0j)] __str__ test diff --git a/matrix/matrix_class.py b/matrix/matrix_class.py index 8b6fefa21..0c3078fe6 100644 --- a/matrix/matrix_class.py +++ b/matrix/matrix_class.py @@ -21,9 +21,9 @@ class Matrix: [7. 8. 9.]] Matrix rows and columns are available as 2D arrays - >>> print(matrix.rows) + >>> matrix.rows [[1, 2, 3], [4, 5, 6], [7, 8, 9]] - >>> print(matrix.columns()) + >>> matrix.columns() [[1, 4, 7], [2, 5, 8], [3, 6, 9]] Order is returned as a tuple @@ -55,7 +55,7 @@ class Matrix: [[-3. 6. -3.] [6. -12. 6.] [-3. 6. -3.]] - >>> print(matrix.inverse()) + >>> matrix.inverse() Traceback (most recent call last): ... TypeError: Only matrices with a non-zero determinant have an inverse diff --git a/searches/simple_binary_search.py b/searches/simple_binary_search.py index d1f7f7a51..ff043d736 100644 --- a/searches/simple_binary_search.py +++ b/searches/simple_binary_search.py @@ -13,25 +13,25 @@ from __future__ import annotations def binary_search(a_list: list[int], item: int) -> bool: """ >>> test_list = [0, 1, 2, 8, 13, 17, 19, 32, 42] - >>> print(binary_search(test_list, 3)) + >>> binary_search(test_list, 3) False - >>> print(binary_search(test_list, 13)) + >>> binary_search(test_list, 13) True - >>> print(binary_search([4, 4, 5, 6, 7], 4)) + >>> binary_search([4, 4, 5, 6, 7], 4) True - >>> print(binary_search([4, 4, 5, 6, 7], -10)) + >>> binary_search([4, 4, 5, 6, 7], -10) False - >>> print(binary_search([-18, 2], -18)) + >>> binary_search([-18, 2], -18) True - >>> print(binary_search([5], 5)) + >>> binary_search([5], 5) True - >>> print(binary_search(['a', 'c', 'd'], 'c')) + >>> binary_search(['a', 'c', 'd'], 'c') True - >>> print(binary_search(['a', 'c', 'd'], 'f')) + >>> binary_search(['a', 'c', 'd'], 'f') False - >>> print(binary_search([], 1)) + >>> binary_search([], 1) False - >>> print(binary_search([-.1, .1 , .8], .1)) + >>> binary_search([-.1, .1 , .8], .1) True >>> binary_search(range(-5000, 5000, 10), 80) True diff --git a/sorts/bitonic_sort.py b/sorts/bitonic_sort.py index 201fecd2c..b65f877a4 100644 --- a/sorts/bitonic_sort.py +++ b/sorts/bitonic_sort.py @@ -16,19 +16,19 @@ def comp_and_swap(array: list[int], index1: int, index2: int, direction: int) -> >>> arr = [12, 42, -21, 1] >>> comp_and_swap(arr, 1, 2, 1) - >>> print(arr) + >>> arr [12, -21, 42, 1] >>> comp_and_swap(arr, 1, 2, 0) - >>> print(arr) + >>> arr [12, 42, -21, 1] >>> comp_and_swap(arr, 0, 3, 1) - >>> print(arr) + >>> arr [1, 42, -21, 12] >>> comp_and_swap(arr, 0, 3, 0) - >>> print(arr) + >>> arr [12, 42, -21, 1] """ if (direction == 1 and array[index1] > array[index2]) or ( @@ -46,11 +46,11 @@ def bitonic_merge(array: list[int], low: int, length: int, direction: int) -> No >>> arr = [12, 42, -21, 1] >>> bitonic_merge(arr, 0, 4, 1) - >>> print(arr) + >>> arr [-21, 1, 12, 42] >>> bitonic_merge(arr, 0, 4, 0) - >>> print(arr) + >>> arr [42, 12, 1, -21] """ if length > 1: diff --git a/sorts/normal_distribution_quick_sort.md b/sorts/normal_distribution_quick_sort.md index c073f2cbc..27aca340f 100644 --- a/sorts/normal_distribution_quick_sort.md +++ b/sorts/normal_distribution_quick_sort.md @@ -17,8 +17,8 @@ The array elements are taken from a Standard Normal Distribution, having mean = >>> mu, sigma = 0, 1 # mean and standard deviation >>> X = np.random.normal(mu, sigma, p) >>> np.save(outfile, X) ->>> print('The array is') ->>> print(X) +>>> 'The array is' +>>> X ``` diff --git a/sorts/recursive_insertion_sort.py b/sorts/recursive_insertion_sort.py index ab2716f8e..297dbe945 100644 --- a/sorts/recursive_insertion_sort.py +++ b/sorts/recursive_insertion_sort.py @@ -14,17 +14,17 @@ def rec_insertion_sort(collection: list, n: int): >>> col = [1, 2, 1] >>> rec_insertion_sort(col, len(col)) - >>> print(col) + >>> col [1, 1, 2] >>> col = [2, 1, 0, -1, -2] >>> rec_insertion_sort(col, len(col)) - >>> print(col) + >>> col [-2, -1, 0, 1, 2] >>> col = [1] >>> rec_insertion_sort(col, len(col)) - >>> print(col) + >>> col [1] """ # Checks if the entire collection has been sorted @@ -41,17 +41,17 @@ def insert_next(collection: list, index: int): >>> col = [3, 2, 4, 2] >>> insert_next(col, 1) - >>> print(col) + >>> col [2, 3, 4, 2] >>> col = [3, 2, 3] >>> insert_next(col, 2) - >>> print(col) + >>> col [3, 2, 3] >>> col = [] >>> insert_next(col, 1) - >>> print(col) + >>> col [] """ # Checks order between adjacent elements diff --git a/web_programming/reddit.py b/web_programming/reddit.py index 672109f13..6a31c81c3 100644 --- a/web_programming/reddit.py +++ b/web_programming/reddit.py @@ -23,8 +23,6 @@ def get_subreddit_data( limit : Number of posts to fetch age : ["new", "top", "hot"] wanted_data : Get only the required data in the list - - >>> pass """ wanted_data = wanted_data or [] if invalid_search_terms := ", ".join(sorted(set(wanted_data) - valid_terms)): diff --git a/web_programming/search_books_by_isbn.py b/web_programming/search_books_by_isbn.py index 22a31dcb1..abac3c70b 100644 --- a/web_programming/search_books_by_isbn.py +++ b/web_programming/search_books_by_isbn.py @@ -19,7 +19,6 @@ def get_openlibrary_data(olid: str = "isbn/0140328726") -> dict: {'publishers': ['Puffin'], 'number_of_pages': 96, 'isbn_10': ['0140328726'], ... # >>> get_openlibrary_data(olid='/authors/OL7353617A') # doctest: +ELLIPSIS {'name': 'Adrian Brisku', 'created': {'type': '/type/datetime', ... - >>> pass # Placate https://github.com/apps/algorithms-keeper """ new_olid = olid.strip().strip("/") # Remove leading/trailing whitespace & slashes if new_olid.count("/") != 1: @@ -29,9 +28,7 @@ def get_openlibrary_data(olid: str = "isbn/0140328726") -> dict: def summarize_book(ol_book_data: dict) -> dict: """ - Given Open Library book data, return a summary as a Python dict. - - >>> pass # Placate https://github.com/apps/algorithms-keeper + Given Open Library book data, return a summary as a Python dict. """ desired_keys = { "title": "Title", From de3271ec80c76a8b79c913f68a94f693e8a00a0b Mon Sep 17 00:00:00 2001 From: SwayamSahu <91021799+SwayamSahu@users.noreply.github.com> Date: Fri, 28 Oct 2022 02:32:15 +0530 Subject: [PATCH 451/726] Refactoring the syntax using list comprehension (#7749) * Refactoring the syntax using list comprehension * Update detecting_english_programmatically.py * Update detecting_english_programmatically.py Co-authored-by: Christian Clauss --- strings/detecting_english_programmatically.py | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/strings/detecting_english_programmatically.py b/strings/detecting_english_programmatically.py index aa18db210..b9000101b 100644 --- a/strings/detecting_english_programmatically.py +++ b/strings/detecting_english_programmatically.py @@ -1,7 +1,7 @@ import os +from string import ascii_letters -UPPERLETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" -LETTERS_AND_SPACE = UPPERLETTERS + UPPERLETTERS.lower() + " \t\n" +LETTERS_AND_SPACE = ascii_letters + " \t\n" def load_dictionary() -> dict[str, None]: @@ -20,24 +20,12 @@ def get_english_count(message: str) -> float: message = message.upper() message = remove_non_letters(message) possible_words = message.split() - - if possible_words == []: - return 0.0 - - matches = 0 - for word in possible_words: - if word in ENGLISH_WORDS: - matches += 1 - + matches = len([word for word in possible_words if word in ENGLISH_WORDS]) return float(matches) / len(possible_words) def remove_non_letters(message: str) -> str: - letters_only = [] - for symbol in message: - if symbol in LETTERS_AND_SPACE: - letters_only.append(symbol) - return "".join(letters_only) + return "".join(symbol for symbol in message if symbol in LETTERS_AND_SPACE) def is_english( From 25757e697cfbb5bc7abf47c1ffa13061cb1534e1 Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Thu, 27 Oct 2022 22:03:01 +0100 Subject: [PATCH 452/726] Binary tree path sum (#7748) * feat: Implement binary tree path sum (#7135) * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update data_structures/binary_tree/binary_tree_path_sum.py Co-authored-by: Christian Clauss * refactor: Rename `dfs` to `depth_first_search` Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .../binary_tree/binary_tree_path_sum.py | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 data_structures/binary_tree/binary_tree_path_sum.py diff --git a/data_structures/binary_tree/binary_tree_path_sum.py b/data_structures/binary_tree/binary_tree_path_sum.py new file mode 100644 index 000000000..a3fe9ca7a --- /dev/null +++ b/data_structures/binary_tree/binary_tree_path_sum.py @@ -0,0 +1,88 @@ +""" +Given the root of a binary tree and an integer target, +find the number of paths where the sum of the values +along the path equals target. + + +Leetcode reference: https://leetcode.com/problems/path-sum-iii/ +""" + +from __future__ import annotations + + +class Node: + """ + A Node has value variable and pointers to Nodes to its left and right. + """ + + def __init__(self, value: int) -> None: + self.value = value + self.left: Node | None = None + self.right: Node | None = None + + +class BinaryTreePathSum: + r""" + The below tree looks like this + 10 + / \ + 5 -3 + / \ \ + 3 2 11 + / \ \ + 3 -2 1 + + + >>> tree = Node(10) + >>> tree.left = Node(5) + >>> tree.right = Node(-3) + >>> tree.left.left = Node(3) + >>> tree.left.right = Node(2) + >>> tree.right.right = Node(11) + >>> tree.left.left.left = Node(3) + >>> tree.left.left.right = Node(-2) + >>> tree.left.right.right = Node(1) + + >>> BinaryTreePathSum().path_sum(tree, 8) + 3 + >>> BinaryTreePathSum().path_sum(tree, 7) + 2 + >>> tree.right.right = Node(10) + >>> BinaryTreePathSum().path_sum(tree, 8) + 2 + """ + + target: int + + def __init__(self) -> None: + self.paths = 0 + + def depth_first_search(self, node: Node | None, path_sum: int) -> None: + if node is None: + return + + if path_sum == self.target: + self.paths += 1 + + if node.left: + self.depth_first_search(node.left, path_sum + node.left.value) + if node.right: + self.depth_first_search(node.right, path_sum + node.right.value) + + def path_sum(self, node: Node | None, target: int | None = None) -> int: + if node is None: + return 0 + if target is not None: + self.target = target + + self.depth_first_search(node, node.value) + self.path_sum(node.left) + self.path_sum(node.right) + + return self.paths + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 15c93e5f4bc5b03cecc000506bdf45c100b8f0b3 Mon Sep 17 00:00:00 2001 From: MoPaMo <67760881+MoPaMo@users.noreply.github.com> Date: Thu, 27 Oct 2022 23:03:34 +0200 Subject: [PATCH 453/726] fix typo in caesar_cipher.py (#7761) very character-> every character --- ciphers/caesar_cipher.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ciphers/caesar_cipher.py b/ciphers/caesar_cipher.py index 8cd9fab58..d19b9a337 100644 --- a/ciphers/caesar_cipher.py +++ b/ciphers/caesar_cipher.py @@ -27,7 +27,7 @@ def encrypt(input_string: str, key: int, alphabet: str | None = None) -> str: ========================= The caesar cipher is named after Julius Caesar who used it when sending secret military messages to his troops. This is a simple substitution cipher - where very character in the plain-text is shifted by a certain number known + where every character in the plain-text is shifted by a certain number known as the "key" or "shift". Example: From 19bff003aa1c365bec86d3f4a13a9c3d6c36d230 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Fri, 28 Oct 2022 15:54:54 +0200 Subject: [PATCH 454/726] Adopt Python >= 3.8 assignment expressions using auto-walrus (#7737) * Adopt Python >= 3.8 assignment expressions using auto-walrus * updating DIRECTORY.md * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 5 + DIRECTORY.md | 3 + ciphers/enigma_machine2.py | 3 +- .../linked_list/doubly_linked_list_two.py | 3 +- dynamic_programming/fibonacci.py | 3 +- .../sequential_minimum_optimization.py | 1261 ++++++++--------- strings/indian_phone_validator.py | 3 +- 7 files changed, 642 insertions(+), 639 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5bdda50be..7f6c206b4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,6 +13,11 @@ repos: )$ - id: requirements-txt-fixer + - repo: https://github.com/MarcoGorelli/auto-walrus + rev: v0.2.1 + hooks: + - id: auto-walrus + - repo: https://github.com/psf/black rev: 22.10.0 hooks: diff --git a/DIRECTORY.md b/DIRECTORY.md index ba7d3e62a..7621427a6 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -45,6 +45,7 @@ * [Count 1S Brian Kernighan Method](bit_manipulation/count_1s_brian_kernighan_method.py) * [Count Number Of One Bits](bit_manipulation/count_number_of_one_bits.py) * [Gray Code Sequence](bit_manipulation/gray_code_sequence.py) + * [Highest Set Bit](bit_manipulation/highest_set_bit.py) * [Is Even](bit_manipulation/is_even.py) * [Reverse Bits](bit_manipulation/reverse_bits.py) * [Single Bit Manipulation Operations](bit_manipulation/single_bit_manipulation_operations.py) @@ -326,6 +327,7 @@ ## Financial * [Equated Monthly Installments](financial/equated_monthly_installments.py) * [Interest](financial/interest.py) + * [Price Plus Tax](financial/price_plus_tax.py) ## Fractals * [Julia Sets](fractals/julia_sets.py) @@ -669,6 +671,7 @@ * [Horizontal Projectile Motion](physics/horizontal_projectile_motion.py) * [Kinetic Energy](physics/kinetic_energy.py) * [Lorentz Transformation Four Vector](physics/lorentz_transformation_four_vector.py) + * [Malus Law](physics/malus_law.py) * [N Body Simulation](physics/n_body_simulation.py) * [Newtons Law Of Gravitation](physics/newtons_law_of_gravitation.py) * [Newtons Second Law Of Motion](physics/newtons_second_law_of_motion.py) diff --git a/ciphers/enigma_machine2.py b/ciphers/enigma_machine2.py index 9f9dbe6f7..a877256eb 100644 --- a/ciphers/enigma_machine2.py +++ b/ciphers/enigma_machine2.py @@ -86,8 +86,7 @@ def _validator( """ # Checks if there are 3 unique rotors - unique_rotsel = len(set(rotsel)) - if unique_rotsel < 3: + if (unique_rotsel := len(set(rotsel))) < 3: raise Exception(f"Please use 3 unique rotors (not {unique_rotsel})") # Checks if rotor positions are valid diff --git a/data_structures/linked_list/doubly_linked_list_two.py b/data_structures/linked_list/doubly_linked_list_two.py index 184b6966b..94b916a62 100644 --- a/data_structures/linked_list/doubly_linked_list_two.py +++ b/data_structures/linked_list/doubly_linked_list_two.py @@ -143,9 +143,8 @@ class LinkedList: raise Exception("Node not found") def delete_value(self, value): - node = self.get_node(value) - if node is not None: + if (node := self.get_node(value)) is not None: if node == self.head: self.head = self.head.get_next() diff --git a/dynamic_programming/fibonacci.py b/dynamic_programming/fibonacci.py index 4abc60d4f..7ec5993ef 100644 --- a/dynamic_programming/fibonacci.py +++ b/dynamic_programming/fibonacci.py @@ -18,8 +18,7 @@ class Fibonacci: >>> Fibonacci().get(5) [0, 1, 1, 2, 3] """ - difference = index - (len(self.sequence) - 2) - if difference >= 1: + if (difference := index - (len(self.sequence) - 2)) >= 1: for _ in range(difference): self.sequence.append(self.sequence[-1] + self.sequence[-2]) return self.sequence[:index] diff --git a/machine_learning/sequential_minimum_optimization.py b/machine_learning/sequential_minimum_optimization.py index df5b03790..66535e806 100644 --- a/machine_learning/sequential_minimum_optimization.py +++ b/machine_learning/sequential_minimum_optimization.py @@ -1,631 +1,630 @@ -""" - Implementation of sequential minimal optimization (SMO) for support vector machines - (SVM). - - Sequential minimal optimization (SMO) is an algorithm for solving the quadratic - programming (QP) problem that arises during the training of support vector - machines. - It was invented by John Platt in 1998. - -Input: - 0: type: numpy.ndarray. - 1: first column of ndarray must be tags of samples, must be 1 or -1. - 2: rows of ndarray represent samples. - -Usage: - Command: - python3 sequential_minimum_optimization.py - Code: - from sequential_minimum_optimization import SmoSVM, Kernel - - kernel = Kernel(kernel='poly', degree=3., coef0=1., gamma=0.5) - init_alphas = np.zeros(train.shape[0]) - SVM = SmoSVM(train=train, alpha_list=init_alphas, kernel_func=kernel, cost=0.4, - b=0.0, tolerance=0.001) - SVM.fit() - predict = SVM.predict(test_samples) - -Reference: - https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/smo-book.pdf - https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/tr-98-14.pdf -""" - - -import os -import sys -import urllib.request - -import numpy as np -import pandas as pd -from matplotlib import pyplot as plt -from sklearn.datasets import make_blobs, make_circles -from sklearn.preprocessing import StandardScaler - -CANCER_DATASET_URL = ( - "https://archive.ics.uci.edu/ml/machine-learning-databases/" - "breast-cancer-wisconsin/wdbc.data" -) - - -class SmoSVM: - def __init__( - self, - train, - kernel_func, - alpha_list=None, - cost=0.4, - b=0.0, - tolerance=0.001, - auto_norm=True, - ): - self._init = True - self._auto_norm = auto_norm - self._c = np.float64(cost) - self._b = np.float64(b) - self._tol = np.float64(tolerance) if tolerance > 0.0001 else np.float64(0.001) - - self.tags = train[:, 0] - self.samples = self._norm(train[:, 1:]) if self._auto_norm else train[:, 1:] - self.alphas = alpha_list if alpha_list is not None else np.zeros(train.shape[0]) - self.Kernel = kernel_func - - self._eps = 0.001 - self._all_samples = list(range(self.length)) - self._K_matrix = self._calculate_k_matrix() - self._error = np.zeros(self.length) - self._unbound = [] - - self.choose_alpha = self._choose_alphas() - - # Calculate alphas using SMO algorithm - def fit(self): - k = self._k - state = None - while True: - - # 1: Find alpha1, alpha2 - try: - i1, i2 = self.choose_alpha.send(state) - state = None - except StopIteration: - print("Optimization done!\nEvery sample satisfy the KKT condition!") - break - - # 2: calculate new alpha2 and new alpha1 - y1, y2 = self.tags[i1], self.tags[i2] - a1, a2 = self.alphas[i1].copy(), self.alphas[i2].copy() - e1, e2 = self._e(i1), self._e(i2) - args = (i1, i2, a1, a2, e1, e2, y1, y2) - a1_new, a2_new = self._get_new_alpha(*args) - if not a1_new and not a2_new: - state = False - continue - self.alphas[i1], self.alphas[i2] = a1_new, a2_new - - # 3: update threshold(b) - b1_new = np.float64( - -e1 - - y1 * k(i1, i1) * (a1_new - a1) - - y2 * k(i2, i1) * (a2_new - a2) - + self._b - ) - b2_new = np.float64( - -e2 - - y2 * k(i2, i2) * (a2_new - a2) - - y1 * k(i1, i2) * (a1_new - a1) - + self._b - ) - if 0.0 < a1_new < self._c: - b = b1_new - if 0.0 < a2_new < self._c: - b = b2_new - if not (np.float64(0) < a2_new < self._c) and not ( - np.float64(0) < a1_new < self._c - ): - b = (b1_new + b2_new) / 2.0 - b_old = self._b - self._b = b - - # 4: update error value,here we only calculate those non-bound samples' - # error - self._unbound = [i for i in self._all_samples if self._is_unbound(i)] - for s in self.unbound: - if s == i1 or s == i2: - continue - self._error[s] += ( - y1 * (a1_new - a1) * k(i1, s) - + y2 * (a2_new - a2) * k(i2, s) - + (self._b - b_old) - ) - - # if i1 or i2 is non-bound,update there error value to zero - if self._is_unbound(i1): - self._error[i1] = 0 - if self._is_unbound(i2): - self._error[i2] = 0 - - # Predict test samples - def predict(self, test_samples, classify=True): - - if test_samples.shape[1] > self.samples.shape[1]: - raise ValueError( - "Test samples' feature length does not equal to that of train samples" - ) - - if self._auto_norm: - test_samples = self._norm(test_samples) - - results = [] - for test_sample in test_samples: - result = self._predict(test_sample) - if classify: - results.append(1 if result > 0 else -1) - else: - results.append(result) - return np.array(results) - - # Check if alpha violate KKT condition - def _check_obey_kkt(self, index): - alphas = self.alphas - tol = self._tol - r = self._e(index) * self.tags[index] - c = self._c - - return (r < -tol and alphas[index] < c) or (r > tol and alphas[index] > 0.0) - - # Get value calculated from kernel function - def _k(self, i1, i2): - # for test samples,use Kernel function - if isinstance(i2, np.ndarray): - return self.Kernel(self.samples[i1], i2) - # for train samples,Kernel values have been saved in matrix - else: - return self._K_matrix[i1, i2] - - # Get sample's error - def _e(self, index): - """ - Two cases: - 1:Sample[index] is non-bound,Fetch error from list: _error - 2:sample[index] is bound,Use predicted value deduct true value: g(xi) - yi - - """ - # get from error data - if self._is_unbound(index): - return self._error[index] - # get by g(xi) - yi - else: - gx = np.dot(self.alphas * self.tags, self._K_matrix[:, index]) + self._b - yi = self.tags[index] - return gx - yi - - # Calculate Kernel matrix of all possible i1,i2 ,saving time - def _calculate_k_matrix(self): - k_matrix = np.zeros([self.length, self.length]) - for i in self._all_samples: - for j in self._all_samples: - k_matrix[i, j] = np.float64( - self.Kernel(self.samples[i, :], self.samples[j, :]) - ) - return k_matrix - - # Predict test sample's tag - def _predict(self, sample): - k = self._k - predicted_value = ( - np.sum( - [ - self.alphas[i1] * self.tags[i1] * k(i1, sample) - for i1 in self._all_samples - ] - ) - + self._b - ) - return predicted_value - - # Choose alpha1 and alpha2 - def _choose_alphas(self): - locis = yield from self._choose_a1() - if not locis: - return - return locis - - def _choose_a1(self): - """ - Choose first alpha ;steps: - 1:First loop over all sample - 2:Second loop over all non-bound samples till all non-bound samples does not - voilate kkt condition. - 3:Repeat this two process endlessly,till all samples does not voilate kkt - condition samples after first loop. - """ - while True: - all_not_obey = True - # all sample - print("scanning all sample!") - for i1 in [i for i in self._all_samples if self._check_obey_kkt(i)]: - all_not_obey = False - yield from self._choose_a2(i1) - - # non-bound sample - print("scanning non-bound sample!") - while True: - not_obey = True - for i1 in [ - i - for i in self._all_samples - if self._check_obey_kkt(i) and self._is_unbound(i) - ]: - not_obey = False - yield from self._choose_a2(i1) - if not_obey: - print("all non-bound samples fit the KKT condition!") - break - if all_not_obey: - print("all samples fit the KKT condition! Optimization done!") - break - return False - - def _choose_a2(self, i1): - """ - Choose the second alpha by using heuristic algorithm ;steps: - 1: Choose alpha2 which gets the maximum step size (|E1 - E2|). - 2: Start in a random point,loop over all non-bound samples till alpha1 and - alpha2 are optimized. - 3: Start in a random point,loop over all samples till alpha1 and alpha2 are - optimized. - """ - self._unbound = [i for i in self._all_samples if self._is_unbound(i)] - - if len(self.unbound) > 0: - tmp_error = self._error.copy().tolist() - tmp_error_dict = { - index: value - for index, value in enumerate(tmp_error) - if self._is_unbound(index) - } - if self._e(i1) >= 0: - i2 = min(tmp_error_dict, key=lambda index: tmp_error_dict[index]) - else: - i2 = max(tmp_error_dict, key=lambda index: tmp_error_dict[index]) - cmd = yield i1, i2 - if cmd is None: - return - - for i2 in np.roll(self.unbound, np.random.choice(self.length)): - cmd = yield i1, i2 - if cmd is None: - return - - for i2 in np.roll(self._all_samples, np.random.choice(self.length)): - cmd = yield i1, i2 - if cmd is None: - return - - # Get the new alpha2 and new alpha1 - def _get_new_alpha(self, i1, i2, a1, a2, e1, e2, y1, y2): - k = self._k - if i1 == i2: - return None, None - - # calculate L and H which bound the new alpha2 - s = y1 * y2 - if s == -1: - l, h = max(0.0, a2 - a1), min(self._c, self._c + a2 - a1) - else: - l, h = max(0.0, a2 + a1 - self._c), min(self._c, a2 + a1) - if l == h: # noqa: E741 - return None, None - - # calculate eta - k11 = k(i1, i1) - k22 = k(i2, i2) - k12 = k(i1, i2) - eta = k11 + k22 - 2.0 * k12 - - # select the new alpha2 which could get the minimal objectives - if eta > 0.0: - a2_new_unc = a2 + (y2 * (e1 - e2)) / eta - # a2_new has a boundary - if a2_new_unc >= h: - a2_new = h - elif a2_new_unc <= l: - a2_new = l - else: - a2_new = a2_new_unc - else: - b = self._b - l1 = a1 + s * (a2 - l) - h1 = a1 + s * (a2 - h) - - # way 1 - f1 = y1 * (e1 + b) - a1 * k(i1, i1) - s * a2 * k(i1, i2) - f2 = y2 * (e2 + b) - a2 * k(i2, i2) - s * a1 * k(i1, i2) - ol = ( - l1 * f1 - + l * f2 - + 1 / 2 * l1**2 * k(i1, i1) - + 1 / 2 * l**2 * k(i2, i2) - + s * l * l1 * k(i1, i2) - ) - oh = ( - h1 * f1 - + h * f2 - + 1 / 2 * h1**2 * k(i1, i1) - + 1 / 2 * h**2 * k(i2, i2) - + s * h * h1 * k(i1, i2) - ) - """ - # way 2 - Use objective function check which alpha2 new could get the minimal - objectives - """ - if ol < (oh - self._eps): - a2_new = l - elif ol > oh + self._eps: - a2_new = h - else: - a2_new = a2 - - # a1_new has a boundary too - a1_new = a1 + s * (a2 - a2_new) - if a1_new < 0: - a2_new += s * a1_new - a1_new = 0 - if a1_new > self._c: - a2_new += s * (a1_new - self._c) - a1_new = self._c - - return a1_new, a2_new - - # Normalise data using min_max way - def _norm(self, data): - if self._init: - self._min = np.min(data, axis=0) - self._max = np.max(data, axis=0) - self._init = False - return (data - self._min) / (self._max - self._min) - else: - return (data - self._min) / (self._max - self._min) - - def _is_unbound(self, index): - if 0.0 < self.alphas[index] < self._c: - return True - else: - return False - - def _is_support(self, index): - if self.alphas[index] > 0: - return True - else: - return False - - @property - def unbound(self): - return self._unbound - - @property - def support(self): - return [i for i in range(self.length) if self._is_support(i)] - - @property - def length(self): - return self.samples.shape[0] - - -class Kernel: - def __init__(self, kernel, degree=1.0, coef0=0.0, gamma=1.0): - self.degree = np.float64(degree) - self.coef0 = np.float64(coef0) - self.gamma = np.float64(gamma) - self._kernel_name = kernel - self._kernel = self._get_kernel(kernel_name=kernel) - self._check() - - def _polynomial(self, v1, v2): - return (self.gamma * np.inner(v1, v2) + self.coef0) ** self.degree - - def _linear(self, v1, v2): - return np.inner(v1, v2) + self.coef0 - - def _rbf(self, v1, v2): - return np.exp(-1 * (self.gamma * np.linalg.norm(v1 - v2) ** 2)) - - def _check(self): - if self._kernel == self._rbf: - if self.gamma < 0: - raise ValueError("gamma value must greater than 0") - - def _get_kernel(self, kernel_name): - maps = {"linear": self._linear, "poly": self._polynomial, "rbf": self._rbf} - return maps[kernel_name] - - def __call__(self, v1, v2): - return self._kernel(v1, v2) - - def __repr__(self): - return self._kernel_name - - -def count_time(func): - def call_func(*args, **kwargs): - import time - - start_time = time.time() - func(*args, **kwargs) - end_time = time.time() - print(f"smo algorithm cost {end_time - start_time} seconds") - - return call_func - - -@count_time -def test_cancel_data(): - print("Hello!\nStart test svm by smo algorithm!") - # 0: download dataset and load into pandas' dataframe - if not os.path.exists(r"cancel_data.csv"): - request = urllib.request.Request( - CANCER_DATASET_URL, - headers={"User-Agent": "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)"}, - ) - response = urllib.request.urlopen(request) - content = response.read().decode("utf-8") - with open(r"cancel_data.csv", "w") as f: - f.write(content) - - data = pd.read_csv(r"cancel_data.csv", header=None) - - # 1: pre-processing data - del data[data.columns.tolist()[0]] - data = data.dropna(axis=0) - data = data.replace({"M": np.float64(1), "B": np.float64(-1)}) - samples = np.array(data)[:, :] - - # 2: dividing data into train_data data and test_data data - train_data, test_data = samples[:328, :], samples[328:, :] - test_tags, test_samples = test_data[:, 0], test_data[:, 1:] - - # 3: choose kernel function,and set initial alphas to zero(optional) - mykernel = Kernel(kernel="rbf", degree=5, coef0=1, gamma=0.5) - al = np.zeros(train_data.shape[0]) - - # 4: calculating best alphas using SMO algorithm and predict test_data samples - mysvm = SmoSVM( - train=train_data, - kernel_func=mykernel, - alpha_list=al, - cost=0.4, - b=0.0, - tolerance=0.001, - ) - mysvm.fit() - predict = mysvm.predict(test_samples) - - # 5: check accuracy - score = 0 - test_num = test_tags.shape[0] - for i in range(test_tags.shape[0]): - if test_tags[i] == predict[i]: - score += 1 - print(f"\nall: {test_num}\nright: {score}\nfalse: {test_num - score}") - print(f"Rough Accuracy: {score / test_tags.shape[0]}") - - -def test_demonstration(): - # change stdout - print("\nStart plot,please wait!!!") - sys.stdout = open(os.devnull, "w") - - ax1 = plt.subplot2grid((2, 2), (0, 0)) - ax2 = plt.subplot2grid((2, 2), (0, 1)) - ax3 = plt.subplot2grid((2, 2), (1, 0)) - ax4 = plt.subplot2grid((2, 2), (1, 1)) - ax1.set_title("linear svm,cost:0.1") - test_linear_kernel(ax1, cost=0.1) - ax2.set_title("linear svm,cost:500") - test_linear_kernel(ax2, cost=500) - ax3.set_title("rbf kernel svm,cost:0.1") - test_rbf_kernel(ax3, cost=0.1) - ax4.set_title("rbf kernel svm,cost:500") - test_rbf_kernel(ax4, cost=500) - - sys.stdout = sys.__stdout__ - print("Plot done!!!") - - -def test_linear_kernel(ax, cost): - train_x, train_y = make_blobs( - n_samples=500, centers=2, n_features=2, random_state=1 - ) - train_y[train_y == 0] = -1 - scaler = StandardScaler() - train_x_scaled = scaler.fit_transform(train_x, train_y) - train_data = np.hstack((train_y.reshape(500, 1), train_x_scaled)) - mykernel = Kernel(kernel="linear", degree=5, coef0=1, gamma=0.5) - mysvm = SmoSVM( - train=train_data, - kernel_func=mykernel, - cost=cost, - tolerance=0.001, - auto_norm=False, - ) - mysvm.fit() - plot_partition_boundary(mysvm, train_data, ax=ax) - - -def test_rbf_kernel(ax, cost): - train_x, train_y = make_circles( - n_samples=500, noise=0.1, factor=0.1, random_state=1 - ) - train_y[train_y == 0] = -1 - scaler = StandardScaler() - train_x_scaled = scaler.fit_transform(train_x, train_y) - train_data = np.hstack((train_y.reshape(500, 1), train_x_scaled)) - mykernel = Kernel(kernel="rbf", degree=5, coef0=1, gamma=0.5) - mysvm = SmoSVM( - train=train_data, - kernel_func=mykernel, - cost=cost, - tolerance=0.001, - auto_norm=False, - ) - mysvm.fit() - plot_partition_boundary(mysvm, train_data, ax=ax) - - -def plot_partition_boundary( - model, train_data, ax, resolution=100, colors=("b", "k", "r") -): - """ - We can not get the optimum w of our kernel svm model which is different from linear - svm. For this reason, we generate randomly distributed points with high desity and - prediced values of these points are calculated by using our tained model. Then we - could use this prediced values to draw contour map. - And this contour map can represent svm's partition boundary. - """ - train_data_x = train_data[:, 1] - train_data_y = train_data[:, 2] - train_data_tags = train_data[:, 0] - xrange = np.linspace(train_data_x.min(), train_data_x.max(), resolution) - yrange = np.linspace(train_data_y.min(), train_data_y.max(), resolution) - test_samples = np.array([(x, y) for x in xrange for y in yrange]).reshape( - resolution * resolution, 2 - ) - - test_tags = model.predict(test_samples, classify=False) - grid = test_tags.reshape((len(xrange), len(yrange))) - - # Plot contour map which represents the partition boundary - ax.contour( - xrange, - yrange, - np.mat(grid).T, - levels=(-1, 0, 1), - linestyles=("--", "-", "--"), - linewidths=(1, 1, 1), - colors=colors, - ) - # Plot all train samples - ax.scatter( - train_data_x, - train_data_y, - c=train_data_tags, - cmap=plt.cm.Dark2, - lw=0, - alpha=0.5, - ) - - # Plot support vectors - support = model.support - ax.scatter( - train_data_x[support], - train_data_y[support], - c=train_data_tags[support], - cmap=plt.cm.Dark2, - ) - - -if __name__ == "__main__": - test_cancel_data() - test_demonstration() - plt.show() +""" + Implementation of sequential minimal optimization (SMO) for support vector machines + (SVM). + + Sequential minimal optimization (SMO) is an algorithm for solving the quadratic + programming (QP) problem that arises during the training of support vector + machines. + It was invented by John Platt in 1998. + +Input: + 0: type: numpy.ndarray. + 1: first column of ndarray must be tags of samples, must be 1 or -1. + 2: rows of ndarray represent samples. + +Usage: + Command: + python3 sequential_minimum_optimization.py + Code: + from sequential_minimum_optimization import SmoSVM, Kernel + + kernel = Kernel(kernel='poly', degree=3., coef0=1., gamma=0.5) + init_alphas = np.zeros(train.shape[0]) + SVM = SmoSVM(train=train, alpha_list=init_alphas, kernel_func=kernel, cost=0.4, + b=0.0, tolerance=0.001) + SVM.fit() + predict = SVM.predict(test_samples) + +Reference: + https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/smo-book.pdf + https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/tr-98-14.pdf +""" + + +import os +import sys +import urllib.request + +import numpy as np +import pandas as pd +from matplotlib import pyplot as plt +from sklearn.datasets import make_blobs, make_circles +from sklearn.preprocessing import StandardScaler + +CANCER_DATASET_URL = ( + "https://archive.ics.uci.edu/ml/machine-learning-databases/" + "breast-cancer-wisconsin/wdbc.data" +) + + +class SmoSVM: + def __init__( + self, + train, + kernel_func, + alpha_list=None, + cost=0.4, + b=0.0, + tolerance=0.001, + auto_norm=True, + ): + self._init = True + self._auto_norm = auto_norm + self._c = np.float64(cost) + self._b = np.float64(b) + self._tol = np.float64(tolerance) if tolerance > 0.0001 else np.float64(0.001) + + self.tags = train[:, 0] + self.samples = self._norm(train[:, 1:]) if self._auto_norm else train[:, 1:] + self.alphas = alpha_list if alpha_list is not None else np.zeros(train.shape[0]) + self.Kernel = kernel_func + + self._eps = 0.001 + self._all_samples = list(range(self.length)) + self._K_matrix = self._calculate_k_matrix() + self._error = np.zeros(self.length) + self._unbound = [] + + self.choose_alpha = self._choose_alphas() + + # Calculate alphas using SMO algorithm + def fit(self): + k = self._k + state = None + while True: + + # 1: Find alpha1, alpha2 + try: + i1, i2 = self.choose_alpha.send(state) + state = None + except StopIteration: + print("Optimization done!\nEvery sample satisfy the KKT condition!") + break + + # 2: calculate new alpha2 and new alpha1 + y1, y2 = self.tags[i1], self.tags[i2] + a1, a2 = self.alphas[i1].copy(), self.alphas[i2].copy() + e1, e2 = self._e(i1), self._e(i2) + args = (i1, i2, a1, a2, e1, e2, y1, y2) + a1_new, a2_new = self._get_new_alpha(*args) + if not a1_new and not a2_new: + state = False + continue + self.alphas[i1], self.alphas[i2] = a1_new, a2_new + + # 3: update threshold(b) + b1_new = np.float64( + -e1 + - y1 * k(i1, i1) * (a1_new - a1) + - y2 * k(i2, i1) * (a2_new - a2) + + self._b + ) + b2_new = np.float64( + -e2 + - y2 * k(i2, i2) * (a2_new - a2) + - y1 * k(i1, i2) * (a1_new - a1) + + self._b + ) + if 0.0 < a1_new < self._c: + b = b1_new + if 0.0 < a2_new < self._c: + b = b2_new + if not (np.float64(0) < a2_new < self._c) and not ( + np.float64(0) < a1_new < self._c + ): + b = (b1_new + b2_new) / 2.0 + b_old = self._b + self._b = b + + # 4: update error value,here we only calculate those non-bound samples' + # error + self._unbound = [i for i in self._all_samples if self._is_unbound(i)] + for s in self.unbound: + if s == i1 or s == i2: + continue + self._error[s] += ( + y1 * (a1_new - a1) * k(i1, s) + + y2 * (a2_new - a2) * k(i2, s) + + (self._b - b_old) + ) + + # if i1 or i2 is non-bound,update there error value to zero + if self._is_unbound(i1): + self._error[i1] = 0 + if self._is_unbound(i2): + self._error[i2] = 0 + + # Predict test samples + def predict(self, test_samples, classify=True): + + if test_samples.shape[1] > self.samples.shape[1]: + raise ValueError( + "Test samples' feature length does not equal to that of train samples" + ) + + if self._auto_norm: + test_samples = self._norm(test_samples) + + results = [] + for test_sample in test_samples: + result = self._predict(test_sample) + if classify: + results.append(1 if result > 0 else -1) + else: + results.append(result) + return np.array(results) + + # Check if alpha violate KKT condition + def _check_obey_kkt(self, index): + alphas = self.alphas + tol = self._tol + r = self._e(index) * self.tags[index] + c = self._c + + return (r < -tol and alphas[index] < c) or (r > tol and alphas[index] > 0.0) + + # Get value calculated from kernel function + def _k(self, i1, i2): + # for test samples,use Kernel function + if isinstance(i2, np.ndarray): + return self.Kernel(self.samples[i1], i2) + # for train samples,Kernel values have been saved in matrix + else: + return self._K_matrix[i1, i2] + + # Get sample's error + def _e(self, index): + """ + Two cases: + 1:Sample[index] is non-bound,Fetch error from list: _error + 2:sample[index] is bound,Use predicted value deduct true value: g(xi) - yi + + """ + # get from error data + if self._is_unbound(index): + return self._error[index] + # get by g(xi) - yi + else: + gx = np.dot(self.alphas * self.tags, self._K_matrix[:, index]) + self._b + yi = self.tags[index] + return gx - yi + + # Calculate Kernel matrix of all possible i1,i2 ,saving time + def _calculate_k_matrix(self): + k_matrix = np.zeros([self.length, self.length]) + for i in self._all_samples: + for j in self._all_samples: + k_matrix[i, j] = np.float64( + self.Kernel(self.samples[i, :], self.samples[j, :]) + ) + return k_matrix + + # Predict test sample's tag + def _predict(self, sample): + k = self._k + predicted_value = ( + np.sum( + [ + self.alphas[i1] * self.tags[i1] * k(i1, sample) + for i1 in self._all_samples + ] + ) + + self._b + ) + return predicted_value + + # Choose alpha1 and alpha2 + def _choose_alphas(self): + locis = yield from self._choose_a1() + if not locis: + return + return locis + + def _choose_a1(self): + """ + Choose first alpha ;steps: + 1:First loop over all sample + 2:Second loop over all non-bound samples till all non-bound samples does not + voilate kkt condition. + 3:Repeat this two process endlessly,till all samples does not voilate kkt + condition samples after first loop. + """ + while True: + all_not_obey = True + # all sample + print("scanning all sample!") + for i1 in [i for i in self._all_samples if self._check_obey_kkt(i)]: + all_not_obey = False + yield from self._choose_a2(i1) + + # non-bound sample + print("scanning non-bound sample!") + while True: + not_obey = True + for i1 in [ + i + for i in self._all_samples + if self._check_obey_kkt(i) and self._is_unbound(i) + ]: + not_obey = False + yield from self._choose_a2(i1) + if not_obey: + print("all non-bound samples fit the KKT condition!") + break + if all_not_obey: + print("all samples fit the KKT condition! Optimization done!") + break + return False + + def _choose_a2(self, i1): + """ + Choose the second alpha by using heuristic algorithm ;steps: + 1: Choose alpha2 which gets the maximum step size (|E1 - E2|). + 2: Start in a random point,loop over all non-bound samples till alpha1 and + alpha2 are optimized. + 3: Start in a random point,loop over all samples till alpha1 and alpha2 are + optimized. + """ + self._unbound = [i for i in self._all_samples if self._is_unbound(i)] + + if len(self.unbound) > 0: + tmp_error = self._error.copy().tolist() + tmp_error_dict = { + index: value + for index, value in enumerate(tmp_error) + if self._is_unbound(index) + } + if self._e(i1) >= 0: + i2 = min(tmp_error_dict, key=lambda index: tmp_error_dict[index]) + else: + i2 = max(tmp_error_dict, key=lambda index: tmp_error_dict[index]) + cmd = yield i1, i2 + if cmd is None: + return + + for i2 in np.roll(self.unbound, np.random.choice(self.length)): + cmd = yield i1, i2 + if cmd is None: + return + + for i2 in np.roll(self._all_samples, np.random.choice(self.length)): + cmd = yield i1, i2 + if cmd is None: + return + + # Get the new alpha2 and new alpha1 + def _get_new_alpha(self, i1, i2, a1, a2, e1, e2, y1, y2): + k = self._k + if i1 == i2: + return None, None + + # calculate L and H which bound the new alpha2 + s = y1 * y2 + if s == -1: + l, h = max(0.0, a2 - a1), min(self._c, self._c + a2 - a1) + else: + l, h = max(0.0, a2 + a1 - self._c), min(self._c, a2 + a1) + if l == h: # noqa: E741 + return None, None + + # calculate eta + k11 = k(i1, i1) + k22 = k(i2, i2) + k12 = k(i1, i2) + + # select the new alpha2 which could get the minimal objectives + if (eta := k11 + k22 - 2.0 * k12) > 0.0: + a2_new_unc = a2 + (y2 * (e1 - e2)) / eta + # a2_new has a boundary + if a2_new_unc >= h: + a2_new = h + elif a2_new_unc <= l: + a2_new = l + else: + a2_new = a2_new_unc + else: + b = self._b + l1 = a1 + s * (a2 - l) + h1 = a1 + s * (a2 - h) + + # way 1 + f1 = y1 * (e1 + b) - a1 * k(i1, i1) - s * a2 * k(i1, i2) + f2 = y2 * (e2 + b) - a2 * k(i2, i2) - s * a1 * k(i1, i2) + ol = ( + l1 * f1 + + l * f2 + + 1 / 2 * l1**2 * k(i1, i1) + + 1 / 2 * l**2 * k(i2, i2) + + s * l * l1 * k(i1, i2) + ) + oh = ( + h1 * f1 + + h * f2 + + 1 / 2 * h1**2 * k(i1, i1) + + 1 / 2 * h**2 * k(i2, i2) + + s * h * h1 * k(i1, i2) + ) + """ + # way 2 + Use objective function check which alpha2 new could get the minimal + objectives + """ + if ol < (oh - self._eps): + a2_new = l + elif ol > oh + self._eps: + a2_new = h + else: + a2_new = a2 + + # a1_new has a boundary too + a1_new = a1 + s * (a2 - a2_new) + if a1_new < 0: + a2_new += s * a1_new + a1_new = 0 + if a1_new > self._c: + a2_new += s * (a1_new - self._c) + a1_new = self._c + + return a1_new, a2_new + + # Normalise data using min_max way + def _norm(self, data): + if self._init: + self._min = np.min(data, axis=0) + self._max = np.max(data, axis=0) + self._init = False + return (data - self._min) / (self._max - self._min) + else: + return (data - self._min) / (self._max - self._min) + + def _is_unbound(self, index): + if 0.0 < self.alphas[index] < self._c: + return True + else: + return False + + def _is_support(self, index): + if self.alphas[index] > 0: + return True + else: + return False + + @property + def unbound(self): + return self._unbound + + @property + def support(self): + return [i for i in range(self.length) if self._is_support(i)] + + @property + def length(self): + return self.samples.shape[0] + + +class Kernel: + def __init__(self, kernel, degree=1.0, coef0=0.0, gamma=1.0): + self.degree = np.float64(degree) + self.coef0 = np.float64(coef0) + self.gamma = np.float64(gamma) + self._kernel_name = kernel + self._kernel = self._get_kernel(kernel_name=kernel) + self._check() + + def _polynomial(self, v1, v2): + return (self.gamma * np.inner(v1, v2) + self.coef0) ** self.degree + + def _linear(self, v1, v2): + return np.inner(v1, v2) + self.coef0 + + def _rbf(self, v1, v2): + return np.exp(-1 * (self.gamma * np.linalg.norm(v1 - v2) ** 2)) + + def _check(self): + if self._kernel == self._rbf: + if self.gamma < 0: + raise ValueError("gamma value must greater than 0") + + def _get_kernel(self, kernel_name): + maps = {"linear": self._linear, "poly": self._polynomial, "rbf": self._rbf} + return maps[kernel_name] + + def __call__(self, v1, v2): + return self._kernel(v1, v2) + + def __repr__(self): + return self._kernel_name + + +def count_time(func): + def call_func(*args, **kwargs): + import time + + start_time = time.time() + func(*args, **kwargs) + end_time = time.time() + print(f"smo algorithm cost {end_time - start_time} seconds") + + return call_func + + +@count_time +def test_cancel_data(): + print("Hello!\nStart test svm by smo algorithm!") + # 0: download dataset and load into pandas' dataframe + if not os.path.exists(r"cancel_data.csv"): + request = urllib.request.Request( + CANCER_DATASET_URL, + headers={"User-Agent": "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)"}, + ) + response = urllib.request.urlopen(request) + content = response.read().decode("utf-8") + with open(r"cancel_data.csv", "w") as f: + f.write(content) + + data = pd.read_csv(r"cancel_data.csv", header=None) + + # 1: pre-processing data + del data[data.columns.tolist()[0]] + data = data.dropna(axis=0) + data = data.replace({"M": np.float64(1), "B": np.float64(-1)}) + samples = np.array(data)[:, :] + + # 2: dividing data into train_data data and test_data data + train_data, test_data = samples[:328, :], samples[328:, :] + test_tags, test_samples = test_data[:, 0], test_data[:, 1:] + + # 3: choose kernel function,and set initial alphas to zero(optional) + mykernel = Kernel(kernel="rbf", degree=5, coef0=1, gamma=0.5) + al = np.zeros(train_data.shape[0]) + + # 4: calculating best alphas using SMO algorithm and predict test_data samples + mysvm = SmoSVM( + train=train_data, + kernel_func=mykernel, + alpha_list=al, + cost=0.4, + b=0.0, + tolerance=0.001, + ) + mysvm.fit() + predict = mysvm.predict(test_samples) + + # 5: check accuracy + score = 0 + test_num = test_tags.shape[0] + for i in range(test_tags.shape[0]): + if test_tags[i] == predict[i]: + score += 1 + print(f"\nall: {test_num}\nright: {score}\nfalse: {test_num - score}") + print(f"Rough Accuracy: {score / test_tags.shape[0]}") + + +def test_demonstration(): + # change stdout + print("\nStart plot,please wait!!!") + sys.stdout = open(os.devnull, "w") + + ax1 = plt.subplot2grid((2, 2), (0, 0)) + ax2 = plt.subplot2grid((2, 2), (0, 1)) + ax3 = plt.subplot2grid((2, 2), (1, 0)) + ax4 = plt.subplot2grid((2, 2), (1, 1)) + ax1.set_title("linear svm,cost:0.1") + test_linear_kernel(ax1, cost=0.1) + ax2.set_title("linear svm,cost:500") + test_linear_kernel(ax2, cost=500) + ax3.set_title("rbf kernel svm,cost:0.1") + test_rbf_kernel(ax3, cost=0.1) + ax4.set_title("rbf kernel svm,cost:500") + test_rbf_kernel(ax4, cost=500) + + sys.stdout = sys.__stdout__ + print("Plot done!!!") + + +def test_linear_kernel(ax, cost): + train_x, train_y = make_blobs( + n_samples=500, centers=2, n_features=2, random_state=1 + ) + train_y[train_y == 0] = -1 + scaler = StandardScaler() + train_x_scaled = scaler.fit_transform(train_x, train_y) + train_data = np.hstack((train_y.reshape(500, 1), train_x_scaled)) + mykernel = Kernel(kernel="linear", degree=5, coef0=1, gamma=0.5) + mysvm = SmoSVM( + train=train_data, + kernel_func=mykernel, + cost=cost, + tolerance=0.001, + auto_norm=False, + ) + mysvm.fit() + plot_partition_boundary(mysvm, train_data, ax=ax) + + +def test_rbf_kernel(ax, cost): + train_x, train_y = make_circles( + n_samples=500, noise=0.1, factor=0.1, random_state=1 + ) + train_y[train_y == 0] = -1 + scaler = StandardScaler() + train_x_scaled = scaler.fit_transform(train_x, train_y) + train_data = np.hstack((train_y.reshape(500, 1), train_x_scaled)) + mykernel = Kernel(kernel="rbf", degree=5, coef0=1, gamma=0.5) + mysvm = SmoSVM( + train=train_data, + kernel_func=mykernel, + cost=cost, + tolerance=0.001, + auto_norm=False, + ) + mysvm.fit() + plot_partition_boundary(mysvm, train_data, ax=ax) + + +def plot_partition_boundary( + model, train_data, ax, resolution=100, colors=("b", "k", "r") +): + """ + We can not get the optimum w of our kernel svm model which is different from linear + svm. For this reason, we generate randomly distributed points with high desity and + prediced values of these points are calculated by using our tained model. Then we + could use this prediced values to draw contour map. + And this contour map can represent svm's partition boundary. + """ + train_data_x = train_data[:, 1] + train_data_y = train_data[:, 2] + train_data_tags = train_data[:, 0] + xrange = np.linspace(train_data_x.min(), train_data_x.max(), resolution) + yrange = np.linspace(train_data_y.min(), train_data_y.max(), resolution) + test_samples = np.array([(x, y) for x in xrange for y in yrange]).reshape( + resolution * resolution, 2 + ) + + test_tags = model.predict(test_samples, classify=False) + grid = test_tags.reshape((len(xrange), len(yrange))) + + # Plot contour map which represents the partition boundary + ax.contour( + xrange, + yrange, + np.mat(grid).T, + levels=(-1, 0, 1), + linestyles=("--", "-", "--"), + linewidths=(1, 1, 1), + colors=colors, + ) + # Plot all train samples + ax.scatter( + train_data_x, + train_data_y, + c=train_data_tags, + cmap=plt.cm.Dark2, + lw=0, + alpha=0.5, + ) + + # Plot support vectors + support = model.support + ax.scatter( + train_data_x[support], + train_data_y[support], + c=train_data_tags[support], + cmap=plt.cm.Dark2, + ) + + +if __name__ == "__main__": + test_cancel_data() + test_demonstration() + plt.show() diff --git a/strings/indian_phone_validator.py b/strings/indian_phone_validator.py index 7f3fda5db..07161a63a 100644 --- a/strings/indian_phone_validator.py +++ b/strings/indian_phone_validator.py @@ -20,8 +20,7 @@ def indian_phone_validator(phone: str) -> bool: True """ pat = re.compile(r"^(\+91[\-\s]?)?[0]?(91)?[789]\d{9}$") - match = re.search(pat, phone) - if match: + if match := re.search(pat, phone): return match.string == phone return False From 3a671b57a29e3c2b4e973b01bc5bbe1554aa5da2 Mon Sep 17 00:00:00 2001 From: Kuldeep Borkar <74557588+KuldeepBorkar@users.noreply.github.com> Date: Fri, 28 Oct 2022 19:57:16 +0530 Subject: [PATCH 455/726] Implemented Swish Function (#7357) * Implemented Swish Function * Added more description and return hint in def * Changed the name and added more descrition including test for sigmoid function * Added * in front of links --- maths/sigmoid_linear_unit.py | 57 ++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 maths/sigmoid_linear_unit.py diff --git a/maths/sigmoid_linear_unit.py b/maths/sigmoid_linear_unit.py new file mode 100644 index 000000000..a8ada10dd --- /dev/null +++ b/maths/sigmoid_linear_unit.py @@ -0,0 +1,57 @@ +""" +This script demonstrates the implementation of the Sigmoid Linear Unit (SiLU) +or swish function. +* https://en.wikipedia.org/wiki/Rectifier_(neural_networks) +* https://en.wikipedia.org/wiki/Swish_function + +The function takes a vector x of K real numbers as input and returns x * sigmoid(x). +Swish is a smooth, non-monotonic function defined as f(x) = x * sigmoid(x). +Extensive experiments shows that Swish consistently matches or outperforms ReLU +on deep networks applied to a variety of challenging domains such as +image classification and machine translation. + +This script is inspired by a corresponding research paper. +* https://arxiv.org/abs/1710.05941 +""" + +import numpy as np + + +def sigmoid(vector: np.array) -> np.array: + """ + Mathematical function sigmoid takes a vector x of K real numbers as input and + returns 1/ (1 + e^-x). + https://en.wikipedia.org/wiki/Sigmoid_function + + >>> sigmoid(np.array([-1.0, 1.0, 2.0])) + array([0.26894142, 0.73105858, 0.88079708]) + """ + return 1 / (1 + np.exp(-vector)) + + +def sigmoid_linear_unit(vector: np.array) -> np.array: + """ + Implements the Sigmoid Linear Unit (SiLU) or swish function + + Parameters: + vector (np.array): A numpy array consisting of real + values. + + Returns: + swish_vec (np.array): The input numpy array, after applying + swish. + + Examples: + >>> sigmoid_linear_unit(np.array([-1.0, 1.0, 2.0])) + array([-0.26894142, 0.73105858, 1.76159416]) + + >>> sigmoid_linear_unit(np.array([-2])) + array([-0.23840584]) + """ + return vector * sigmoid(vector) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 26cecea27198848e2c1c0bc6d7f887d4ed7adb87 Mon Sep 17 00:00:00 2001 From: SparshRastogi <75373475+SparshRastogi@users.noreply.github.com> Date: Fri, 28 Oct 2022 20:03:21 +0530 Subject: [PATCH 456/726] Create fetch_amazon_product_data.py (#7585) * Create fetch_amazon_product_data.py This file provides a function which will take a product name as input from the user,and fetch the necessary information about that kind of products from Amazon like the product title,link to that product,price of the product,the ratings of the product and the discount available on the product in the form of a csv file,this will help the users by improving searchability and navigability and find the right product easily and in a short period of time, it will also be beneficial for performing better analysis on products * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update fetch_amazon_product_data.py Added type hints and modified files to pass precommit test * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update fetch_amazon_product_data.py Added type hints and made changes to pass the precommit * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update fetch_amazon_product_data.py Modified function to return the data in the form of Pandas Dataframe,modified type hints and added a functionality to let the user determine if they need the data in a csv file * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update fetch_amazon_product_data.py Made some bug fixes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update and rename fetch_amazon_product_data.py to get_amazon_product_data.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update get_amazon_product_data.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- web_programming/get_amazon_product_data.py | 100 +++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 web_programming/get_amazon_product_data.py diff --git a/web_programming/get_amazon_product_data.py b/web_programming/get_amazon_product_data.py new file mode 100644 index 000000000..c796793f2 --- /dev/null +++ b/web_programming/get_amazon_product_data.py @@ -0,0 +1,100 @@ +""" +This file provides a function which will take a product name as input from the user, +and fetch from Amazon information about products of this name or category. The product +information will include title, URL, price, ratings, and the discount available. +""" + + +from itertools import zip_longest + +import requests +from bs4 import BeautifulSoup +from pandas import DataFrame + + +def get_amazon_product_data(product: str = "laptop") -> DataFrame: + """ + Take a product name or category as input and return product information from Amazon + including title, URL, price, ratings, and the discount available. + """ + url = f"https://www.amazon.in/laptop/s?k={product}" + header = { + "User-Agent": """Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 + (KHTML, like Gecko)Chrome/44.0.2403.157 Safari/537.36""", + "Accept-Language": "en-US, en;q=0.5", + } + soup = BeautifulSoup(requests.get(url, headers=header).text) + # Initialize a Pandas dataframe with the column titles + data_frame = DataFrame( + columns=[ + "Product Title", + "Product Link", + "Current Price of the product", + "Product Rating", + "MRP of the product", + "Discount", + ] + ) + # Loop through each entry and store them in the dataframe + for item, _ in zip_longest( + soup.find_all( + "div", + attrs={"class": "s-result-item", "data-component-type": "s-search-result"}, + ), + soup.find_all("div", attrs={"class": "a-row a-size-base a-color-base"}), + ): + try: + product_title = item.h2.text + product_link = "https://www.amazon.in/" + item.h2.a["href"] + product_price = item.find("span", attrs={"class": "a-offscreen"}).text + try: + product_rating = item.find("span", attrs={"class": "a-icon-alt"}).text + except AttributeError: + product_rating = "Not available" + try: + product_mrp = ( + "₹" + + item.find( + "span", attrs={"class": "a-price a-text-price"} + ).text.split("₹")[1] + ) + except AttributeError: + product_mrp = "" + try: + discount = float( + ( + ( + float(product_mrp.strip("₹").replace(",", "")) + - float(product_price.strip("₹").replace(",", "")) + ) + / float(product_mrp.strip("₹").replace(",", "")) + ) + * 100 + ) + except ValueError: + discount = float("nan") + except AttributeError: + pass + data_frame.loc[len(data_frame.index)] = [ + product_title, + product_link, + product_price, + product_rating, + product_mrp, + discount, + ] + data_frame.loc[ + data_frame["Current Price of the product"] > data_frame["MRP of the product"], + "MRP of the product", + ] = " " + data_frame.loc[ + data_frame["Current Price of the product"] > data_frame["MRP of the product"], + "Discount", + ] = " " + data_frame.index += 1 + return data_frame + + +if __name__ == "__main__": + product = "headphones" + get_amazon_product_data(product).to_csv(f"Amazon Product Data for {product}.csv") From d9efd7e25bbe937893a9818cfda62ca3f72ffe0d Mon Sep 17 00:00:00 2001 From: Andrey Date: Fri, 28 Oct 2022 21:54:44 +0300 Subject: [PATCH 457/726] Update PR template (#7794) * Update PR template * Revert changes, reword line --- .github/pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 4d2265968..b3ba8baf9 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -16,5 +16,5 @@ * [ ] All functions and variable names follow Python naming conventions. * [ ] All function parameters and return values are annotated with Python [type hints](https://docs.python.org/3/library/typing.html). * [ ] All functions have [doctests](https://docs.python.org/3/library/doctest.html) that pass the automated testing. -* [ ] All new algorithms have a URL in its comments that points to Wikipedia or other similar explanation. +* [ ] All new algorithms include at least one URL that points to Wikipedia or another similar explanation. * [ ] If this pull request resolves one or more open issues then the commit message contains `Fixes: #{$ISSUE_NO}`. From 528b1290194da09c2e762c2232502d2cfcdb1e3d Mon Sep 17 00:00:00 2001 From: Pronoy Mandal Date: Sat, 29 Oct 2022 00:38:41 +0530 Subject: [PATCH 458/726] Update maximum_subarray.py (#7757) * Update maximum_subarray.py 1. Rectify documentation to indicate the correct output: function doesn't return the subarray, but rather returns a sum. 2. Make the function more Pythonic and optimal. 3. Make function annotation generic i.e. can accept any sequence. 4. Raise value error when the input sequence is empty. * Update maximum_subarray.py 1. Use the conventions as mentioned in pep-0257. 2. Use negative infinity as the initial value for the current maximum and the answer. * Update maximum_subarray.py Avoid type conflict by returning the answer cast to an integer. * Update other/maximum_subarray.py Co-authored-by: Andrey * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update maximum_subarray.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update maximum_subarray.py Remove typecast to int for the final answer Co-authored-by: Andrey Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- other/maximum_subarray.py | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/other/maximum_subarray.py b/other/maximum_subarray.py index 756e00944..1c8c8cabc 100644 --- a/other/maximum_subarray.py +++ b/other/maximum_subarray.py @@ -1,20 +1,26 @@ -def max_subarray(nums: list[int]) -> int: - """ - Returns the subarray with maximum sum - >>> max_subarray([1,2,3,4,-2]) +from collections.abc import Sequence + + +def max_subarray_sum(nums: Sequence[int]) -> int: + """Return the maximum possible sum amongst all non - empty subarrays. + + Raises: + ValueError: when nums is empty. + + >>> max_subarray_sum([1,2,3,4,-2]) 10 - >>> max_subarray([-2,1,-3,4,-1,2,1,-5,4]) + >>> max_subarray_sum([-2,1,-3,4,-1,2,1,-5,4]) 6 """ + if not nums: + raise ValueError("Input sequence should not be empty") curr_max = ans = nums[0] + nums_len = len(nums) - for i in range(1, len(nums)): - if curr_max >= 0: - curr_max = curr_max + nums[i] - else: - curr_max = nums[i] - + for i in range(1, nums_len): + num = nums[i] + curr_max = max(curr_max + num, num) ans = max(curr_max, ans) return ans @@ -23,4 +29,4 @@ def max_subarray(nums: list[int]) -> int: if __name__ == "__main__": n = int(input("Enter number of elements : ").strip()) array = list(map(int, input("\nEnter the numbers : ").strip().split()))[:n] - print(max_subarray(array)) + print(max_subarray_sum(array)) From fe5819c872abcbe1a96ee7bd20ab930b2892bbf5 Mon Sep 17 00:00:00 2001 From: Shubham Kondekar <40213815+kondekarshubham123@users.noreply.github.com> Date: Sat, 29 Oct 2022 01:02:32 +0530 Subject: [PATCH 459/726] Create combination_sum_iv.py (#7672) * Create combination_sum_iv.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update dynamic_programming/combination_sum_iv.py Co-authored-by: Caeden Perelli-Harris * Update dynamic_programming/combination_sum_iv.py Co-authored-by: Caeden Perelli-Harris * Update dynamic_programming/combination_sum_iv.py Co-authored-by: Caeden Perelli-Harris * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update combination_sum_iv.py * Update combination_sum_iv.py * Resolved PR Comments * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * minor change, argument missing in function * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update dynamic_programming/combination_sum_iv.py Co-authored-by: Christian Clauss * minor change Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Caeden Perelli-Harris Co-authored-by: Christian Clauss --- dynamic_programming/combination_sum_iv.py | 102 ++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 dynamic_programming/combination_sum_iv.py diff --git a/dynamic_programming/combination_sum_iv.py b/dynamic_programming/combination_sum_iv.py new file mode 100644 index 000000000..b2aeb0824 --- /dev/null +++ b/dynamic_programming/combination_sum_iv.py @@ -0,0 +1,102 @@ +""" +Question: +You are given an array of distinct integers and you have to tell how many +different ways of selecting the elements from the array are there such that +the sum of chosen elements is equal to the target number tar. + +Example + +Input: +N = 3 +target = 5 +array = [1, 2, 5] + +Output: +9 + +Approach: +The basic idea is to go over recursively to find the way such that the sum +of chosen elements is “tar”. For every element, we have two choices + 1. Include the element in our set of chosen elements. + 2. Don’t include the element in our set of chosen elements. +""" + + +def combination_sum_iv(n: int, array: list[int], target: int) -> int: + """ + Function checks the all possible combinations, and returns the count + of possible combination in exponential Time Complexity. + + >>> combination_sum_iv(3, [1,2,5], 5) + 9 + """ + + def count_of_possible_combinations(target: int) -> int: + if target < 0: + return 0 + if target == 0: + return 1 + return sum(count_of_possible_combinations(target - item) for item in array) + + return count_of_possible_combinations(target) + + +def combination_sum_iv_dp_array(n: int, array: list[int], target: int) -> int: + """ + Function checks the all possible combinations, and returns the count + of possible combination in O(N^2) Time Complexity as we are using Dynamic + programming array here. + + >>> combination_sum_iv_dp_array(3, [1,2,5], 5) + 9 + """ + + def count_of_possible_combinations_with_dp_array( + target: int, dp_array: list[int] + ) -> int: + if target < 0: + return 0 + if target == 0: + return 1 + if dp_array[target] != -1: + return dp_array[target] + answer = sum( + count_of_possible_combinations_with_dp_array(target - item, dp_array) + for item in array + ) + dp_array[target] = answer + return answer + + dp_array = [-1] * (target + 1) + return count_of_possible_combinations_with_dp_array(target, dp_array) + + +def combination_sum_iv_bottom_up(n: int, array: list[int], target: int) -> int: + """ + Function checks the all possible combinations with using bottom up approach, + and returns the count of possible combination in O(N^2) Time Complexity + as we are using Dynamic programming array here. + + >>> combination_sum_iv_bottom_up(3, [1,2,5], 5) + 9 + """ + + dp_array = [0] * (target + 1) + dp_array[0] = 1 + + for i in range(1, target + 1): + for j in range(n): + if i - array[j] >= 0: + dp_array[i] += dp_array[i - array[j]] + + return dp_array[target] + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + n = 3 + target = 5 + array = [1, 2, 5] + print(combination_sum_iv(n, array, target)) From 762afc086f065f1d8fe1afcde8c8ad3fa46898a7 Mon Sep 17 00:00:00 2001 From: Andrey Date: Fri, 28 Oct 2022 23:27:39 +0300 Subject: [PATCH 460/726] Update breadth_first_search_2.py (#7765) * Cleanup the BFS * Add both functions and timeit * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Add performace results as comment * Update breadth_first_search_2.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- graphs/breadth_first_search_2.py | 45 +++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/graphs/breadth_first_search_2.py b/graphs/breadth_first_search_2.py index 2f060a90d..a0b92b90b 100644 --- a/graphs/breadth_first_search_2.py +++ b/graphs/breadth_first_search_2.py @@ -14,7 +14,9 @@ while Q is non-empty: """ from __future__ import annotations +from collections import deque from queue import Queue +from timeit import timeit G = { "A": ["B", "C"], @@ -26,12 +28,15 @@ G = { } -def breadth_first_search(graph: dict, start: str) -> set[str]: +def breadth_first_search(graph: dict, start: str) -> list[str]: """ - >>> ''.join(sorted(breadth_first_search(G, 'A'))) + Implementation of breadth first search using queue.Queue. + + >>> ''.join(breadth_first_search(G, 'A')) 'ABCDEF' """ explored = {start} + result = [start] queue: Queue = Queue() queue.put(start) while not queue.empty(): @@ -39,12 +44,44 @@ def breadth_first_search(graph: dict, start: str) -> set[str]: for w in graph[v]: if w not in explored: explored.add(w) + result.append(w) queue.put(w) - return explored + return result + + +def breadth_first_search_with_deque(graph: dict, start: str) -> list[str]: + """ + Implementation of breadth first search using collection.queue. + + >>> ''.join(breadth_first_search_with_deque(G, 'A')) + 'ABCDEF' + """ + visited = {start} + result = [start] + queue = deque([start]) + while queue: + v = queue.popleft() + for child in graph[v]: + if child not in visited: + visited.add(child) + result.append(child) + queue.append(child) + return result + + +def benchmark_function(name: str) -> None: + setup = f"from __main__ import G, {name}" + number = 10000 + res = timeit(f"{name}(G, 'A')", setup=setup, number=number) + print(f"{name:<35} finished {number} runs in {res:.5f} seconds") if __name__ == "__main__": import doctest doctest.testmod() - print(breadth_first_search(G, "A")) + + benchmark_function("breadth_first_search") + benchmark_function("breadth_first_search_with_deque") + # breadth_first_search finished 10000 runs in 0.20999 seconds + # breadth_first_search_with_deque finished 10000 runs in 0.01421 seconds From cf08d9f5e7afdcfb9406032abcad328aa79c566a Mon Sep 17 00:00:00 2001 From: Andrey Date: Sat, 29 Oct 2022 09:26:19 +0300 Subject: [PATCH 461/726] Format docs (#7821) * Reformat docs for odd_even_sort.py * Fix docstring formatting * Apply suggestions from code review Co-authored-by: Caeden Perelli-Harris Co-authored-by: Caeden Perelli-Harris --- machine_learning/data_transformations.py | 10 +++++++--- physics/kinetic_energy.py | 5 ++++- sorts/merge_sort.py | 9 ++++++--- sorts/odd_even_sort.py | 9 +++++++-- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/machine_learning/data_transformations.py b/machine_learning/data_transformations.py index 9e0d747e9..ecfd3b9e2 100644 --- a/machine_learning/data_transformations.py +++ b/machine_learning/data_transformations.py @@ -1,5 +1,7 @@ """ -Normalization Wikipedia: https://en.wikipedia.org/wiki/Normalization +Normalization. + +Wikipedia: https://en.wikipedia.org/wiki/Normalization Normalization is the process of converting numerical data to a standard range of values. This range is typically between [0, 1] or [-1, 1]. The equation for normalization is x_norm = (x - x_min)/(x_max - x_min) where x_norm is the normalized value, x is the @@ -28,7 +30,8 @@ from statistics import mean, stdev def normalization(data: list, ndigits: int = 3) -> list: """ - Returns a normalized list of values + Return a normalized list of values. + @params: data, a list of values to normalize @returns: a list of normalized values (rounded to ndigits decimal places) @examples: @@ -46,7 +49,8 @@ def normalization(data: list, ndigits: int = 3) -> list: def standardization(data: list, ndigits: int = 3) -> list: """ - Returns a standardized list of values + Return a standardized list of values. + @params: data, a list of values to standardize @returns: a list of standardized values (rounded to ndigits decimal places) @examples: diff --git a/physics/kinetic_energy.py b/physics/kinetic_energy.py index 535ffc219..8863919ac 100644 --- a/physics/kinetic_energy.py +++ b/physics/kinetic_energy.py @@ -1,5 +1,6 @@ """ -Find the kinetic energy of an object, give its mass and velocity +Find the kinetic energy of an object, given its mass and velocity. + Description : In physics, the kinetic energy of an object is the energy that it possesses due to its motion. It is defined as the work needed to accelerate a body of a given mass from rest to its stated velocity. Having gained this energy during its @@ -19,6 +20,8 @@ Reference : https://en.m.wikipedia.org/wiki/Kinetic_energy def kinetic_energy(mass: float, velocity: float) -> float: """ + Calculate kinetick energy. + The kinetic energy of a non-rotating object of mass m traveling at a speed v is ½mv² >>> kinetic_energy(10,10) diff --git a/sorts/merge_sort.py b/sorts/merge_sort.py index 4da29f32a..e80b1cb22 100644 --- a/sorts/merge_sort.py +++ b/sorts/merge_sort.py @@ -1,5 +1,6 @@ """ -This is a pure Python implementation of the merge sort algorithm +This is a pure Python implementation of the merge sort algorithm. + For doctests run following command: python -m doctest -v merge_sort.py or @@ -10,7 +11,7 @@ python merge_sort.py def merge_sort(collection: list) -> list: - """Pure implementation of the merge sort algorithm in Python + """ :param collection: some mutable ordered collection with heterogeneous comparable items inside :return: the same collection ordered by ascending @@ -24,7 +25,9 @@ def merge_sort(collection: list) -> list: """ def merge(left: list, right: list) -> list: - """merge left and right + """ + Merge left and right. + :param left: left collection :param right: right collection :return: merge result diff --git a/sorts/odd_even_sort.py b/sorts/odd_even_sort.py index 532f82949..9ef4462c7 100644 --- a/sorts/odd_even_sort.py +++ b/sorts/odd_even_sort.py @@ -1,10 +1,15 @@ -"""For reference +""" +Odd even sort implementation. + https://en.wikipedia.org/wiki/Odd%E2%80%93even_sort """ def odd_even_sort(input_list: list) -> list: - """this algorithm uses the same idea of bubblesort, + """ + Sort input with odd even sort. + + This algorithm uses the same idea of bubblesort, but by first dividing in two phase (odd and even). Originally developed for use on parallel processors with local interconnections. From 301a520f0362261cddadc87e1bcfe20310308030 Mon Sep 17 00:00:00 2001 From: SparshRastogi <75373475+SparshRastogi@users.noreply.github.com> Date: Sat, 29 Oct 2022 16:44:44 +0530 Subject: [PATCH 462/726] Create potential_energy.py (#7666) * Create potential_energy.py Finding the gravitational potential energy of an object with reference to the earth, by taking its mass and height above the ground as input * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update physics/potential_energy.py Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> * Update physics/potential_energy.py Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> * Update physics/potential_energy.py Co-authored-by: Caeden Perelli-Harris * Update physics/potential_energy.py Co-authored-by: Caeden Perelli-Harris * Update physics/potential_energy.py Co-authored-by: Caeden Perelli-Harris * Update physics/potential_energy.py Co-authored-by: Caeden Perelli-Harris * Update physics/potential_energy.py Co-authored-by: Caeden Perelli-Harris * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> Co-authored-by: Caeden Perelli-Harris --- physics/potential_energy.py | 61 +++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 physics/potential_energy.py diff --git a/physics/potential_energy.py b/physics/potential_energy.py new file mode 100644 index 000000000..c6544f6f7 --- /dev/null +++ b/physics/potential_energy.py @@ -0,0 +1,61 @@ +from scipy.constants import g + +""" +Finding the gravitational potential energy of an object with reference +to the earth,by taking its mass and height above the ground as input + + +Description : Gravitational energy or gravitational potential energy +is the potential energy a massive object has in relation to another +massive object due to gravity. It is the potential energy associated +with the gravitational field, which is released (converted into +kinetic energy) when the objects fall towards each other. +Gravitational potential energy increases when two objects +are brought further apart. + +For two pairwise interacting point particles, the gravitational +potential energy U is given by +U=-GMm/R +where M and m are the masses of the two particles, R is the distance +between them, and G is the gravitational constant. +Close to the Earth's surface, the gravitational field is approximately +constant, and the gravitational potential energy of an object reduces to +U=mgh +where m is the object's mass, g=GM/R² is the gravity of Earth, and h is +the height of the object's center of mass above a chosen reference level. + +Reference : "https://en.m.wikipedia.org/wiki/Gravitational_energy" +""" + + +def potential_energy(mass: float, height: float) -> float: + # function will accept mass and height as parameters and return potential energy + """ + >>> potential_energy(10,10) + 980.665 + >>> potential_energy(0,5) + 0.0 + >>> potential_energy(8,0) + 0.0 + >>> potential_energy(10,5) + 490.3325 + >>> potential_energy(0,0) + 0.0 + >>> potential_energy(2,8) + 156.9064 + >>> potential_energy(20,100) + 19613.3 + """ + if mass < 0: + # handling of negative values of mass + raise ValueError("The mass of a body cannot be negative") + if height < 0: + # handling of negative values of height + raise ValueError("The height above the ground cannot be negative") + return mass * g * height + + +if __name__ == "__main__": + from doctest import testmod + + testmod(name="potential_energy") From a9bd68d96e519d0919c2e4385dbe433ff44b4c4f Mon Sep 17 00:00:00 2001 From: Andrey Date: Sat, 29 Oct 2022 15:27:47 +0300 Subject: [PATCH 463/726] Add running doctest to pytest default (#7840) * Add default options for pytest * updating DIRECTORY.md * Move pytest settings to pyproject.toml * Move coverage settings to the pyproject.toml * Return --doctest-continue-on-failure to pytest * Convert pytest args to list * Update pyproject.toml Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss --- .coveragerc | 4 ---- .github/workflows/build.yml | 2 +- DIRECTORY.md | 4 ++++ pyproject.toml | 20 ++++++++++++++++++++ pytest.ini | 5 ----- 5 files changed, 25 insertions(+), 10 deletions(-) delete mode 100644 .coveragerc create mode 100644 pyproject.toml delete mode 100644 pytest.ini diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index f7e6eb212..000000000 --- a/.coveragerc +++ /dev/null @@ -1,4 +0,0 @@ -[report] -sort = Cover -omit = - .env/* diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8481b962a..159ce13b3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,6 +22,6 @@ jobs: python -m pip install --upgrade pip setuptools six wheel python -m pip install pytest-cov -r requirements.txt - name: Run tests - run: pytest --doctest-modules --ignore=project_euler/ --ignore=scripts/validate_solutions.py --cov-report=term-missing:skip-covered --cov=. . + run: pytest --ignore=project_euler/ --ignore=scripts/validate_solutions.py --cov-report=term-missing:skip-covered --cov=. . - if: ${{ success() }} run: scripts/build_directory_md.py 2>&1 | tee DIRECTORY.md diff --git a/DIRECTORY.md b/DIRECTORY.md index 7621427a6..1fa6af75d 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -165,6 +165,7 @@ * [Binary Search Tree Recursive](data_structures/binary_tree/binary_search_tree_recursive.py) * [Binary Tree Mirror](data_structures/binary_tree/binary_tree_mirror.py) * [Binary Tree Node Sum](data_structures/binary_tree/binary_tree_node_sum.py) + * [Binary Tree Path Sum](data_structures/binary_tree/binary_tree_path_sum.py) * [Binary Tree Traversals](data_structures/binary_tree/binary_tree_traversals.py) * [Diff Views Of Binary Tree](data_structures/binary_tree/diff_views_of_binary_tree.py) * [Fenwick Tree](data_structures/binary_tree/fenwick_tree.py) @@ -285,6 +286,7 @@ * [Bitmask](dynamic_programming/bitmask.py) * [Catalan Numbers](dynamic_programming/catalan_numbers.py) * [Climbing Stairs](dynamic_programming/climbing_stairs.py) + * [Combination Sum Iv](dynamic_programming/combination_sum_iv.py) * [Edit Distance](dynamic_programming/edit_distance.py) * [Factorial](dynamic_programming/factorial.py) * [Fast Fibonacci](dynamic_programming/fast_fibonacci.py) @@ -595,6 +597,7 @@ * [P Series](maths/series/p_series.py) * [Sieve Of Eratosthenes](maths/sieve_of_eratosthenes.py) * [Sigmoid](maths/sigmoid.py) + * [Sigmoid Linear Unit](maths/sigmoid_linear_unit.py) * [Signum](maths/signum.py) * [Simpson Rule](maths/simpson_rule.py) * [Sin](maths/sin.py) @@ -1107,6 +1110,7 @@ * [Fetch Jobs](web_programming/fetch_jobs.py) * [Fetch Quotes](web_programming/fetch_quotes.py) * [Fetch Well Rx Price](web_programming/fetch_well_rx_price.py) + * [Get Amazon Product Data](web_programming/get_amazon_product_data.py) * [Get Imdb Top 250 Movies Csv](web_programming/get_imdb_top_250_movies_csv.py) * [Get Imdbtop](web_programming/get_imdbtop.py) * [Get Top Billioners](web_programming/get_top_billioners.py) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..410e7655b --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,20 @@ +[tool.pytest.ini_options] +markers = [ + "mat_ops: mark a test as utilizing matrix operations.", +] +addopts = [ + "--durations=10", + "--doctest-modules", + "--showlocals", +] + + +[tool.coverage.report] +omit = [".env/*"] +sort = "Cover" + +#[report] +#sort = Cover +#omit = +# .env/* +# backtracking/* diff --git a/pytest.ini b/pytest.ini deleted file mode 100644 index 488379278..000000000 --- a/pytest.ini +++ /dev/null @@ -1,5 +0,0 @@ -# Setup for pytest -[pytest] -markers = - mat_ops: mark a test as utilizing matrix operations. -addopts = --durations=10 From 6e809a25e33e2da07e03921bbf6614523a939e94 Mon Sep 17 00:00:00 2001 From: Andrey Date: Sat, 29 Oct 2022 15:31:56 +0300 Subject: [PATCH 464/726] Rename files (#7819) --- ...s_shortest_path.py => breadth_first_search_shortest_path_2.py} | 0 ...est_path.py => breadth_first_search_zero_one_shortest_path.py} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename graphs/{bfs_shortest_path.py => breadth_first_search_shortest_path_2.py} (100%) rename graphs/{bfs_zero_one_shortest_path.py => breadth_first_search_zero_one_shortest_path.py} (100%) diff --git a/graphs/bfs_shortest_path.py b/graphs/breadth_first_search_shortest_path_2.py similarity index 100% rename from graphs/bfs_shortest_path.py rename to graphs/breadth_first_search_shortest_path_2.py diff --git a/graphs/bfs_zero_one_shortest_path.py b/graphs/breadth_first_search_zero_one_shortest_path.py similarity index 100% rename from graphs/bfs_zero_one_shortest_path.py rename to graphs/breadth_first_search_zero_one_shortest_path.py From 327c38d6f0c6b79b46465406373ea7048bfec55e Mon Sep 17 00:00:00 2001 From: Sineth Sankalpa <66241389+sinsankio@users.noreply.github.com> Date: Sat, 29 Oct 2022 18:10:14 +0530 Subject: [PATCH 465/726] Srilankan phone number validation (#7706) * Add is_srilankan_phone_number.py * Update is_srilankan_phone_number.py --- strings/is_srilankan_phone_number.py | 35 ++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 strings/is_srilankan_phone_number.py diff --git a/strings/is_srilankan_phone_number.py b/strings/is_srilankan_phone_number.py new file mode 100644 index 000000000..7bded93f7 --- /dev/null +++ b/strings/is_srilankan_phone_number.py @@ -0,0 +1,35 @@ +import re + + +def is_sri_lankan_phone_number(phone: str) -> bool: + """ + Determine whether the string is a valid sri lankan mobile phone number or not + References: https://aye.sh/blog/sri-lankan-phone-number-regex + + >>> is_sri_lankan_phone_number("+94773283048") + True + >>> is_sri_lankan_phone_number("+9477-3283048") + True + >>> is_sri_lankan_phone_number("0718382399") + True + >>> is_sri_lankan_phone_number("0094702343221") + True + >>> is_sri_lankan_phone_number("075 3201568") + True + >>> is_sri_lankan_phone_number("07779209245") + False + >>> is_sri_lankan_phone_number("0957651234") + False + """ + + pattern = re.compile( + r"^(?:0|94|\+94|0{2}94)" r"7(0|1|2|4|5|6|7|8)" r"(-| |)" r"\d{7}$" + ) + + return bool(re.search(pattern, phone)) + + +if __name__ == "__main__": + phone = "0094702343221" + + print(is_sri_lankan_phone_number(phone)) From b0f68a0248d3eb48f3baf7e18f6420dc983bdb19 Mon Sep 17 00:00:00 2001 From: tarushirastogi <108577219+tarushirastogi@users.noreply.github.com> Date: Sat, 29 Oct 2022 18:13:51 +0530 Subject: [PATCH 466/726] Create centripetal_force.py (#7778) * Create centripetal_force.py Centripetal force is the force acting on an object in curvilinear motion directed towards the axis of rotation or centre of curvature. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update centripetal_force.py The value error should also handle negative values of the radius and using more descriptive names will be more beneficial for the users * Update centripetal_force.py Made some bug fixes Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: SparshRastogi <75373475+SparshRastogi@users.noreply.github.com> --- physics/centripetal_force.py | 49 ++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 physics/centripetal_force.py diff --git a/physics/centripetal_force.py b/physics/centripetal_force.py new file mode 100644 index 000000000..04069d256 --- /dev/null +++ b/physics/centripetal_force.py @@ -0,0 +1,49 @@ +""" +Description : Centripetal force is the force acting on an object in +curvilinear motion directed towards the axis of rotation +or centre of curvature. + +The unit of centripetal force is newton. + +The centripetal force is always directed perpendicular to the +direction of the object’s displacement. Using Newton’s second +law of motion, it is found that the centripetal force of an object +moving in a circular path always acts towards the centre of the circle. +The Centripetal Force Formula is given as the product of mass (in kg) +and tangential velocity (in meters per second) squared, divided by the +radius (in meters) that implies that on doubling the tangential velocity, +the centripetal force will be quadrupled. Mathematically it is written as: +F = mv²/r +Where, F is the Centripetal force, m is the mass of the object, v is the +speed or velocity of the object and r is the radius. + +Reference: https://byjus.com/physics/centripetal-and-centrifugal-force/ +""" + + +def centripetal(mass: float, velocity: float, radius: float) -> float: + """ + The Centripetal Force formula is given as: (m*v*v)/r + + >>> round(centripetal(15.5,-30,10),2) + 1395.0 + >>> round(centripetal(10,15,5),2) + 450.0 + >>> round(centripetal(20,-50,15),2) + 3333.33 + >>> round(centripetal(12.25,40,25),2) + 784.0 + >>> round(centripetal(50,100,50),2) + 10000.0 + """ + if mass < 0: + raise ValueError("The mass of the body cannot be negative") + if radius <= 0: + raise ValueError("The radius is always a positive non zero integer") + return (mass * (velocity) ** 2) / radius + + +if __name__ == "__main__": + import doctest + + doctest.testmod(verbose=True) From 18ffc4dec85a85837f71cd6c9b1e630b9d185001 Mon Sep 17 00:00:00 2001 From: Pronoy Mandal Date: Sat, 29 Oct 2022 18:24:13 +0530 Subject: [PATCH 467/726] Update password_generator.py (#7745) * Update password_generator.py 1. Use secrets module instead of random for passwords as it gives a secure source of randomness 2. Add type annotations for functions 3. Replace ctbi (variable for the characters to be included) with a more meaningful and short name 4. Use integer division instead of obtaining the integer part of a division computing a floating point * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- other/password_generator.py | 40 +++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/other/password_generator.py b/other/password_generator.py index c09afd7e6..8f9d58a33 100644 --- a/other/password_generator.py +++ b/other/password_generator.py @@ -1,9 +1,10 @@ """Password Generator allows you to generate a random password of length N.""" -from random import choice, shuffle +import secrets +from random import shuffle from string import ascii_letters, digits, punctuation -def password_generator(length=8): +def password_generator(length: int = 8) -> str: """ >>> len(password_generator()) 8 @@ -17,58 +18,59 @@ def password_generator(length=8): 0 """ chars = ascii_letters + digits + punctuation - return "".join(choice(chars) for x in range(length)) + return "".join(secrets.choice(chars) for _ in range(length)) # ALTERNATIVE METHODS -# ctbi= characters that must be in password +# chars_incl= characters that must be in password # i= how many letters or characters the password length will be -def alternative_password_generator(ctbi, i): +def alternative_password_generator(chars_incl: str, i: int) -> str: # Password Generator = full boot with random_number, random_letters, and # random_character FUNCTIONS # Put your code here... - i = i - len(ctbi) - quotient = int(i / 3) + i -= len(chars_incl) + quotient = i // 3 remainder = i % 3 - # chars = ctbi + random_letters(ascii_letters, i / 3 + remainder) + + # chars = chars_incl + random_letters(ascii_letters, i / 3 + remainder) + # random_number(digits, i / 3) + random_characters(punctuation, i / 3) chars = ( - ctbi + chars_incl + random(ascii_letters, quotient + remainder) + random(digits, quotient) + random(punctuation, quotient) ) - chars = list(chars) - shuffle(chars) - return "".join(chars) + list_of_chars = list(chars) + shuffle(list_of_chars) + return "".join(list_of_chars) # random is a generalised function for letters, characters and numbers -def random(ctbi, i): - return "".join(choice(ctbi) for x in range(i)) +def random(chars_incl: str, i: int) -> str: + return "".join(secrets.choice(chars_incl) for _ in range(i)) -def random_number(ctbi, i): +def random_number(chars_incl, i): pass # Put your code here... -def random_letters(ctbi, i): +def random_letters(chars_incl, i): pass # Put your code here... -def random_characters(ctbi, i): +def random_characters(chars_incl, i): pass # Put your code here... def main(): length = int(input("Please indicate the max length of your password: ").strip()) - ctbi = input( + chars_incl = input( "Please indicate the characters that must be in your password: " ).strip() print("Password generated:", password_generator(length)) print( - "Alternative Password generated:", alternative_password_generator(ctbi, length) + "Alternative Password generated:", + alternative_password_generator(chars_incl, length), ) print("[If you are thinking of using this passsword, You better save it.]") From 584e743422565decd35b1b6f94cef3ced840698b Mon Sep 17 00:00:00 2001 From: Andrey Date: Sat, 29 Oct 2022 16:07:02 +0300 Subject: [PATCH 468/726] Fix yesqa hook (#7843) * fix yesqa hook * Remove redundant noqa * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .pre-commit-config.yaml | 10 ++++++++-- DIRECTORY.md | 5 +++-- .../binary_tree/non_recursive_segment_tree.py | 2 +- digital_image_processing/index_calculation.py | 2 +- genetic_algorithm/basic_string.py | 2 +- maths/prime_sieve_eratosthenes.py | 2 -- 6 files changed, 14 insertions(+), 9 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7f6c206b4..56946f5f2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,13 +41,19 @@ repos: rev: 5.0.4 hooks: - id: flake8 # See .flake8 for args - additional_dependencies: + additional_dependencies: &flake8-plugins - flake8-bugbear - flake8-builtins - flake8-broken-line - flake8-comprehensions - pep8-naming - - yesqa + + - repo: https://github.com/asottile/yesqa + rev: v1.4.0 + hooks: + - id: yesqa + additional_dependencies: + *flake8-plugins - repo: https://github.com/pre-commit/mirrors-mypy rev: v0.982 diff --git a/DIRECTORY.md b/DIRECTORY.md index 1fa6af75d..198cc7077 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -356,14 +356,14 @@ * [Articulation Points](graphs/articulation_points.py) * [Basic Graphs](graphs/basic_graphs.py) * [Bellman Ford](graphs/bellman_ford.py) - * [Bfs Shortest Path](graphs/bfs_shortest_path.py) - * [Bfs Zero One Shortest Path](graphs/bfs_zero_one_shortest_path.py) * [Bidirectional A Star](graphs/bidirectional_a_star.py) * [Bidirectional Breadth First Search](graphs/bidirectional_breadth_first_search.py) * [Boruvka](graphs/boruvka.py) * [Breadth First Search](graphs/breadth_first_search.py) * [Breadth First Search 2](graphs/breadth_first_search_2.py) * [Breadth First Search Shortest Path](graphs/breadth_first_search_shortest_path.py) + * [Breadth First Search Shortest Path 2](graphs/breadth_first_search_shortest_path_2.py) + * [Breadth First Search Zero One Shortest Path](graphs/breadth_first_search_zero_one_shortest_path.py) * [Check Bipartite Graph Bfs](graphs/check_bipartite_graph_bfs.py) * [Check Bipartite Graph Dfs](graphs/check_bipartite_graph_dfs.py) * [Check Cycle](graphs/check_cycle.py) @@ -678,6 +678,7 @@ * [N Body Simulation](physics/n_body_simulation.py) * [Newtons Law Of Gravitation](physics/newtons_law_of_gravitation.py) * [Newtons Second Law Of Motion](physics/newtons_second_law_of_motion.py) + * [Potential Energy](physics/potential_energy.py) ## Project Euler * Problem 001 diff --git a/data_structures/binary_tree/non_recursive_segment_tree.py b/data_structures/binary_tree/non_recursive_segment_tree.py index c29adefff..075ff6c91 100644 --- a/data_structures/binary_tree/non_recursive_segment_tree.py +++ b/data_structures/binary_tree/non_recursive_segment_tree.py @@ -103,7 +103,7 @@ class SegmentTree(Generic[T]): >>> st.query(2, 3) 7 """ - l, r = l + self.N, r + self.N # noqa: E741 + l, r = l + self.N, r + self.N res: T | None = None while l <= r: # noqa: E741 diff --git a/digital_image_processing/index_calculation.py b/digital_image_processing/index_calculation.py index be1855e99..67830668b 100644 --- a/digital_image_processing/index_calculation.py +++ b/digital_image_processing/index_calculation.py @@ -413,7 +413,7 @@ class IndexCalculation: """ return (self.nir / ((self.nir + self.red) / 2)) * (self.ndvi() + 1) - def i(self): # noqa: E741,E743 + def i(self): """ Intensity https://www.indexdatabase.de/db/i-single.php?id=36 diff --git a/genetic_algorithm/basic_string.py b/genetic_algorithm/basic_string.py index 5cf8d691b..45b8be651 100644 --- a/genetic_algorithm/basic_string.py +++ b/genetic_algorithm/basic_string.py @@ -80,7 +80,7 @@ def basic(target: str, genes: list[str], debug: bool = True) -> tuple[int, int, score = len( [g for position, g in enumerate(item) if g == main_target[position]] ) - return (item, float(score)) # noqa: B023 + return (item, float(score)) # Adding a bit of concurrency can make everything faster, # diff --git a/maths/prime_sieve_eratosthenes.py b/maths/prime_sieve_eratosthenes.py index 8d60e48c2..3a3c55085 100644 --- a/maths/prime_sieve_eratosthenes.py +++ b/maths/prime_sieve_eratosthenes.py @@ -1,5 +1,3 @@ -# flake8: noqa - """ Sieve of Eratosthenes From 93ad7db97fa211b6e9f77025513a45df83400f88 Mon Sep 17 00:00:00 2001 From: JatinR05 <71865805+JatinR05@users.noreply.github.com> Date: Sat, 29 Oct 2022 18:58:12 +0530 Subject: [PATCH 469/726] Create recursive_approach_knapsack.py (#7587) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Create recursive_approach_knapsack.py Added a new naïve recursive approach to solve the knapsack problem. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update recursive_approach_knapsack.py Updated the code * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update recursive_approach_knapsack.py Updated * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- knapsack/recursive_approach_knapsack.py | 52 +++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 knapsack/recursive_approach_knapsack.py diff --git a/knapsack/recursive_approach_knapsack.py b/knapsack/recursive_approach_knapsack.py new file mode 100644 index 000000000..d813981cb --- /dev/null +++ b/knapsack/recursive_approach_knapsack.py @@ -0,0 +1,52 @@ +# To get an insight into naive recursive way to solve the Knapsack problem + + +""" +A shopkeeper has bags of wheat that each have different weights and different profits. +eg. +no_of_items 4 +profit 5 4 8 6 +weight 1 2 4 5 +max_weight 5 +Constraints: +max_weight > 0 +profit[i] >= 0 +weight[i] >= 0 +Calculate the maximum profit that the shopkeeper can make given maxmum weight that can +be carried. +""" + + +def knapsack( + weights: list, values: list, number_of_items: int, max_weight: int, index: int +) -> int: + """ + Function description is as follows- + :param weights: Take a list of weights + :param values: Take a list of profits corresponding to the weights + :param number_of_items: number of items available to pick from + :param max_weight: Maximum weight that could be carried + :param index: the element we are looking at + :return: Maximum expected gain + >>> knapsack([1, 2, 4, 5], [5, 4, 8, 6], 4, 5, 0) + 13 + >>> knapsack([3 ,4 , 5], [10, 9 , 8], 3, 25, 0) + 27 + """ + if index == number_of_items: + return 0 + ans1 = 0 + ans2 = 0 + ans1 = knapsack(weights, values, number_of_items, max_weight, index + 1) + if weights[index] <= max_weight: + ans2 = values[index] + knapsack( + weights, values, number_of_items, max_weight - weights[index], index + 1 + ) + return max(ans1, ans2) + + +if __name__ == "__main__": + + import doctest + + doctest.testmod() From efb4a3aee842e1db855e678f28b79588734ff146 Mon Sep 17 00:00:00 2001 From: Anshraj Shrivastava <42239140+rajansh87@users.noreply.github.com> Date: Sat, 29 Oct 2022 18:59:15 +0530 Subject: [PATCH 470/726] added algo for finding permutations of an array (#7614) * Add files via upload * Delete permutations.cpython-310.pyc * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update permutations.py * Update permutations.py * Add files via upload * Delete permutations.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update permutations.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update permutations.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update permutations.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update data_structures/arrays/permutations.py Co-authored-by: Christian Clauss * Update permutations.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update permutations.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update data_structures/arrays/permutations.py Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> * Update permutations.py * Update permutations.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update permutations.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> --- data_structures/arrays/permutations.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 data_structures/arrays/permutations.py diff --git a/data_structures/arrays/permutations.py b/data_structures/arrays/permutations.py new file mode 100644 index 000000000..eb3f26517 --- /dev/null +++ b/data_structures/arrays/permutations.py @@ -0,0 +1,26 @@ +def permute(nums: list[int]) -> list[list[int]]: + """ + Return all permutations. + + >>> from itertools import permutations + >>> numbers= [1,2,3] + >>> all(list(nums) in permute(numbers) for nums in permutations(numbers)) + True + """ + result = [] + if len(nums) == 1: + return [nums.copy()] + for _ in range(len(nums)): + n = nums.pop(0) + permutations = permute(nums) + for perm in permutations: + perm.append(n) + result.extend(permutations) + nums.append(n) + return result + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 7b521b66cfe3d16960c3fa8e01ff947794cc44a6 Mon Sep 17 00:00:00 2001 From: Carlos Villar Date: Sat, 29 Oct 2022 15:44:18 +0200 Subject: [PATCH 471/726] Add Viterbi algorithm (#7509) * Added Viterbi algorithm Fixes: #7465 Squashed commits * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Added doctest for validators * moved all extracted functions to the main function * Forgot a type hint Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- dynamic_programming/viterbi.py | 400 +++++++++++++++++++++++++++++++++ 1 file changed, 400 insertions(+) create mode 100644 dynamic_programming/viterbi.py diff --git a/dynamic_programming/viterbi.py b/dynamic_programming/viterbi.py new file mode 100644 index 000000000..93ab845e2 --- /dev/null +++ b/dynamic_programming/viterbi.py @@ -0,0 +1,400 @@ +from typing import Any + + +def viterbi( + observations_space: list, + states_space: list, + initial_probabilities: dict, + transition_probabilities: dict, + emission_probabilities: dict, +) -> list: + """ + Viterbi Algorithm, to find the most likely path of + states from the start and the expected output. + https://en.wikipedia.org/wiki/Viterbi_algorithm + sdafads + Wikipedia example + >>> observations = ["normal", "cold", "dizzy"] + >>> states = ["Healthy", "Fever"] + >>> start_p = {"Healthy": 0.6, "Fever": 0.4} + >>> trans_p = { + ... "Healthy": {"Healthy": 0.7, "Fever": 0.3}, + ... "Fever": {"Healthy": 0.4, "Fever": 0.6}, + ... } + >>> emit_p = { + ... "Healthy": {"normal": 0.5, "cold": 0.4, "dizzy": 0.1}, + ... "Fever": {"normal": 0.1, "cold": 0.3, "dizzy": 0.6}, + ... } + >>> viterbi(observations, states, start_p, trans_p, emit_p) + ['Healthy', 'Healthy', 'Fever'] + + >>> viterbi((), states, start_p, trans_p, emit_p) + Traceback (most recent call last): + ... + ValueError: There's an empty parameter + + >>> viterbi(observations, (), start_p, trans_p, emit_p) + Traceback (most recent call last): + ... + ValueError: There's an empty parameter + + >>> viterbi(observations, states, {}, trans_p, emit_p) + Traceback (most recent call last): + ... + ValueError: There's an empty parameter + + >>> viterbi(observations, states, start_p, {}, emit_p) + Traceback (most recent call last): + ... + ValueError: There's an empty parameter + + >>> viterbi(observations, states, start_p, trans_p, {}) + Traceback (most recent call last): + ... + ValueError: There's an empty parameter + + >>> viterbi("invalid", states, start_p, trans_p, emit_p) + Traceback (most recent call last): + ... + ValueError: observations_space must be a list + + >>> viterbi(["valid", 123], states, start_p, trans_p, emit_p) + Traceback (most recent call last): + ... + ValueError: observations_space must be a list of strings + + >>> viterbi(observations, "invalid", start_p, trans_p, emit_p) + Traceback (most recent call last): + ... + ValueError: states_space must be a list + + >>> viterbi(observations, ["valid", 123], start_p, trans_p, emit_p) + Traceback (most recent call last): + ... + ValueError: states_space must be a list of strings + + >>> viterbi(observations, states, "invalid", trans_p, emit_p) + Traceback (most recent call last): + ... + ValueError: initial_probabilities must be a dict + + >>> viterbi(observations, states, {2:2}, trans_p, emit_p) + Traceback (most recent call last): + ... + ValueError: initial_probabilities all keys must be strings + + >>> viterbi(observations, states, {"a":2}, trans_p, emit_p) + Traceback (most recent call last): + ... + ValueError: initial_probabilities all values must be float + + >>> viterbi(observations, states, start_p, "invalid", emit_p) + Traceback (most recent call last): + ... + ValueError: transition_probabilities must be a dict + + >>> viterbi(observations, states, start_p, {"a":2}, emit_p) + Traceback (most recent call last): + ... + ValueError: transition_probabilities all values must be dict + + >>> viterbi(observations, states, start_p, {2:{2:2}}, emit_p) + Traceback (most recent call last): + ... + ValueError: transition_probabilities all keys must be strings + + >>> viterbi(observations, states, start_p, {"a":{2:2}}, emit_p) + Traceback (most recent call last): + ... + ValueError: transition_probabilities all keys must be strings + + >>> viterbi(observations, states, start_p, {"a":{"b":2}}, emit_p) + Traceback (most recent call last): + ... + ValueError: transition_probabilities nested dictionary all values must be float + + >>> viterbi(observations, states, start_p, trans_p, "invalid") + Traceback (most recent call last): + ... + ValueError: emission_probabilities must be a dict + + >>> viterbi(observations, states, start_p, trans_p, None) + Traceback (most recent call last): + ... + ValueError: There's an empty parameter + + """ + _validation( + observations_space, + states_space, + initial_probabilities, + transition_probabilities, + emission_probabilities, + ) + # Creates data structures and fill initial step + probabilities: dict = {} + pointers: dict = {} + for state in states_space: + observation = observations_space[0] + probabilities[(state, observation)] = ( + initial_probabilities[state] * emission_probabilities[state][observation] + ) + pointers[(state, observation)] = None + + # Fills the data structure with the probabilities of + # different transitions and pointers to previous states + for o in range(1, len(observations_space)): + observation = observations_space[o] + prior_observation = observations_space[o - 1] + for state in states_space: + # Calculates the argmax for probability function + arg_max = "" + max_probability = -1 + for k_state in states_space: + probability = ( + probabilities[(k_state, prior_observation)] + * transition_probabilities[k_state][state] + * emission_probabilities[state][observation] + ) + if probability > max_probability: + max_probability = probability + arg_max = k_state + + # Update probabilities and pointers dicts + probabilities[(state, observation)] = ( + probabilities[(arg_max, prior_observation)] + * transition_probabilities[arg_max][state] + * emission_probabilities[state][observation] + ) + + pointers[(state, observation)] = arg_max + + # The final observation + final_observation = observations_space[len(observations_space) - 1] + + # argmax for given final observation + arg_max = "" + max_probability = -1 + for k_state in states_space: + probability = probabilities[(k_state, final_observation)] + if probability > max_probability: + max_probability = probability + arg_max = k_state + last_state = arg_max + + # Process pointers backwards + previous = last_state + result = [] + for o in range(len(observations_space) - 1, -1, -1): + result.append(previous) + previous = pointers[previous, observations_space[o]] + result.reverse() + + return result + + +def _validation( + observations_space: Any, + states_space: Any, + initial_probabilities: Any, + transition_probabilities: Any, + emission_probabilities: Any, +) -> None: + """ + >>> observations = ["normal", "cold", "dizzy"] + >>> states = ["Healthy", "Fever"] + >>> start_p = {"Healthy": 0.6, "Fever": 0.4} + >>> trans_p = { + ... "Healthy": {"Healthy": 0.7, "Fever": 0.3}, + ... "Fever": {"Healthy": 0.4, "Fever": 0.6}, + ... } + >>> emit_p = { + ... "Healthy": {"normal": 0.5, "cold": 0.4, "dizzy": 0.1}, + ... "Fever": {"normal": 0.1, "cold": 0.3, "dizzy": 0.6}, + ... } + >>> _validation(observations, states, start_p, trans_p, emit_p) + + >>> _validation([], states, start_p, trans_p, emit_p) + Traceback (most recent call last): + ... + ValueError: There's an empty parameter + """ + _validate_not_empty( + observations_space, + states_space, + initial_probabilities, + transition_probabilities, + emission_probabilities, + ) + _validate_lists(observations_space, states_space) + _validate_dicts( + initial_probabilities, transition_probabilities, emission_probabilities + ) + + +def _validate_not_empty( + observations_space: Any, + states_space: Any, + initial_probabilities: Any, + transition_probabilities: Any, + emission_probabilities: Any, +) -> None: + """ + >>> _validate_not_empty(["a"], ["b"], {"c":0.5}, + ... {"d": {"e": 0.6}}, {"f": {"g": 0.7}}) + + >>> _validate_not_empty(["a"], ["b"], {"c":0.5}, {}, {"f": {"g": 0.7}}) + Traceback (most recent call last): + ... + ValueError: There's an empty parameter + >>> _validate_not_empty(["a"], ["b"], None, {"d": {"e": 0.6}}, {"f": {"g": 0.7}}) + Traceback (most recent call last): + ... + ValueError: There's an empty parameter + """ + if not all( + [ + observations_space, + states_space, + initial_probabilities, + transition_probabilities, + emission_probabilities, + ] + ): + raise ValueError("There's an empty parameter") + + +def _validate_lists(observations_space: Any, states_space: Any) -> None: + """ + >>> _validate_lists(["a"], ["b"]) + + >>> _validate_lists(1234, ["b"]) + Traceback (most recent call last): + ... + ValueError: observations_space must be a list + + >>> _validate_lists(["a"], [3]) + Traceback (most recent call last): + ... + ValueError: states_space must be a list of strings + """ + _validate_list(observations_space, "observations_space") + _validate_list(states_space, "states_space") + + +def _validate_list(_object: Any, var_name: str) -> None: + """ + >>> _validate_list(["a"], "mock_name") + + >>> _validate_list("a", "mock_name") + Traceback (most recent call last): + ... + ValueError: mock_name must be a list + >>> _validate_list([0.5], "mock_name") + Traceback (most recent call last): + ... + ValueError: mock_name must be a list of strings + + """ + if not isinstance(_object, list): + raise ValueError(f"{var_name} must be a list") + else: + for x in _object: + if not isinstance(x, str): + raise ValueError(f"{var_name} must be a list of strings") + + +def _validate_dicts( + initial_probabilities: Any, + transition_probabilities: Any, + emission_probabilities: Any, +) -> None: + """ + >>> _validate_dicts({"c":0.5}, {"d": {"e": 0.6}}, {"f": {"g": 0.7}}) + + >>> _validate_dicts("invalid", {"d": {"e": 0.6}}, {"f": {"g": 0.7}}) + Traceback (most recent call last): + ... + ValueError: initial_probabilities must be a dict + >>> _validate_dicts({"c":0.5}, {2: {"e": 0.6}}, {"f": {"g": 0.7}}) + Traceback (most recent call last): + ... + ValueError: transition_probabilities all keys must be strings + >>> _validate_dicts({"c":0.5}, {"d": {"e": 0.6}}, {"f": {2: 0.7}}) + Traceback (most recent call last): + ... + ValueError: emission_probabilities all keys must be strings + >>> _validate_dicts({"c":0.5}, {"d": {"e": 0.6}}, {"f": {"g": "h"}}) + Traceback (most recent call last): + ... + ValueError: emission_probabilities nested dictionary all values must be float + """ + _validate_dict(initial_probabilities, "initial_probabilities", float) + _validate_nested_dict(transition_probabilities, "transition_probabilities") + _validate_nested_dict(emission_probabilities, "emission_probabilities") + + +def _validate_nested_dict(_object: Any, var_name: str) -> None: + """ + >>> _validate_nested_dict({"a":{"b": 0.5}}, "mock_name") + + >>> _validate_nested_dict("invalid", "mock_name") + Traceback (most recent call last): + ... + ValueError: mock_name must be a dict + >>> _validate_nested_dict({"a": 8}, "mock_name") + Traceback (most recent call last): + ... + ValueError: mock_name all values must be dict + >>> _validate_nested_dict({"a":{2: 0.5}}, "mock_name") + Traceback (most recent call last): + ... + ValueError: mock_name all keys must be strings + >>> _validate_nested_dict({"a":{"b": 4}}, "mock_name") + Traceback (most recent call last): + ... + ValueError: mock_name nested dictionary all values must be float + """ + _validate_dict(_object, var_name, dict) + for x in _object.values(): + _validate_dict(x, var_name, float, True) + + +def _validate_dict( + _object: Any, var_name: str, value_type: type, nested: bool = False +) -> None: + """ + >>> _validate_dict({"b": 0.5}, "mock_name", float) + + >>> _validate_dict("invalid", "mock_name", float) + Traceback (most recent call last): + ... + ValueError: mock_name must be a dict + >>> _validate_dict({"a": 8}, "mock_name", dict) + Traceback (most recent call last): + ... + ValueError: mock_name all values must be dict + >>> _validate_dict({2: 0.5}, "mock_name",float, True) + Traceback (most recent call last): + ... + ValueError: mock_name all keys must be strings + >>> _validate_dict({"b": 4}, "mock_name", float,True) + Traceback (most recent call last): + ... + ValueError: mock_name nested dictionary all values must be float + """ + if not isinstance(_object, dict): + raise ValueError(f"{var_name} must be a dict") + if not all(isinstance(x, str) for x in _object): + raise ValueError(f"{var_name} all keys must be strings") + if not all(isinstance(x, value_type) for x in _object.values()): + nested_text = "nested dictionary " if nested else "" + raise ValueError( + f"{var_name} {nested_text}all values must be {value_type.__name__}" + ) + + +if __name__ == "__main__": + from doctest import testmod + + testmod() From 038f8a00e56bda8e8e2903fe4acf2ca7e3c83a57 Mon Sep 17 00:00:00 2001 From: sadiqebrahim <75269485+sadiqebrahim@users.noreply.github.com> Date: Sat, 29 Oct 2022 19:22:19 +0530 Subject: [PATCH 472/726] add electric conductivity algorithm (#7449) * add electric conductivity algorithm * Update electric_conductivity.py * Apply suggestions from code review Co-authored-by: Caeden Perelli-Harris * Update electric_conductivity.py * Update electric_conductivity.py * Update electric_conductivity.py * add algorithm Co-authored-by: Caeden Perelli-Harris --- electronics/electric_conductivity.py | 53 ++++++++++++++++++++++++++++ physics/sheer_stress.py | 51 ++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 electronics/electric_conductivity.py create mode 100644 physics/sheer_stress.py diff --git a/electronics/electric_conductivity.py b/electronics/electric_conductivity.py new file mode 100644 index 000000000..11f2a607d --- /dev/null +++ b/electronics/electric_conductivity.py @@ -0,0 +1,53 @@ +from __future__ import annotations + +ELECTRON_CHARGE = 1.6021e-19 # units = C + + +def electric_conductivity( + conductivity: float, + electron_conc: float, + mobility: float, +) -> tuple[str, float]: + """ + This function can calculate any one of the three - + 1. Conductivity + 2. Electron Concentration + 3. Electron Mobility + This is calculated from the other two provided values + Examples - + >>> electric_conductivity(conductivity=25, electron_conc=100, mobility=0) + ('mobility', 1.5604519068722301e+18) + >>> electric_conductivity(conductivity=0, electron_conc=1600, mobility=200) + ('conductivity', 5.12672e-14) + >>> electric_conductivity(conductivity=1000, electron_conc=0, mobility=1200) + ('electron_conc', 5.201506356240767e+18) + """ + if (conductivity, electron_conc, mobility).count(0) != 1: + raise ValueError("You cannot supply more or less than 2 values") + elif conductivity < 0: + raise ValueError("Conductivity cannot be negative") + elif electron_conc < 0: + raise ValueError("Electron concentration cannot be negative") + elif mobility < 0: + raise ValueError("mobility cannot be negative") + elif conductivity == 0: + return ( + "conductivity", + mobility * electron_conc * ELECTRON_CHARGE, + ) + elif electron_conc == 0: + return ( + "electron_conc", + conductivity / (mobility * ELECTRON_CHARGE), + ) + else: + return ( + "mobility", + conductivity / (electron_conc * ELECTRON_CHARGE), + ) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() diff --git a/physics/sheer_stress.py b/physics/sheer_stress.py new file mode 100644 index 000000000..74a2d36b1 --- /dev/null +++ b/physics/sheer_stress.py @@ -0,0 +1,51 @@ +from __future__ import annotations + + +def sheer_stress( + stress: float, + tangential_force: float, + area: float, +) -> tuple[str, float]: + """ + This function can calculate any one of the three - + 1. Sheer Stress + 2. Tangential Force + 3. Cross-sectional Area + This is calculated from the other two provided values + Examples - + >>> sheer_stress(stress=25, tangential_force=100, area=0) + ('area', 4.0) + >>> sheer_stress(stress=0, tangential_force=1600, area=200) + ('stress', 8.0) + >>> sheer_stress(stress=1000, tangential_force=0, area=1200) + ('tangential_force', 1200000) + """ + if (stress, tangential_force, area).count(0) != 1: + raise ValueError("You cannot supply more or less than 2 values") + elif stress < 0: + raise ValueError("Stress cannot be negative") + elif tangential_force < 0: + raise ValueError("Tangential Force cannot be negative") + elif area < 0: + raise ValueError("Area cannot be negative") + elif stress == 0: + return ( + "stress", + tangential_force / area, + ) + elif tangential_force == 0: + return ( + "tangential_force", + stress * area, + ) + else: + return ( + "area", + tangential_force / stress, + ) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From a02e7a1331583829b2768f02c4b9c412bf26251b Mon Sep 17 00:00:00 2001 From: Harsh Verma <53353745+TheLameOne@users.noreply.github.com> Date: Sat, 29 Oct 2022 19:24:32 +0530 Subject: [PATCH 473/726] Added algorithm for Text Justification in Strings (#7354) * Added algorithm for Text Justification in Strings * Added algorithm for Text Justification in Strings --- strings/text_justification.py | 92 +++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 strings/text_justification.py diff --git a/strings/text_justification.py b/strings/text_justification.py new file mode 100644 index 000000000..5e86456c2 --- /dev/null +++ b/strings/text_justification.py @@ -0,0 +1,92 @@ +def text_justification(word: str, max_width: int) -> list: + """ + Will format the string such that each line has exactly + (max_width) characters and is fully (left and right) justified, + and return the list of justified text. + + example 1: + string = "This is an example of text justification." + max_width = 16 + + output = ['This is an', + 'example of text', + 'justification. '] + + >>> text_justification("This is an example of text justification.", 16) + ['This is an', 'example of text', 'justification. '] + + example 2: + string = "Two roads diverged in a yellow wood" + max_width = 16 + output = ['Two roads', + 'diverged in a', + 'yellow wood '] + + >>> text_justification("Two roads diverged in a yellow wood", 16) + ['Two roads', 'diverged in a', 'yellow wood '] + + Time complexity: O(m*n) + Space complexity: O(m*n) + """ + + # Converting string into list of strings split by a space + words = word.split() + + def justify(line: list, width: int, max_width: int) -> str: + + overall_spaces_count = max_width - width + words_count = len(line) + if len(line) == 1: + # if there is only word in line + # just insert overall_spaces_count for the remainder of line + return line[0] + " " * overall_spaces_count + else: + spaces_to_insert_between_words = words_count - 1 + # num_spaces_between_words_list[i] : tells you to insert + # num_spaces_between_words_list[i] spaces + # after word on line[i] + num_spaces_between_words_list = spaces_to_insert_between_words * [ + overall_spaces_count // spaces_to_insert_between_words + ] + spaces_count_in_locations = ( + overall_spaces_count % spaces_to_insert_between_words + ) + # distribute spaces via round robin to the left words + for i in range(spaces_count_in_locations): + num_spaces_between_words_list[i] += 1 + aligned_words_list = [] + for i in range(spaces_to_insert_between_words): + # add the word + aligned_words_list.append(line[i]) + # add the spaces to insert + aligned_words_list.append(num_spaces_between_words_list[i] * " ") + # just add the last word to the sentence + aligned_words_list.append(line[-1]) + # join the aligned words list to form a justified line + return "".join(aligned_words_list) + + answer = [] + line: list[str] = [] + width = 0 + for word in words: + if width + len(word) + len(line) <= max_width: + # keep adding words until we can fill out max_width + # width = sum of length of all words (without overall_spaces_count) + # len(word) = length of current word + # len(line) = number of overall_spaces_count to insert between words + line.append(word) + width += len(word) + else: + # justify the line and add it to result + answer.append(justify(line, width, max_width)) + # reset new line and new width + line, width = [word], len(word) + remaining_spaces = max_width - width - len(line) + answer.append(" ".join(line) + (remaining_spaces + 1) * " ") + return answer + + +if __name__ == "__main__": + from doctest import testmod + + testmod() From d84452344ae1931c635245b1311a10e330223fc6 Mon Sep 17 00:00:00 2001 From: dmorozov001 <116645674+dmorozov001@users.noreply.github.com> Date: Sat, 29 Oct 2022 15:43:03 +0100 Subject: [PATCH 474/726] Correcting typos in CONTRIBUTING.md (#7845) --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b5a07af10..5cbb24e56 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ Welcome to [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python)! Befo ### Contributor -We are very happy that you consider implementing algorithms and data structures for others! This repository is referenced and used by learners from all over the globe. Being one of our contributors, you agree and confirm that: +We are very happy that you are considering implementing algorithms and data structures for others! This repository is referenced and used by learners from all over the globe. Being one of our contributors, you agree and confirm that: - You did your work - no plagiarism allowed - Any plagiarized work will not be merged. From bd50a3068270261fe845aac0daf309c7134e2477 Mon Sep 17 00:00:00 2001 From: Shashank Kashyap <50551759+SKVKPandey@users.noreply.github.com> Date: Sat, 29 Oct 2022 20:55:26 +0530 Subject: [PATCH 475/726] Resonant Frequency & Electrical Impedance (#6983) * Resonant Frequency * Resonant Frequency of LC Circuit * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update electronics/resonant_frequency.py Co-authored-by: Caeden * Update electronics/resonant_frequency.py Co-authored-by: Caeden * Update electronics/resonant_frequency.py Co-authored-by: Caeden * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Updated resonant_frequency.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update electronics/resonant_frequency.py Co-authored-by: Paul <56065602+ZeroDayOwl@users.noreply.github.com> * Fixed doctest issues in resonant_frequency.py * Algorithm for Electrical Impedance * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Updated Algorithm for Electrical Impedance * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update resonant_frequency.py * Update electrical_impedance.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update resonant_frequency.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update electronics/electrical_impedance.py Co-authored-by: Paul <56065602+ZeroDayOwl@users.noreply.github.com> * Update electronics/electrical_impedance.py Co-authored-by: Paul <56065602+ZeroDayOwl@users.noreply.github.com> * Update electronics/resonant_frequency.py Co-authored-by: Paul <56065602+ZeroDayOwl@users.noreply.github.com> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Caeden Co-authored-by: Paul <56065602+ZeroDayOwl@users.noreply.github.com> --- electronics/electrical_impedance.py | 46 ++++++++++++++++++++++++++ electronics/resonant_frequency.py | 50 +++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 electronics/electrical_impedance.py create mode 100644 electronics/resonant_frequency.py diff --git a/electronics/electrical_impedance.py b/electronics/electrical_impedance.py new file mode 100644 index 000000000..44041ff79 --- /dev/null +++ b/electronics/electrical_impedance.py @@ -0,0 +1,46 @@ +"""Electrical impedance is the measure of the opposition that a +circuit presents to a current when a voltage is applied. +Impedance extends the concept of resistance to alternating current (AC) circuits. +Source: https://en.wikipedia.org/wiki/Electrical_impedance +""" + +from __future__ import annotations + +from math import pow, sqrt + + +def electrical_impedance( + resistance: float, reactance: float, impedance: float +) -> dict[str, float]: + """ + Apply Electrical Impedance formula, on any two given electrical values, + which can be resistance, reactance, and impedance, and then in a Python dict + return name/value pair of the zero value. + + >>> electrical_impedance(3,4,0) + {'impedance': 5.0} + >>> electrical_impedance(0,4,5) + {'resistance': 3.0} + >>> electrical_impedance(3,0,5) + {'reactance': 4.0} + >>> electrical_impedance(3,4,5) + Traceback (most recent call last): + ... + ValueError: One and only one argument must be 0 + """ + if (resistance, reactance, impedance).count(0) != 1: + raise ValueError("One and only one argument must be 0") + if resistance == 0: + return {"resistance": sqrt(pow(impedance, 2) - pow(reactance, 2))} + elif reactance == 0: + return {"reactance": sqrt(pow(impedance, 2) - pow(resistance, 2))} + elif impedance == 0: + return {"impedance": sqrt(pow(resistance, 2) + pow(reactance, 2))} + else: + raise ValueError("Exactly one argument must be 0") + + +if __name__ == "__main__": + import doctest + + doctest.testmod() diff --git a/electronics/resonant_frequency.py b/electronics/resonant_frequency.py new file mode 100644 index 000000000..4f95043b6 --- /dev/null +++ b/electronics/resonant_frequency.py @@ -0,0 +1,50 @@ +# https://en.wikipedia.org/wiki/LC_circuit + +"""An LC circuit, also called a resonant circuit, tank circuit, or tuned circuit, +is an electric circuit consisting of an inductor, represented by the letter L, +and a capacitor, represented by the letter C, connected together. +The circuit can act as an electrical resonator, an electrical analogue of a +tuning fork, storing energy oscillating at the circuit's resonant frequency. +Source: https://en.wikipedia.org/wiki/LC_circuit +""" + +from __future__ import annotations + +from math import pi, sqrt + + +def resonant_frequency(inductance: float, capacitance: float) -> tuple: + """ + This function can calculate the resonant frequency of LC circuit, + for the given value of inductance and capacitnace. + + Examples are given below: + >>> resonant_frequency(inductance=10, capacitance=5) + ('Resonant frequency', 0.022507907903927652) + >>> resonant_frequency(inductance=0, capacitance=5) + Traceback (most recent call last): + ... + ValueError: Inductance cannot be 0 or negative + >>> resonant_frequency(inductance=10, capacitance=0) + Traceback (most recent call last): + ... + ValueError: Capacitance cannot be 0 or negative + """ + + if inductance <= 0: + raise ValueError("Inductance cannot be 0 or negative") + + elif capacitance <= 0: + raise ValueError("Capacitance cannot be 0 or negative") + + else: + return ( + "Resonant frequency", + float(1 / (2 * pi * (sqrt(inductance * capacitance)))), + ) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 47ddba1d914bf5955a244056e794e718dee9ead1 Mon Sep 17 00:00:00 2001 From: Kushagra Makharia Date: Sat, 29 Oct 2022 21:08:40 +0530 Subject: [PATCH 476/726] Added cosine similarity (#7001) * Added cosine similarity * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- machine_learning/similarity_search.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/machine_learning/similarity_search.py b/machine_learning/similarity_search.py index 2f5fc46c0..72979181f 100644 --- a/machine_learning/similarity_search.py +++ b/machine_learning/similarity_search.py @@ -12,6 +12,7 @@ from __future__ import annotations import math import numpy as np +from numpy.linalg import norm def euclidean(input_a: np.ndarray, input_b: np.ndarray) -> float: @@ -135,6 +136,22 @@ def similarity_search( return answer +def cosine_similarity(input_a: np.ndarray, input_b: np.ndarray) -> float: + """ + Calculates cosine similarity between two data. + :param input_a: ndarray of first vector. + :param input_b: ndarray of second vector. + :return: Cosine similarity of input_a and input_b. By using math.sqrt(), + result will be float. + + >>> cosine_similarity(np.array([1]), np.array([1])) + 1.0 + >>> cosine_similarity(np.array([1, 2]), np.array([6, 32])) + 0.9615239476408232 + """ + return np.dot(input_a, input_b) / (norm(input_a) * norm(input_b)) + + if __name__ == "__main__": import doctest From 1550731cb7457ddae216da2ffe0bc1587f5234f3 Mon Sep 17 00:00:00 2001 From: Andrey Date: Sat, 29 Oct 2022 23:45:21 +0300 Subject: [PATCH 477/726] Remove file-level flake8 suppression (#7844) * Remove file-level flake8 suppression * updating DIRECTORY.md * Fix tests Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 2 ++ data_structures/heap/binomial_heap.py | 50 +++++++++++++-------------- other/activity_selection.py | 8 ++--- searches/binary_tree_traversal.py | 10 +++--- 4 files changed, 34 insertions(+), 36 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 198cc7077..9ea8f3140 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -671,6 +671,7 @@ ## Physics * [Casimir Effect](physics/casimir_effect.py) + * [Centripetal Force](physics/centripetal_force.py) * [Horizontal Projectile Motion](physics/horizontal_projectile_motion.py) * [Kinetic Energy](physics/kinetic_energy.py) * [Lorentz Transformation Four Vector](physics/lorentz_transformation_four_vector.py) @@ -1069,6 +1070,7 @@ * [Is Palindrome](strings/is_palindrome.py) * [Is Pangram](strings/is_pangram.py) * [Is Spain National Id](strings/is_spain_national_id.py) + * [Is Srilankan Phone Number](strings/is_srilankan_phone_number.py) * [Jaro Winkler](strings/jaro_winkler.py) * [Join](strings/join.py) * [Knuth Morris Pratt](strings/knuth_morris_pratt.py) diff --git a/data_structures/heap/binomial_heap.py b/data_structures/heap/binomial_heap.py index 6398c9943..d79fac7a9 100644 --- a/data_structures/heap/binomial_heap.py +++ b/data_structures/heap/binomial_heap.py @@ -1,5 +1,3 @@ -# flake8: noqa - """ Binomial Heap Reference: Advanced Data Structures, Peter Brass @@ -22,7 +20,7 @@ class Node: self.right = None self.parent = None - def mergeTrees(self, other): + def merge_trees(self, other): """ In-place merge of two binomial trees of equal size. Returns the root of the resulting tree @@ -75,9 +73,8 @@ class BinomialHeap: 30 Deleting - delete() test - >>> for i in range(25): - ... print(first_heap.deleteMin(), end=" ") - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 + >>> [first_heap.delete_min() for _ in range(20)] + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] Create a new Heap >>> second_heap = BinomialHeap() @@ -97,8 +94,8 @@ class BinomialHeap: # # # # preOrder() test - >>> second_heap.preOrder() - [(17, 0), ('#', 1), (31, 1), (20, 2), ('#', 3), ('#', 3), (34, 2), ('#', 3), ('#', 3)] + >>> " ".join(str(x) for x in second_heap.pre_order()) + "(17, 0) ('#', 1) (31, 1) (20, 2) ('#', 3) ('#', 3) (34, 2) ('#', 3) ('#', 3)" printing Heap - __str__() test >>> print(second_heap) @@ -113,14 +110,17 @@ class BinomialHeap: ---# mergeHeaps() test - >>> merged = second_heap.mergeHeaps(first_heap) + >>> + >>> merged = second_heap.merge_heaps(first_heap) >>> merged.peek() 17 values in merged heap; (merge is inplace) - >>> while not first_heap.isEmpty(): - ... print(first_heap.deleteMin(), end=" ") - 17 20 25 26 27 28 29 31 34 + >>> results = [] + >>> while not first_heap.is_empty(): + ... results.append(first_heap.delete_min()) + >>> results + [17, 20, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 34] """ def __init__(self, bottom_root=None, min_node=None, heap_size=0): @@ -128,7 +128,7 @@ class BinomialHeap: self.bottom_root = bottom_root self.min_node = min_node - def mergeHeaps(self, other): + def merge_heaps(self, other): """ In-place merge of two binomial heaps. Both of them become the resulting merged heap @@ -180,7 +180,7 @@ class BinomialHeap: next_node = i.parent.parent # Merging trees - i = i.mergeTrees(i.parent) + i = i.merge_trees(i.parent) # Updating links i.left = previous_node @@ -238,7 +238,7 @@ class BinomialHeap: next_node = self.bottom_root.parent.parent # Merge - self.bottom_root = self.bottom_root.mergeTrees(self.bottom_root.parent) + self.bottom_root = self.bottom_root.merge_trees(self.bottom_root.parent) # Update Links self.bottom_root.parent = next_node @@ -252,10 +252,10 @@ class BinomialHeap: """ return self.min_node.val - def isEmpty(self): + def is_empty(self): return self.size == 0 - def deleteMin(self): + def delete_min(self): """ delete min element and return it """ @@ -317,7 +317,7 @@ class BinomialHeap: return min_value # Remaining cases # Construct heap of right subtree - newHeap = BinomialHeap( + new_heap = BinomialHeap( bottom_root=bottom_of_new, min_node=min_of_new, heap_size=size_of_new ) @@ -354,11 +354,11 @@ class BinomialHeap: self.min_node = i i = i.parent # Merge heaps - self.mergeHeaps(newHeap) + self.merge_heaps(new_heap) return min_value - def preOrder(self): + def pre_order(self): """ Returns the Pre-order representation of the heap including values of nodes plus their level distance from the root; @@ -369,9 +369,9 @@ class BinomialHeap: while top_root.parent: top_root = top_root.parent # preorder - heap_preOrder = [] - self.__traversal(top_root, heap_preOrder) - return heap_preOrder + heap_pre_order = [] + self.__traversal(top_root, heap_pre_order) + return heap_pre_order def __traversal(self, curr_node, preorder, level=0): """ @@ -389,9 +389,9 @@ class BinomialHeap: Overwriting str for a pre-order print of nodes in heap; Performance is poor, so use only for small examples """ - if self.isEmpty(): + if self.is_empty(): return "" - preorder_heap = self.preOrder() + preorder_heap = self.pre_order() return "\n".join(("-" * level + str(value)) for value, level in preorder_heap) diff --git a/other/activity_selection.py b/other/activity_selection.py index d809bf90a..18ff6a24c 100644 --- a/other/activity_selection.py +++ b/other/activity_selection.py @@ -1,5 +1,3 @@ -# flake8: noqa - """The following implementation assumes that the activities are already sorted according to their finish time""" @@ -10,11 +8,11 @@ single person, one at a time""" # finish[] --> An array that contains finish time of all activities -def printMaxActivities(start: list[int], finish: list[int]) -> None: +def print_max_activities(start: list[int], finish: list[int]) -> None: """ >>> start = [1, 3, 0, 5, 8, 5] >>> finish = [2, 4, 6, 7, 9, 9] - >>> printMaxActivities(start, finish) + >>> print_max_activities(start, finish) The following activities are selected: 0,1,3,4, """ @@ -43,4 +41,4 @@ if __name__ == "__main__": start = [1, 3, 0, 5, 8, 5] finish = [2, 4, 6, 7, 9, 9] - printMaxActivities(start, finish) + print_max_activities(start, finish) diff --git a/searches/binary_tree_traversal.py b/searches/binary_tree_traversal.py index 033db83d7..66814b478 100644 --- a/searches/binary_tree_traversal.py +++ b/searches/binary_tree_traversal.py @@ -1,5 +1,3 @@ -# flake8: noqa - """ This is pure Python implementation of tree traversal algorithms """ @@ -157,16 +155,16 @@ def level_order_actual(node: TreeNode) -> None: q: queue.Queue = queue.Queue() q.put(node) while not q.empty(): - list = [] + list_ = [] while not q.empty(): node_dequeued = q.get() print(node_dequeued.data, end=",") if node_dequeued.left: - list.append(node_dequeued.left) + list_.append(node_dequeued.left) if node_dequeued.right: - list.append(node_dequeued.right) + list_.append(node_dequeued.right) print() - for node in list: + for node in list_: q.put(node) From 3ec0aa85c0074d838d97dc030e582743586cd80e Mon Sep 17 00:00:00 2001 From: SparshRastogi <75373475+SparshRastogi@users.noreply.github.com> Date: Sun, 30 Oct 2022 02:54:59 +0530 Subject: [PATCH 478/726] Update kinetic_energy.py (#7848) Fixed a typo error in docstrings --- physics/kinetic_energy.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/physics/kinetic_energy.py b/physics/kinetic_energy.py index 8863919ac..77016e223 100644 --- a/physics/kinetic_energy.py +++ b/physics/kinetic_energy.py @@ -2,16 +2,16 @@ Find the kinetic energy of an object, given its mass and velocity. Description : In physics, the kinetic energy of an object is the energy that it -possesses due to its motion. It is defined as the work needed to accelerate a body of a -given mass from rest to its stated velocity. Having gained this energy during its -acceleration, the body maintains this kinetic energy unless its speed changes. The same +possesses due to its motion.It is defined as the work needed to accelerate a body of a +given mass from rest to its stated velocity.Having gained this energy during its +acceleration, the body maintains this kinetic energy unless its speed changes.The same amount of work is done by the body when decelerating from its current speed to a state -of rest. Formally, a kinetic energy is any term in a system's Lagrangian which includes +of rest.Formally, a kinetic energy is any term in a system's Lagrangian which includes a derivative with respect to time. In classical mechanics, the kinetic energy of a non-rotating object of mass m traveling -at a speed v is ½mv². In relativistic mechanics, this is a good approximation only when -v is much less than the speed of light. The standard unit of kinetic energy is the +at a speed v is ½mv².In relativistic mechanics, this is a good approximation only when +v is much less than the speed of light.The standard unit of kinetic energy is the joule, while the English unit of kinetic energy is the foot-pound. Reference : https://en.m.wikipedia.org/wiki/Kinetic_energy @@ -20,7 +20,7 @@ Reference : https://en.m.wikipedia.org/wiki/Kinetic_energy def kinetic_energy(mass: float, velocity: float) -> float: """ - Calculate kinetick energy. + Calculate kinetic energy. The kinetic energy of a non-rotating object of mass m traveling at a speed v is ½mv² From 7b7b3dd086eb3d8f6a82aa94b4398c0b95a7f186 Mon Sep 17 00:00:00 2001 From: Jason Devers <74424054+jdevers1@users.noreply.github.com> Date: Sun, 30 Oct 2022 01:20:07 -0400 Subject: [PATCH 479/726] matrix/count_paths.py (#7533) * added recursive dfs backtracking for count paths with doctests * fixed doc testing * added type hints * redefined r as row, c as col * fixed naming conventions, ran mypy, only tests that didn't pass were using List[], rathan list() * added another doctest, as well as a explanation above * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update matrix/count_paths.py Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> * Update matrix/count_paths.py Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Apply suggestions from code review Co-authored-by: Caeden Perelli-Harris Co-authored-by: J Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> Co-authored-by: Caeden Perelli-Harris --- matrix/count_paths.py | 75 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 matrix/count_paths.py diff --git a/matrix/count_paths.py b/matrix/count_paths.py new file mode 100644 index 000000000..4861ad5fd --- /dev/null +++ b/matrix/count_paths.py @@ -0,0 +1,75 @@ +""" +Given a grid, where you start from the top left position [0, 0], +you want to find how many paths you can take to get to the bottom right position. + +start here -> 0 0 0 0 + 1 1 0 0 + 0 0 0 1 + 0 1 0 0 <- finish here +how many 'distinct' paths can you take to get to the finish? +Using a recursive depth-first search algorithm below, you are able to +find the number of distinct unique paths (count). + +'*' will demonstrate a path +In the example above, there are two distinct paths: +1. 2. + * * * 0 * * * * + 1 1 * 0 1 1 * * + 0 0 * 1 0 0 * 1 + 0 1 * * 0 1 * * +""" + + +def depth_first_search(grid: list[list[int]], row: int, col: int, visit: set) -> int: + """ + Recursive Backtracking Depth First Search Algorithm + + Starting from top left of a matrix, count the number of + paths that can reach the bottom right of a matrix. + 1 represents a block (inaccessible) + 0 represents a valid space (accessible) + + 0 0 0 0 + 1 1 0 0 + 0 0 0 1 + 0 1 0 0 + >>> grid = [[0, 0, 0, 0], [1, 1, 0, 0], [0, 0, 0, 1], [0, 1, 0, 0]] + >>> depth_first_search(grid, 0, 0, set()) + 2 + + 0 0 0 0 0 + 0 1 1 1 0 + 0 1 1 1 0 + 0 0 0 0 0 + >>> grid = [[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0]] + >>> depth_first_search(grid, 0, 0, set()) + 2 + """ + row_length, col_length = len(grid), len(grid[0]) + if ( + min(row, col) < 0 + or row == row_length + or col == col_length + or (row, col) in visit + or grid[row][col] == 1 + ): + return 0 + if row == row_length - 1 and col == col_length - 1: + return 1 + + visit.add((row, col)) + + count = 0 + count += depth_first_search(grid, row + 1, col, visit) + count += depth_first_search(grid, row - 1, col, visit) + count += depth_first_search(grid, row, col + 1, visit) + count += depth_first_search(grid, row, col - 1, visit) + + visit.remove((row, col)) + return count + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 2d3985006f0c88e339a900caa4974493bc6fa861 Mon Sep 17 00:00:00 2001 From: Itssxxsalman <114142076+Itssxxsalman@users.noreply.github.com> Date: Sun, 30 Oct 2022 12:03:28 +0500 Subject: [PATCH 480/726] Fix grammatical mistakes in `simple_keyword_cypher.py` (#6385) * Fixed grammitical mistake * Update ciphers/simple_keyword_cypher.py Co-authored-by: Caeden Perelli-Harris Co-authored-by: Christian Clauss Co-authored-by: Caeden Perelli-Harris --- ciphers/simple_keyword_cypher.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ciphers/simple_keyword_cypher.py b/ciphers/simple_keyword_cypher.py index 447bacfc2..1635471ae 100644 --- a/ciphers/simple_keyword_cypher.py +++ b/ciphers/simple_keyword_cypher.py @@ -21,7 +21,7 @@ def create_cipher_map(key: str) -> dict[str, str]: :param key: keyword to use :return: dictionary cipher map """ - # Create alphabet list + # Create a list of the letters in the alphabet alphabet = [chr(i + 65) for i in range(26)] # Remove duplicate characters from key key = remove_duplicates(key.upper()) From f340bde6e047d86171385b90a023ac01e8914d0c Mon Sep 17 00:00:00 2001 From: Caio Cordeiro Date: Sun, 30 Oct 2022 04:05:44 -0300 Subject: [PATCH 481/726] Add simple neural network (#6452) * feat: add simple foward propagation implementation * fix: add PR requested changes * feat: add code example * fix: solve pre-commit failure * feat: add doctest inside code execution * fix: PR requested changes * fix: pr requested changes Co-authored-by: Caio Cordeiro --- neural_network/simple_neural_network.py | 63 +++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 neural_network/simple_neural_network.py diff --git a/neural_network/simple_neural_network.py b/neural_network/simple_neural_network.py new file mode 100644 index 000000000..f2a323487 --- /dev/null +++ b/neural_network/simple_neural_network.py @@ -0,0 +1,63 @@ +""" +Forward propagation explanation: +https://towardsdatascience.com/forward-propagation-in-neural-networks-simplified-math-and-code-version-bbcfef6f9250 +""" + +import math +import random + + +# Sigmoid +def sigmoid_function(value: float, deriv: bool = False) -> float: + """Return the sigmoid function of a float. + + >>> sigmoid_function(3.5) + 0.9706877692486436 + >>> sigmoid_function(3.5, True) + -8.75 + """ + if deriv: + return value * (1 - value) + return 1 / (1 + math.exp(-value)) + + +# Initial Value +INITIAL_VALUE = 0.02 + + +def forward_propagation(expected: int, number_propagations: int) -> float: + """Return the value found after the forward propagation training. + + >>> res = forward_propagation(32, 10000000) + >>> res > 31 and res < 33 + True + + >>> res = forward_propagation(32, 1000) + >>> res > 31 and res < 33 + False + """ + + # Random weight + weight = float(2 * (random.randint(1, 100)) - 1) + + for _ in range(number_propagations): + # Forward propagation + layer_1 = sigmoid_function(INITIAL_VALUE * weight) + # How much did we miss? + layer_1_error = (expected / 100) - layer_1 + # Error delta + layer_1_delta = layer_1_error * sigmoid_function(layer_1, True) + # Update weight + weight += INITIAL_VALUE * layer_1_delta + + return layer_1 * 100 + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + + expected = int(input("Expected value: ")) + number_propagations = int(input("Number of propagations: ")) + print(forward_propagation(expected, number_propagations)) From 0c5f1c01302c8208251f61730ba74e078bfd0ac8 Mon Sep 17 00:00:00 2001 From: ok-open-sc <114725648+ok-open-sc@users.noreply.github.com> Date: Sun, 30 Oct 2022 03:11:17 -0400 Subject: [PATCH 482/726] Increased Readability Of Variables (#6400) * Increased Readability Of Variables * Update anagrams.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update anagrams.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: Christian Clauss Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- strings/anagrams.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/strings/anagrams.py b/strings/anagrams.py index b671d3f3d..fb9ac0bd1 100644 --- a/strings/anagrams.py +++ b/strings/anagrams.py @@ -26,15 +26,15 @@ def anagram(my_word: str) -> list[str]: >>> anagram('final') ['final'] """ - return word_bysig[signature(my_word)] + return word_by_signature[signature(my_word)] data: str = Path(__file__).parent.joinpath("words.txt").read_text(encoding="utf-8") word_list = sorted({word.strip().lower() for word in data.splitlines()}) -word_bysig = collections.defaultdict(list) +word_by_signature = collections.defaultdict(list) for word in word_list: - word_bysig[signature(word)].append(word) + word_by_signature[signature(word)].append(word) if __name__ == "__main__": all_anagrams = {word: anagram(word) for word in word_list if len(anagram(word)) > 1} From f87de60b6d1cd6e9ce412503f48727015f46ada2 Mon Sep 17 00:00:00 2001 From: lostybtw <58177990+lostybtw@users.noreply.github.com> Date: Sun, 30 Oct 2022 07:22:52 +0000 Subject: [PATCH 483/726] fizzbuzz complete (#6504) * fizzbuzz * Update dynamic_programming/fizz_buzz.py Co-authored-by: Caeden * Update dynamic_programming/fizz_buzz.py Co-authored-by: Caeden * Update dynamic_programming/fizz_buzz.py Co-authored-by: Caeden * Update dynamic_programming/fizz_buzz.py Co-authored-by: Caeden * Update dynamic_programming/fizz_buzz.py Co-authored-by: Caeden * added doctests and function to fizzbuzz * Update fizz_buzz.py * Update fizz_buzz.py * Fixed FizzBuzz * fizzbuzz passing test * Update dynamic_programming/fizz_buzz.py Co-authored-by: Caeden * Update dynamic_programming/fizz_buzz.py Co-authored-by: Caeden * Update dynamic_programming/fizz_buzz.py Co-authored-by: Caeden * Update dynamic_programming/fizz_buzz.py Co-authored-by: Caeden * Update fizz_buzz.py * Update fizz_buzz.py * Update fizz_buzz.py * fixed fizzbuzz * Add files via upload * added mechanical energy calculation * Delete mechanical_energy.py * Update fizz_buzz.py * Update dynamic_programming/fizz_buzz.py Co-authored-by: Christian Clauss * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update fizz_buzz.py Co-authored-by: Caeden Co-authored-by: Christian Clauss Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- dynamic_programming/fizz_buzz.py | 65 ++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 dynamic_programming/fizz_buzz.py diff --git a/dynamic_programming/fizz_buzz.py b/dynamic_programming/fizz_buzz.py new file mode 100644 index 000000000..dd1d21b10 --- /dev/null +++ b/dynamic_programming/fizz_buzz.py @@ -0,0 +1,65 @@ +# https://en.wikipedia.org/wiki/Fizz_buzz#Programming + + +def fizz_buzz(number: int, iterations: int) -> str: + """ + Plays FizzBuzz. + Prints Fizz if number is a multiple of 3. + Prints Buzz if its a multiple of 5. + Prints FizzBuzz if its a multiple of both 3 and 5 or 15. + Else Prints The Number Itself. + >>> fizz_buzz(1,7) + '1 2 Fizz 4 Buzz Fizz 7 ' + >>> fizz_buzz(1,0) + Traceback (most recent call last): + ... + ValueError: Iterations must be done more than 0 times to play FizzBuzz + >>> fizz_buzz(-5,5) + Traceback (most recent call last): + ... + ValueError: starting number must be + and integer and be more than 0 + >>> fizz_buzz(10,-5) + Traceback (most recent call last): + ... + ValueError: Iterations must be done more than 0 times to play FizzBuzz + >>> fizz_buzz(1.5,5) + Traceback (most recent call last): + ... + ValueError: starting number must be + and integer and be more than 0 + >>> fizz_buzz(1,5.5) + Traceback (most recent call last): + ... + ValueError: iterations must be defined as integers + """ + + if not type(iterations) == int: + raise ValueError("iterations must be defined as integers") + if not type(number) == int or not number >= 1: + raise ValueError( + """starting number must be + and integer and be more than 0""" + ) + if not iterations >= 1: + raise ValueError("Iterations must be done more than 0 times to play FizzBuzz") + + out = "" + while number <= iterations: + if number % 3 == 0: + out += "Fizz" + if number % 5 == 0: + out += "Buzz" + if not number % 3 == 0 and not number % 5 == 0: + out += str(number) + + # print(out) + number += 1 + out += " " + return out + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 17d93cab783095dd1def3c382866cd94296db455 Mon Sep 17 00:00:00 2001 From: Carlos Villar Date: Sun, 30 Oct 2022 10:00:47 +0100 Subject: [PATCH 484/726] Added Manhattan distance algorithm (#7790) * Added Manhattan distance algorithm, Fixes: #7776 * Forgot that isinstance can accept a tuple * Apply suggestions from code review * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update manhattan_distance.py * Update manhattan_distance.py Co-authored-by: Christian Clauss Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/manhattan_distance.py | 126 ++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 maths/manhattan_distance.py diff --git a/maths/manhattan_distance.py b/maths/manhattan_distance.py new file mode 100644 index 000000000..2711d4c8c --- /dev/null +++ b/maths/manhattan_distance.py @@ -0,0 +1,126 @@ +def manhattan_distance(point_a: list, point_b: list) -> float: + """ + Expectts two list of numbers representing two points in the same + n-dimensional space + + https://en.wikipedia.org/wiki/Taxicab_geometry + + >>> manhattan_distance([1,1], [2,2]) + 2.0 + >>> manhattan_distance([1.5,1.5], [2,2]) + 1.0 + >>> manhattan_distance([1.5,1.5], [2.5,2]) + 1.5 + >>> manhattan_distance([-3, -3, -3], [0, 0, 0]) + 9.0 + >>> manhattan_distance([1,1], None) + Traceback (most recent call last): + ... + ValueError: Missing an input + >>> manhattan_distance([1,1], [2, 2, 2]) + Traceback (most recent call last): + ... + ValueError: Both points must be in the same n-dimensional space + >>> manhattan_distance([1,"one"], [2, 2, 2]) + Traceback (most recent call last): + ... + TypeError: Expected a list of numbers as input, found str + >>> manhattan_distance(1, [2, 2, 2]) + Traceback (most recent call last): + ... + TypeError: Expected a list of numbers as input, found int + >>> manhattan_distance([1,1], "not_a_list") + Traceback (most recent call last): + ... + TypeError: Expected a list of numbers as input, found str + """ + + _validate_point(point_a) + _validate_point(point_b) + if len(point_a) != len(point_b): + raise ValueError("Both points must be in the same n-dimensional space") + + return float(sum(abs(a - b) for a, b in zip(point_a, point_b))) + + +def _validate_point(point: list[float]) -> None: + """ + >>> _validate_point(None) + Traceback (most recent call last): + ... + ValueError: Missing an input + >>> _validate_point([1,"one"]) + Traceback (most recent call last): + ... + TypeError: Expected a list of numbers as input, found str + >>> _validate_point(1) + Traceback (most recent call last): + ... + TypeError: Expected a list of numbers as input, found int + >>> _validate_point("not_a_list") + Traceback (most recent call last): + ... + TypeError: Expected a list of numbers as input, found str + """ + if point: + if isinstance(point, list): + for item in point: + if not isinstance(item, (int, float)): + raise TypeError( + f"Expected a list of numbers as input, " + f"found {type(item).__name__}" + ) + else: + raise TypeError( + f"Expected a list of numbers as input, found {type(point).__name__}" + ) + else: + raise ValueError("Missing an input") + + +def manhattan_distance_one_liner(point_a: list, point_b: list) -> float: + """ + Version with one liner + + >>> manhattan_distance_one_liner([1,1], [2,2]) + 2.0 + >>> manhattan_distance_one_liner([1.5,1.5], [2,2]) + 1.0 + >>> manhattan_distance_one_liner([1.5,1.5], [2.5,2]) + 1.5 + >>> manhattan_distance_one_liner([-3, -3, -3], [0, 0, 0]) + 9.0 + >>> manhattan_distance_one_liner([1,1], None) + Traceback (most recent call last): + ... + ValueError: Missing an input + >>> manhattan_distance_one_liner([1,1], [2, 2, 2]) + Traceback (most recent call last): + ... + ValueError: Both points must be in the same n-dimensional space + >>> manhattan_distance_one_liner([1,"one"], [2, 2, 2]) + Traceback (most recent call last): + ... + TypeError: Expected a list of numbers as input, found str + >>> manhattan_distance_one_liner(1, [2, 2, 2]) + Traceback (most recent call last): + ... + TypeError: Expected a list of numbers as input, found int + >>> manhattan_distance_one_liner([1,1], "not_a_list") + Traceback (most recent call last): + ... + TypeError: Expected a list of numbers as input, found str + """ + + _validate_point(point_a) + _validate_point(point_b) + if len(point_a) != len(point_b): + raise ValueError("Both points must be in the same n-dimensional space") + + return float(sum(abs(x - y) for x, y in zip(point_a, point_b))) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 57ccabbaeb0f32165271e3a218bc9c6dcfc21823 Mon Sep 17 00:00:00 2001 From: Andrey Date: Sun, 30 Oct 2022 11:01:58 +0200 Subject: [PATCH 485/726] Update docs (#7867) * Update docs, remove unused excludes from pre-commit * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ---- CONTRIBUTING.md | 2 +- DIRECTORY.md | 12 ++++++++++++ 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 56946f5f2..004def5e4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,10 +7,6 @@ repos: - id: end-of-file-fixer types: [python] - id: trailing-whitespace - exclude: | - (?x)^( - data_structures/heap/binomial_heap.py - )$ - id: requirements-txt-fixer - repo: https://github.com/MarcoGorelli/auto-walrus diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5cbb24e56..37e020b8f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -66,7 +66,7 @@ pre-commit run --all-files --show-diff-on-failure We want your work to be readable by others; therefore, we encourage you to note the following: -- Please write in Python 3.9+. For instance: `print()` is a function in Python 3 so `print "Hello"` will *not* work but `print("Hello")` will. +- Please write in Python 3.10+. For instance: `print()` is a function in Python 3 so `print "Hello"` will *not* work but `print("Hello")` will. - Please focus hard on the naming of functions, classes, and variables. Help your reader by using __descriptive names__ that can help you to remove redundant comments. - Single letter variable names are *old school* so please avoid them unless their life only spans a few lines. - Expand acronyms because `gcd()` is hard to understand but `greatest_common_divisor()` is not. diff --git a/DIRECTORY.md b/DIRECTORY.md index 9ea8f3140..8ac9c3be7 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -158,6 +158,8 @@ * [Weight Conversion](conversions/weight_conversion.py) ## Data Structures + * Arrays + * [Permutations](data_structures/arrays/permutations.py) * Binary Tree * [Avl Tree](data_structures/binary_tree/avl_tree.py) * [Basic Binary Tree](data_structures/binary_tree/basic_binary_tree.py) @@ -291,6 +293,7 @@ * [Factorial](dynamic_programming/factorial.py) * [Fast Fibonacci](dynamic_programming/fast_fibonacci.py) * [Fibonacci](dynamic_programming/fibonacci.py) + * [Fizz Buzz](dynamic_programming/fizz_buzz.py) * [Floyd Warshall](dynamic_programming/floyd_warshall.py) * [Integer Partition](dynamic_programming/integer_partition.py) * [Iterating Through Submasks](dynamic_programming/iterating_through_submasks.py) @@ -313,12 +316,16 @@ * [Rod Cutting](dynamic_programming/rod_cutting.py) * [Subset Generation](dynamic_programming/subset_generation.py) * [Sum Of Subset](dynamic_programming/sum_of_subset.py) + * [Viterbi](dynamic_programming/viterbi.py) ## Electronics * [Carrier Concentration](electronics/carrier_concentration.py) * [Coulombs Law](electronics/coulombs_law.py) + * [Electric Conductivity](electronics/electric_conductivity.py) * [Electric Power](electronics/electric_power.py) + * [Electrical Impedance](electronics/electrical_impedance.py) * [Ohms Law](electronics/ohms_law.py) + * [Resonant Frequency](electronics/resonant_frequency.py) ## File Transfer * [Receive File](file_transfer/receive_file.py) @@ -430,6 +437,7 @@ ## Knapsack * [Greedy Knapsack](knapsack/greedy_knapsack.py) * [Knapsack](knapsack/knapsack.py) + * [Recursive Approach Knapsack](knapsack/recursive_approach_knapsack.py) * Tests * [Test Greedy Knapsack](knapsack/tests/test_greedy_knapsack.py) * [Test Knapsack](knapsack/tests/test_knapsack.py) @@ -622,6 +630,7 @@ ## Matrix * [Binary Search Matrix](matrix/binary_search_matrix.py) * [Count Islands In Matrix](matrix/count_islands_in_matrix.py) + * [Count Paths](matrix/count_paths.py) * [Cramers Rule 2X2](matrix/cramers_rule_2x2.py) * [Inverse Of Matrix](matrix/inverse_of_matrix.py) * [Largest Square Area In Matrix](matrix/largest_square_area_in_matrix.py) @@ -645,6 +654,7 @@ * [Back Propagation Neural Network](neural_network/back_propagation_neural_network.py) * [Convolution Neural Network](neural_network/convolution_neural_network.py) * [Perceptron](neural_network/perceptron.py) + * [Simple Neural Network](neural_network/simple_neural_network.py) ## Other * [Activity Selection](other/activity_selection.py) @@ -680,6 +690,7 @@ * [Newtons Law Of Gravitation](physics/newtons_law_of_gravitation.py) * [Newtons Second Law Of Motion](physics/newtons_second_law_of_motion.py) * [Potential Energy](physics/potential_energy.py) + * [Sheer Stress](physics/sheer_stress.py) ## Project Euler * Problem 001 @@ -1089,6 +1100,7 @@ * [Reverse Words](strings/reverse_words.py) * [Snake Case To Camel Pascal Case](strings/snake_case_to_camel_pascal_case.py) * [Split](strings/split.py) + * [Text Justification](strings/text_justification.py) * [Upper](strings/upper.py) * [Wave](strings/wave.py) * [Wildcard Pattern Matching](strings/wildcard_pattern_matching.py) From 5ba5c548584f44bac0bc3c0cb4e95233560627cf Mon Sep 17 00:00:00 2001 From: Sushant Srivastav <63559772+sushant4191@users.noreply.github.com> Date: Sun, 30 Oct 2022 14:38:54 +0530 Subject: [PATCH 486/726] Updated info (#7866) * Updated info Updated the readme section for sorts. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update sorts/README.md Co-authored-by: Caeden Perelli-Harris * Update README.md Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Caeden Perelli-Harris Co-authored-by: Christian Clauss --- sorts/README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 sorts/README.md diff --git a/sorts/README.md b/sorts/README.md new file mode 100644 index 000000000..ceb0207c2 --- /dev/null +++ b/sorts/README.md @@ -0,0 +1,11 @@ +# Sorting Algorithms +Sorting is the process of putting data in a specific order. The way to arrange data in a specific order +is specified by the sorting algorithm. The most typical orders are lexical or numerical. The significance +of sorting lies in the fact that, if data is stored in a sorted manner, data searching can be highly optimised. +Another use for sorting is to represent data in a more readable manner. + +This section contains a lot of important algorithms that helps us to use sorting algorithms in various scenarios. +## References +* +* +* From 87a5d919761e9ccb05e19e68a5307348c6264cd0 Mon Sep 17 00:00:00 2001 From: Kevin Joven <59969678+KevinJoven11@users.noreply.github.com> Date: Sun, 30 Oct 2022 05:49:33 -0400 Subject: [PATCH 487/726] quantum_teleportation.py (#6632) * quantum_teleportation.py This code is for the #Hacktoberfest. This file run the quantum teleportation circuit using Qiskit. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update quantum/quantum_teleportation.py Co-authored-by: Caeden * Update quantum/quantum_teleportation.py Co-authored-by: Caeden * Update Corrected some typos. Add more comments for adding the gates. Update the variable qc with quantum_circuit in the simulator and execute. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * python return typehint solved. * Fix long line Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Caeden Co-authored-by: Christian Clauss --- quantum/quantum_teleportation.py | 70 ++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 quantum/quantum_teleportation.py diff --git a/quantum/quantum_teleportation.py b/quantum/quantum_teleportation.py new file mode 100644 index 000000000..5fbc57a66 --- /dev/null +++ b/quantum/quantum_teleportation.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +""" +Build quantum teleportation circuit using three quantum bits +and 1 classical bit. The main idea is to send one qubit from +Alice to Bob using the entanglement properties. This experiment +run in IBM Q simulator with 1000 shots. +. +References: +https://en.wikipedia.org/wiki/Quantum_teleportation +https://qiskit.org/textbook/ch-algorithms/teleportation.html +""" + +import numpy as np +import qiskit +from qiskit import Aer, ClassicalRegister, QuantumCircuit, QuantumRegister, execute + + +def quantum_teleportation( + theta: float = np.pi / 2, phi: float = np.pi / 2, lam: float = np.pi / 2 +) -> qiskit.result.counts.Counts: + + """ + # >>> quantum_teleportation() + #{'00': 500, '11': 500} # ideally + # ┌─────────────────┐ ┌───┐ + #qr_0: ┤ U(π/2,π/2,π/2) ├───────■──┤ H ├─■───────── + # └──────┬───┬──────┘ ┌─┴─┐└───┘ │ + #qr_1: ───────┤ H ├─────────■──┤ X ├──────┼───■───── + # └───┘ ┌─┴─┐└───┘ │ ┌─┴─┐┌─┐ + #qr_2: ───────────────────┤ X ├───────────■─┤ X ├┤M├ + # └───┘ └───┘└╥┘ + #cr: 1/═══════════════════════════════════════════╩═ + Args: + theta (float): Single qubit rotation U Gate theta parameter. Default to np.pi/2 + phi (float): Single qubit rotation U Gate phi parameter. Default to np.pi/2 + lam (float): Single qubit rotation U Gate lam parameter. Default to np.pi/2 + Returns: + qiskit.result.counts.Counts: Teleported qubit counts. + """ + + qr = QuantumRegister(3, "qr") # Define the number of quantum bits + cr = ClassicalRegister(1, "cr") # Define the number of classical bits + + quantum_circuit = QuantumCircuit(qr, cr) # Define the quantum circuit. + + # Build the circuit + quantum_circuit.u(theta, phi, lam, 0) # Quantum State to teleport + quantum_circuit.h(1) # add hadamard gate + quantum_circuit.cx( + 1, 2 + ) # add control gate with qubit 1 as control and 2 as target. + quantum_circuit.cx(0, 1) + quantum_circuit.h(0) + quantum_circuit.cz(0, 2) # add control z gate. + quantum_circuit.cx(1, 2) + + quantum_circuit.measure([2], [0]) # measure the qubit. + + # Simulate the circuit using qasm simulator + backend = Aer.get_backend("qasm_simulator") + job = execute(quantum_circuit, backend, shots=1000) + + return job.result().get_counts(quantum_circuit) + + +if __name__ == "__main__": + print( + "Total count for teleported state is: " + f"{quantum_teleportation(np.pi/2, np.pi/2, np.pi/2)}" + ) From 00dfad9d20abf755a91abc0ba35f5d92fcab9149 Mon Sep 17 00:00:00 2001 From: giladwo <25708271+giladwo@users.noreply.github.com> Date: Sun, 30 Oct 2022 11:59:10 +0200 Subject: [PATCH 488/726] Simplify climbing stairs and use constant memory (#6628) * Simplify climbing stairs and use constant memory * number_of_steps Co-authored-by: Christian Clauss --- dynamic_programming/climbing_stairs.py | 29 +++++++++++++------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/dynamic_programming/climbing_stairs.py b/dynamic_programming/climbing_stairs.py index 048d57aed..d6273d025 100644 --- a/dynamic_programming/climbing_stairs.py +++ b/dynamic_programming/climbing_stairs.py @@ -1,20 +1,20 @@ #!/usr/bin/env python3 -def climb_stairs(n: int) -> int: +def climb_stairs(number_of_steps: int) -> int: """ LeetCdoe No.70: Climbing Stairs - Distinct ways to climb a n step staircase where - each time you can either climb 1 or 2 steps. + Distinct ways to climb a number_of_steps staircase where each time you can either + climb 1 or 2 steps. Args: - n: number of steps of staircase + number_of_steps: number of steps on the staircase Returns: - Distinct ways to climb a n step staircase + Distinct ways to climb a number_of_steps staircase Raises: - AssertionError: n not positive integer + AssertionError: number_of_steps not positive integer >>> climb_stairs(3) 3 @@ -23,18 +23,17 @@ def climb_stairs(n: int) -> int: >>> climb_stairs(-7) # doctest: +ELLIPSIS Traceback (most recent call last): ... - AssertionError: n needs to be positive integer, your input -7 + AssertionError: number_of_steps needs to be positive integer, your input -7 """ assert ( - isinstance(n, int) and n > 0 - ), f"n needs to be positive integer, your input {n}" - if n == 1: + isinstance(number_of_steps, int) and number_of_steps > 0 + ), f"number_of_steps needs to be positive integer, your input {number_of_steps}" + if number_of_steps == 1: return 1 - dp = [0] * (n + 1) - dp[0], dp[1] = (1, 1) - for i in range(2, n + 1): - dp[i] = dp[i - 1] + dp[i - 2] - return dp[n] + previous, current = 1, 1 + for _ in range(number_of_steps - 1): + current, previous = current + previous, current + return current if __name__ == "__main__": From 84facb78b20be6a9a90307c79e318c65a04987ac Mon Sep 17 00:00:00 2001 From: Saksham1970 <45041294+Saksham1970@users.noreply.github.com> Date: Sun, 30 Oct 2022 15:40:16 +0530 Subject: [PATCH 489/726] Project Euler: 092 decreased the time (#6627) * Added explanation and increased speed of the solution of problem 092 * updating DIRECTORY.md * Added temporary fix to the failing of problem 104 * Reduced few seconds by minor improvements * Update sol.py Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss --- project_euler/problem_092/sol1.py | 42 +++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/project_euler/problem_092/sol1.py b/project_euler/problem_092/sol1.py index d326fc33f..33a6c0694 100644 --- a/project_euler/problem_092/sol1.py +++ b/project_euler/problem_092/sol1.py @@ -11,11 +11,11 @@ What is most amazing is that EVERY starting number will eventually arrive at 1 o How many starting numbers below ten million will arrive at 89? """ - -DIGITS_SQUARED = [digit**2 for digit in range(10)] +DIGITS_SQUARED = [sum(int(c, 10) ** 2 for c in i.__str__()) for i in range(100000)] def next_number(number: int) -> int: + """ Returns the next number of the chain by adding the square of each digit to form a new number. @@ -28,15 +28,29 @@ def next_number(number: int) -> int: >>> next_number(32) 13 """ + sum_of_digits_squared = 0 while number: - sum_of_digits_squared += DIGITS_SQUARED[number % 10] - number //= 10 + + # Increased Speed Slightly by checking every 5 digits together. + sum_of_digits_squared += DIGITS_SQUARED[number % 100000] + number //= 100000 return sum_of_digits_squared -CHAINS = {1: True, 58: False} +# There are 2 Chains made, +# One ends with 89 with the chain member 58 being the one which when declared first, +# there will be the least number of iterations for all the members to be checked. + +# The other one ends with 1 and has only one element 1. + +# So 58 and 1 are chosen to be declared at the starting. + +# Changed dictionary to an array to quicken the solution +CHAINS: list[bool | None] = [None] * 10000000 +CHAINS[0] = True +CHAINS[57] = False def chain(number: int) -> bool: @@ -54,11 +68,16 @@ def chain(number: int) -> bool: >>> chain(1) True """ - if number in CHAINS: - return CHAINS[number] + + if CHAINS[number - 1] is not None: + return CHAINS[number - 1] # type: ignore number_chain = chain(next_number(number)) - CHAINS[number] = number_chain + CHAINS[number - 1] = number_chain + + while number < 10000000: + CHAINS[number - 1] = number_chain + number *= 10 return number_chain @@ -74,12 +93,15 @@ def solution(number: int = 10000000) -> int: >>> solution(10000000) 8581146 """ - return sum(1 for i in range(1, number) if not chain(i)) + for i in range(1, number): + if CHAINS[i] is None: + chain(i + 1) + + return CHAINS[:number].count(False) if __name__ == "__main__": import doctest doctest.testmod() - print(f"{solution() = }") From 48a73a28d477a1b634479001bc04e0886b265bfb Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Sun, 30 Oct 2022 10:11:29 +0000 Subject: [PATCH 490/726] fix(quantum): Correct simulator deprecation (#7869) --- quantum/quantum_teleportation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quantum/quantum_teleportation.py b/quantum/quantum_teleportation.py index 5fbc57a66..d04b44d15 100644 --- a/quantum/quantum_teleportation.py +++ b/quantum/quantum_teleportation.py @@ -57,7 +57,7 @@ def quantum_teleportation( quantum_circuit.measure([2], [0]) # measure the qubit. # Simulate the circuit using qasm simulator - backend = Aer.get_backend("qasm_simulator") + backend = Aer.get_backend("aer_simulator") job = execute(quantum_circuit, backend, shots=1000) return job.result().get_counts(quantum_circuit) From ba576a9a0b0a41405cfa11606c39908a1bc2b01b Mon Sep 17 00:00:00 2001 From: Devesh Swarnkar <71492529+devesh-0419@users.noreply.github.com> Date: Sun, 30 Oct 2022 15:44:02 +0530 Subject: [PATCH 491/726] Create README.md (#6642) for blockchain file --- blockchain/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 blockchain/README.md diff --git a/blockchain/README.md b/blockchain/README.md new file mode 100644 index 000000000..5ae7f95ec --- /dev/null +++ b/blockchain/README.md @@ -0,0 +1,8 @@ +# Blockchain + +A Blockchain is a type of distributed ledger technology (DLT) that consists of growing list of records, called blocks, that are securely linked together using cryptography. + +* +* +* +* From ca923389c0330b6b7afc935bdd7fa9a15d377079 Mon Sep 17 00:00:00 2001 From: Si Lam Date: Sun, 30 Oct 2022 05:25:51 -0500 Subject: [PATCH 492/726] Description of Double hasing (#6467) * Description of DOuble hasing * Fix sheebang * Update double_hash.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update double_hash.py Co-authored-by: Christian Clauss Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- data_structures/hashing/double_hash.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/data_structures/hashing/double_hash.py b/data_structures/hashing/double_hash.py index bd1355fca..453e0d131 100644 --- a/data_structures/hashing/double_hash.py +++ b/data_structures/hashing/double_hash.py @@ -1,4 +1,16 @@ #!/usr/bin/env python3 +""" +Double hashing is a collision resolving technique in Open Addressed Hash tables. +Double hashing uses the idea of applying a second hash function to key when a collision +occurs. The advantage of Double hashing is that it is one of the best form of probing, +producing a uniform distribution of records throughout a hash table. This technique +does not yield any clusters. It is one of effective method for resolving collisions. + +Double hashing can be done using: (hash1(key) + i * hash2(key)) % TABLE_SIZE +Where hash1() and hash2() are hash functions and TABLE_SIZE is size of hash table. + +Reference: https://en.wikipedia.org/wiki/Double_hashing +""" from .hash_table import HashTable from .number_theory.prime_numbers import is_prime, next_prime From c0b0b128b7ad4a5a75ed866bc7c114c3cf7a89ef Mon Sep 17 00:00:00 2001 From: Kavienan J <45987371+kavienanj@users.noreply.github.com> Date: Sun, 30 Oct 2022 15:56:46 +0530 Subject: [PATCH 493/726] Add Ideal Gas Law for physics (#6503) * add physics ideal gas law * run pre commit * Update physics/ideal_gas_law.py Suggestion #1 Co-authored-by: Caeden * Update physics/ideal_gas_law.py Suggestion #2 Co-authored-by: Caeden * run pre commit * Update volume return line sugesstion Co-authored-by: Caeden Perelli-Harris * Add suggestions * Apply suggestions from code review Co-authored-by: Caeden Perelli-Harris Co-authored-by: Caeden Co-authored-by: Christian Clauss --- physics/ideal_gas_law.py | 59 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 physics/ideal_gas_law.py diff --git a/physics/ideal_gas_law.py b/physics/ideal_gas_law.py new file mode 100644 index 000000000..805da47b0 --- /dev/null +++ b/physics/ideal_gas_law.py @@ -0,0 +1,59 @@ +""" +The ideal gas law, also called the general gas equation, is the +equation of state of a hypothetical ideal gas. It is a good approximation +of the behavior of many gases under many conditions, although it has +several limitations. It was first stated by Benoît Paul Émile Clapeyron +in 1834 as a combination of the empirical Boyle's law, Charles's law, +Avogadro's law, and Gay-Lussac's law.[1] The ideal gas law is often written +in an empirical form: + ------------ + | PV = nRT | + ------------ +P = Pressure (Pa) +V = Volume (m^3) +n = Amount of substance (mol) +R = Universal gas constant +T = Absolute temperature (Kelvin) + +(Description adapted from https://en.wikipedia.org/wiki/Ideal_gas_law ) +""" + +UNIVERSAL_GAS_CONSTANT = 8.314462 # Unit - J mol-1 K-1 + + +def pressure_of_gas_system(moles: float, kelvin: float, volume: float) -> float: + """ + >>> pressure_of_gas_system(2, 100, 5) + 332.57848 + >>> pressure_of_gas_system(0.5, 273, 0.004) + 283731.01575 + >>> pressure_of_gas_system(3, -0.46, 23.5) + Traceback (most recent call last): + ... + ValueError: Invalid inputs. Enter positive value. + """ + if moles < 0 or kelvin < 0 or volume < 0: + raise ValueError("Invalid inputs. Enter positive value.") + return moles * kelvin * UNIVERSAL_GAS_CONSTANT / volume + + +def volume_of_gas_system(moles: float, kelvin: float, pressure: float) -> float: + """ + >>> volume_of_gas_system(2, 100, 5) + 332.57848 + >>> volume_of_gas_system(0.5, 273, 0.004) + 283731.01575 + >>> volume_of_gas_system(3, -0.46, 23.5) + Traceback (most recent call last): + ... + ValueError: Invalid inputs. Enter positive value. + """ + if moles < 0 or kelvin < 0 or pressure < 0: + raise ValueError("Invalid inputs. Enter positive value.") + return moles * kelvin * UNIVERSAL_GAS_CONSTANT / pressure + + +if __name__ == "__main__": + from doctest import testmod + + testmod() From b32903d22f3a0fc8985a3dd1e4c4645f12b9f961 Mon Sep 17 00:00:00 2001 From: Kavienan J <45987371+kavienanj@users.noreply.github.com> Date: Sun, 30 Oct 2022 15:59:00 +0530 Subject: [PATCH 494/726] Add root mean square speed of gas molecules to physics (#6569) * add rms speed of molecule to physics * Update physics/rms_speed_of_molecule.py Co-authored-by: Caeden Perelli-Harris Co-authored-by: Christian Clauss Co-authored-by: Caeden Perelli-Harris --- physics/rms_speed_of_molecule.py | 52 ++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 physics/rms_speed_of_molecule.py diff --git a/physics/rms_speed_of_molecule.py b/physics/rms_speed_of_molecule.py new file mode 100644 index 000000000..478cee01c --- /dev/null +++ b/physics/rms_speed_of_molecule.py @@ -0,0 +1,52 @@ +""" +The root-mean-square speed is essential in measuring the average speed of particles +contained in a gas, defined as, + ----------------- + | Vrms = √3RT/M | + ----------------- + +In Kinetic Molecular Theory, gasified particles are in a condition of constant random +motion; each particle moves at a completely different pace, perpetually clashing and +changing directions consistently velocity is used to describe the movement of gas +particles, thereby taking into account both speed and direction. Although the velocity +of gaseous particles is constantly changing, the distribution of velocities does not +change. +We cannot gauge the velocity of every individual particle, thus we frequently reason +in terms of the particles average behavior. Particles moving in opposite directions +have velocities of opposite signs. Since gas particles are in random motion, it's +plausible that there'll be about as several moving in one direction as within the other +way, which means that the average velocity for a collection of gas particles equals +zero; as this value is unhelpful, the average of velocities can be determined using an +alternative method. +""" + + +UNIVERSAL_GAS_CONSTANT = 8.3144598 + + +def rms_speed_of_molecule(temperature: float, molar_mass: float) -> float: + """ + >>> rms_speed_of_molecule(100, 2) + 35.315279554323226 + >>> rms_speed_of_molecule(273, 12) + 23.821458421977443 + """ + if temperature < 0: + raise Exception("Temperature cannot be less than 0 K") + if molar_mass <= 0: + raise Exception("Molar mass cannot be less than or equal to 0 kg/mol") + else: + return (3 * UNIVERSAL_GAS_CONSTANT * temperature / molar_mass) ** 0.5 + + +if __name__ == "__main__": + import doctest + + # run doctest + doctest.testmod() + + # example + temperature = 300 + molar_mass = 28 + vrms = rms_speed_of_molecule(temperature, molar_mass) + print(f"Vrms of Nitrogen gas at 300 K is {vrms} m/s") From fcfe35c3d8ed15037c0f20e3ee2268eea840b1ff Mon Sep 17 00:00:00 2001 From: samyakpagariya <72349392+samyakpagariya@users.noreply.github.com> Date: Sun, 30 Oct 2022 16:13:41 +0530 Subject: [PATCH 495/726] For the better understanding of time taken. (#6583) * For the better understanding of time taken. In this change I have initialized a variable p with the value of (1e9+7) and then took the modulus of process time with it . This modification gives better time taken by the process . Firstly it was giving answer in the exponential now it gives in the integer form. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Apply suggestions from code review Co-authored-by: Caeden Perelli-Harris Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss Co-authored-by: Caeden Perelli-Harris --- sorts/bubble_sort.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sorts/bubble_sort.py b/sorts/bubble_sort.py index d4f0d25ca..aef2da272 100644 --- a/sorts/bubble_sort.py +++ b/sorts/bubble_sort.py @@ -49,4 +49,4 @@ if __name__ == "__main__": unsorted = [int(item) for item in user_input.split(",")] start = time.process_time() print(*bubble_sort(unsorted), sep=",") - print(f"Processing time: {time.process_time() - start}") + print(f"Processing time: {(time.process_time() - start)%1e9 + 7}") From 00fc53de9709648b495ecf707549d6068592fb76 Mon Sep 17 00:00:00 2001 From: happiestbee <87628038+happiestbee@users.noreply.github.com> Date: Sun, 30 Oct 2022 06:49:05 -0400 Subject: [PATCH 496/726] added sumset.py Fixes: #{6563} (#6742) * Create sumset.py * updating DIRECTORY.md * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Add descriptive var names * Update maths/sumset.py Co-authored-by: Caeden * Update sumset.py * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Caeden Co-authored-by: Christian Clauss --- DIRECTORY.md | 5 +++++ maths/sumset.py | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 maths/sumset.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 8ac9c3be7..38fd1d656 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -560,6 +560,7 @@ * [Lucas Lehmer Primality Test](maths/lucas_lehmer_primality_test.py) * [Lucas Series](maths/lucas_series.py) * [Maclaurin Series](maths/maclaurin_series.py) + * [Manhattan Distance](maths/manhattan_distance.py) * [Matrix Exponentiation](maths/matrix_exponentiation.py) * [Max Sum Sliding Window](maths/max_sum_sliding_window.py) * [Median Of Two Arrays](maths/median_of_two_arrays.py) @@ -616,6 +617,7 @@ * [Sum Of Digits](maths/sum_of_digits.py) * [Sum Of Geometric Progression](maths/sum_of_geometric_progression.py) * [Sum Of Harmonic Series](maths/sum_of_harmonic_series.py) + * [Sumset](maths/sumset.py) * [Sylvester Sequence](maths/sylvester_sequence.py) * [Test Prime Check](maths/test_prime_check.py) * [Trapezoidal Rule](maths/trapezoidal_rule.py) @@ -683,6 +685,7 @@ * [Casimir Effect](physics/casimir_effect.py) * [Centripetal Force](physics/centripetal_force.py) * [Horizontal Projectile Motion](physics/horizontal_projectile_motion.py) + * [Ideal Gas Law](physics/ideal_gas_law.py) * [Kinetic Energy](physics/kinetic_energy.py) * [Lorentz Transformation Four Vector](physics/lorentz_transformation_four_vector.py) * [Malus Law](physics/malus_law.py) @@ -690,6 +693,7 @@ * [Newtons Law Of Gravitation](physics/newtons_law_of_gravitation.py) * [Newtons Second Law Of Motion](physics/newtons_second_law_of_motion.py) * [Potential Energy](physics/potential_energy.py) + * [Rms Speed Of Molecule](physics/rms_speed_of_molecule.py) * [Sheer Stress](physics/sheer_stress.py) ## Project Euler @@ -978,6 +982,7 @@ * [Not Gate](quantum/not_gate.py) * [Q Full Adder](quantum/q_full_adder.py) * [Quantum Entanglement](quantum/quantum_entanglement.py) + * [Quantum Teleportation](quantum/quantum_teleportation.py) * [Ripple Adder Classic](quantum/ripple_adder_classic.py) * [Single Qubit Measure](quantum/single_qubit_measure.py) * [Superdense Coding](quantum/superdense_coding.py) diff --git a/maths/sumset.py b/maths/sumset.py new file mode 100644 index 000000000..fa18f9e24 --- /dev/null +++ b/maths/sumset.py @@ -0,0 +1,37 @@ +""" + +Calculates the SumSet of two sets of numbers (A and B) + +Source: + https://en.wikipedia.org/wiki/Sumset + +""" + + +def sumset(set_a: set, set_b: set) -> set: + """ + :param first set: a set of numbers + :param second set: a set of numbers + :return: the nth number in Sylvester's sequence + + >>> sumset({1, 2, 3}, {4, 5, 6}) + {5, 6, 7, 8, 9} + + >>> sumset({1, 2, 3}, {4, 5, 6, 7}) + {5, 6, 7, 8, 9, 10} + + >>> sumset({1, 2, 3, 4}, 3) + Traceback (most recent call last): + ... + AssertionError: The input value of [set_b=3] is not a set + """ + assert isinstance(set_a, set), f"The input value of [set_a={set_a}] is not a set" + assert isinstance(set_b, set), f"The input value of [set_b={set_b}] is not a set" + + return {a + b for a in set_a for b in set_b} + + +if __name__ == "__main__": + from doctest import testmod + + testmod() From 6b6d8cc1110b16b38c7e6aafe91cb6f9583669ae Mon Sep 17 00:00:00 2001 From: Micael Pereira <8707982+micaelalex@users.noreply.github.com> Date: Sun, 30 Oct 2022 10:49:22 +0000 Subject: [PATCH 497/726] Adding ELFHash Algorithm (#6731) * Adding ELFHash Algorithm Adding a new Hash Algorithm. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update elf.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update elf.py * Update elf.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update elf.py * Apply suggestions from code review Co-authored-by: Caeden Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Caeden --- hashes/elf.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 hashes/elf.py diff --git a/hashes/elf.py b/hashes/elf.py new file mode 100644 index 000000000..87fe339da --- /dev/null +++ b/hashes/elf.py @@ -0,0 +1,23 @@ +def elf_hash(data: str) -> int: + """ + Implementation of ElfHash Algorithm, a variant of PJW hash function. + + Returns: + [int] -- [32 bit binary int] + >>> elf_hash('lorem ipsum') + 253956621 + """ + hash = x = 0 + for letter in data: + hash = (hash << 4) + ord(letter) + x = hash & 0xF0000000 + if x != 0: + hash ^= x >> 24 + hash &= ~x + return hash + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From cc423007800b8707ea87353be808a90bef13ba18 Mon Sep 17 00:00:00 2001 From: Pravin Date: Sun, 30 Oct 2022 16:20:08 +0530 Subject: [PATCH 498/726] Added Readme file to document the hashing algorithm. (#6743) * Added Readme file to document the hashing algorithm. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- hashes/README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 hashes/README.md diff --git a/hashes/README.md b/hashes/README.md new file mode 100644 index 000000000..6df9a2fb6 --- /dev/null +++ b/hashes/README.md @@ -0,0 +1,17 @@ +# Hashes +Hashing is the process of mapping any amount of data to a specified size using an algorithm. This is known as a hash value (or, if you're feeling fancy, a hash code, hash sums, or even a hash digest). Hashing is a one-way function, whereas encryption is a two-way function. While it is functionally conceivable to reverse-hash stuff, the required computing power makes it impractical. Hashing is a one-way street. +Unlike encryption, which is intended to protect data in transit, hashing is intended to authenticate that a file or piece of data has not been altered—that it is authentic. In other words, it functions as a checksum. + +## Common hashing algorithms +### MD5 +This is one of the first algorithms that has gained widespread acceptance. MD5 is hashing algorithm made by Ray Rivest that is known to suffer vulnerabilities. It was created in 1992 as the successor to MD4. Currently MD6 is in the works, but as of 2009 Rivest had removed it from NIST consideration for SHA-3. + +### SHA +SHA stands for Security Hashing Algorithm and it’s probably best known as the hashing algorithm used in most SSL/TLS cipher suites. A cipher suite is a collection of ciphers and algorithms that are used for SSL/TLS connections. SHA handles the hashing aspects. SHA-1, as we mentioned earlier, is now deprecated. SHA-2 is now mandatory. SHA-2 is sometimes known has SHA-256, though variants with longer bit lengths are also available. + +### SHA256 +SHA 256 is a member of the SHA 2 algorithm family, under which SHA stands for Secure Hash Algorithm. It was a collaborative effort between both the NSA and NIST to implement a successor to the SHA 1 family, which was beginning to lose potency against brute force attacks. It was published in 2001. +The importance of the 256 in the name refers to the final hash digest value, i.e. the hash value will remain 256 bits regardless of the size of the plaintext/cleartext. Other algorithms in the SHA family are similar to SHA 256 in some ways. + +### Luhn +The Luhn algorithm, also renowned as the modulus 10 or mod 10 algorithm, is a straightforward checksum formula used to validate a wide range of identification numbers, including credit card numbers, IMEI numbers, and Canadian Social Insurance Numbers. A community of mathematicians developed the LUHN formula in the late 1960s. Companies offering credit cards quickly followed suit. Since the algorithm is in the public interest, anyone can use it. The algorithm is used by most credit cards and many government identification numbers as a simple method of differentiating valid figures from mistyped or otherwise incorrect numbers. It was created to guard against unintentional errors, not malicious attacks. \ No newline at end of file From b5d7f186f4c93e0a00635e9efabe33971b161fc6 Mon Sep 17 00:00:00 2001 From: Emmanuel Bauma Murairi <40155399+Emmastro@users.noreply.github.com> Date: Sun, 30 Oct 2022 14:52:50 +0400 Subject: [PATCH 499/726] Polynomial (#6745) * implement function to handle polynomial operations * edit documentation * fix type hint and linter errors * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix short variable name * fix spelling Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/polynomials/__init__.py | 0 .../single_indeterminate_operations.py | 188 ++++++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 maths/polynomials/__init__.py create mode 100644 maths/polynomials/single_indeterminate_operations.py diff --git a/maths/polynomials/__init__.py b/maths/polynomials/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/maths/polynomials/single_indeterminate_operations.py b/maths/polynomials/single_indeterminate_operations.py new file mode 100644 index 000000000..8bafdb591 --- /dev/null +++ b/maths/polynomials/single_indeterminate_operations.py @@ -0,0 +1,188 @@ +""" + +This module implements a single indeterminate polynomials class +with some basic operations + +Reference: https://en.wikipedia.org/wiki/Polynomial + +""" + +from __future__ import annotations + +from collections.abc import MutableSequence + + +class Polynomial: + def __init__(self, degree: int, coefficients: MutableSequence[float]) -> None: + """ + The coefficients should be in order of degree, from smallest to largest. + >>> p = Polynomial(2, [1, 2, 3]) + >>> p = Polynomial(2, [1, 2, 3, 4]) + Traceback (most recent call last): + ... + ValueError: The number of coefficients should be equal to the degree + 1. + + """ + if len(coefficients) != degree + 1: + raise ValueError( + "The number of coefficients should be equal to the degree + 1." + ) + + self.coefficients: list[float] = list(coefficients) + self.degree = degree + + def __add__(self, polynomial_2: Polynomial) -> Polynomial: + """ + Polynomial addition + >>> p = Polynomial(2, [1, 2, 3]) + >>> q = Polynomial(2, [1, 2, 3]) + >>> p + q + 6x^2 + 4x + 2 + """ + + if self.degree > polynomial_2.degree: + coefficients = self.coefficients[:] + for i in range(polynomial_2.degree + 1): + coefficients[i] += polynomial_2.coefficients[i] + return Polynomial(self.degree, coefficients) + else: + coefficients = polynomial_2.coefficients[:] + for i in range(self.degree + 1): + coefficients[i] += self.coefficients[i] + return Polynomial(polynomial_2.degree, coefficients) + + def __sub__(self, polynomial_2: Polynomial) -> Polynomial: + """ + Polynomial subtraction + >>> p = Polynomial(2, [1, 2, 4]) + >>> q = Polynomial(2, [1, 2, 3]) + >>> p - q + 1x^2 + """ + return self + polynomial_2 * Polynomial(0, [-1]) + + def __neg__(self) -> Polynomial: + """ + Polynomial negation + >>> p = Polynomial(2, [1, 2, 3]) + >>> -p + - 3x^2 - 2x - 1 + """ + return Polynomial(self.degree, [-c for c in self.coefficients]) + + def __mul__(self, polynomial_2: Polynomial) -> Polynomial: + """ + Polynomial multiplication + >>> p = Polynomial(2, [1, 2, 3]) + >>> q = Polynomial(2, [1, 2, 3]) + >>> p * q + 9x^4 + 12x^3 + 10x^2 + 4x + 1 + """ + coefficients: list[float] = [0] * (self.degree + polynomial_2.degree + 1) + for i in range(self.degree + 1): + for j in range(polynomial_2.degree + 1): + coefficients[i + j] += ( + self.coefficients[i] * polynomial_2.coefficients[j] + ) + + return Polynomial(self.degree + polynomial_2.degree, coefficients) + + def evaluate(self, substitution: int | float) -> int | float: + """ + Evaluates the polynomial at x. + >>> p = Polynomial(2, [1, 2, 3]) + >>> p.evaluate(2) + 17 + """ + result: int | float = 0 + for i in range(self.degree + 1): + result += self.coefficients[i] * (substitution**i) + return result + + def __str__(self) -> str: + """ + >>> p = Polynomial(2, [1, 2, 3]) + >>> print(p) + 3x^2 + 2x + 1 + """ + polynomial = "" + for i in range(self.degree, -1, -1): + if self.coefficients[i] == 0: + continue + elif self.coefficients[i] > 0: + if polynomial: + polynomial += " + " + else: + polynomial += " - " + + if i == 0: + polynomial += str(abs(self.coefficients[i])) + elif i == 1: + polynomial += str(abs(self.coefficients[i])) + "x" + else: + polynomial += str(abs(self.coefficients[i])) + "x^" + str(i) + + return polynomial + + def __repr__(self) -> str: + """ + >>> p = Polynomial(2, [1, 2, 3]) + >>> p + 3x^2 + 2x + 1 + """ + return self.__str__() + + def derivative(self) -> Polynomial: + """ + Returns the derivative of the polynomial. + >>> p = Polynomial(2, [1, 2, 3]) + >>> p.derivative() + 6x + 2 + """ + coefficients: list[float] = [0] * self.degree + for i in range(self.degree): + coefficients[i] = self.coefficients[i + 1] * (i + 1) + return Polynomial(self.degree - 1, coefficients) + + def integral(self, constant: int | float = 0) -> Polynomial: + """ + Returns the integral of the polynomial. + >>> p = Polynomial(2, [1, 2, 3]) + >>> p.integral() + 1.0x^3 + 1.0x^2 + 1.0x + """ + coefficients: list[float] = [0] * (self.degree + 2) + coefficients[0] = constant + for i in range(self.degree + 1): + coefficients[i + 1] = self.coefficients[i] / (i + 1) + return Polynomial(self.degree + 1, coefficients) + + def __eq__(self, polynomial_2: object) -> bool: + """ + Checks if two polynomials are equal. + >>> p = Polynomial(2, [1, 2, 3]) + >>> q = Polynomial(2, [1, 2, 3]) + >>> p == q + True + """ + if not isinstance(polynomial_2, Polynomial): + return False + + if self.degree != polynomial_2.degree: + return False + + for i in range(self.degree + 1): + if self.coefficients[i] != polynomial_2.coefficients[i]: + return False + + return True + + def __ne__(self, polynomial_2: object) -> bool: + """ + Checks if two polynomials are not equal. + >>> p = Polynomial(2, [1, 2, 3]) + >>> q = Polynomial(2, [1, 2, 3]) + >>> p != q + False + """ + return not self.__eq__(polynomial_2) From 9278d0c6cdaa30115dbfef510e31a805bd3027dd Mon Sep 17 00:00:00 2001 From: Dima I <79413560+DIvkov575@users.noreply.github.com> Date: Sun, 30 Oct 2022 06:54:23 -0400 Subject: [PATCH 500/726] Added archimedes principle (physics) (#7143) * Added archimedes principle (physics) * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * reformated * reformatted archimedes principles Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- physics/archimedes_principle.py | 49 +++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 physics/archimedes_principle.py diff --git a/physics/archimedes_principle.py b/physics/archimedes_principle.py new file mode 100644 index 000000000..6ecfc65e7 --- /dev/null +++ b/physics/archimedes_principle.py @@ -0,0 +1,49 @@ +""" +Calculates buoyant force on object submerged within static fluid. +Discovered by greek mathematician, Archimedes. The principle is named after him. + +Equation for calculating buoyant force: +Fb = ρ * V * g + +Source: +- https://en.wikipedia.org/wiki/Archimedes%27_principle +""" + + +# Acceleration Constant on Earth (unit m/s^2) +g = 9.80665 + + +def archimedes_principle( + fluid_density: float, volume: float, gravity: float = g +) -> float: + """ + Args: + fluid_density: density of fluid (kg/m^3) + volume: volume of object / liquid being displaced by object + gravity: Acceleration from gravity. Gravitational force on system, + Default is Earth Gravity + returns: + buoyant force on object in Newtons + + >>> archimedes_principle(fluid_density=997, volume=0.5, gravity=9.8) + 4885.3 + >>> archimedes_principle(fluid_density=997, volume=0.7) + 6844.061035 + """ + + if fluid_density <= 0: + raise ValueError("Impossible fluid density") + if volume < 0: + raise ValueError("Impossible Object volume") + if gravity <= 0: + raise ValueError("Impossible Gravity") + + return fluid_density * gravity * volume + + +if __name__ == "__main__": + import doctest + + # run doctest + doctest.testmod() From cafbbab125ebcdac4294f4cbda024b840d230b9a Mon Sep 17 00:00:00 2001 From: Lukas Esc <55601315+Luk-ESC@users.noreply.github.com> Date: Sun, 30 Oct 2022 11:56:54 +0100 Subject: [PATCH 501/726] shortened code using abs() and inplace ops (#7191) n = -n if n < 0 else n --> n = abs(n) n = n // 10 --> n //= 10 --- maths/sum_of_digits.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/maths/sum_of_digits.py b/maths/sum_of_digits.py index 64da00d46..5ad5fe6c9 100644 --- a/maths/sum_of_digits.py +++ b/maths/sum_of_digits.py @@ -14,11 +14,11 @@ def sum_of_digits(n: int) -> int: >>> sum_of_digits(0) 0 """ - n = -n if n < 0 else n + n = abs(n) res = 0 while n > 0: res += n % 10 - n = n // 10 + n //= 10 return res @@ -35,7 +35,7 @@ def sum_of_digits_recursion(n: int) -> int: >>> sum_of_digits_recursion(0) 0 """ - n = -n if n < 0 else n + n = abs(n) return n if n < 10 else n % 10 + sum_of_digits(n // 10) From ab9d8f3874ba550bea0103e0891160b8d9145208 Mon Sep 17 00:00:00 2001 From: Jeremias Moreira Gomes Date: Sun, 30 Oct 2022 08:09:23 -0300 Subject: [PATCH 502/726] Adding a Quine in Python. (#6807) * Adding a Quine in Python. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- other/quine.py | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 other/quine.py diff --git a/other/quine.py b/other/quine.py new file mode 100644 index 000000000..01e03bbb0 --- /dev/null +++ b/other/quine.py @@ -0,0 +1,10 @@ +#!/bin/python3 +""" +Quine: + +A quine is a computer program which takes no input and produces a copy of its +own source code as its only output (disregarding this docstring and the shebang). + +More info on: https://en.wikipedia.org/wiki/Quine_(computing) +""" +print((lambda quine: quine % quine)("print((lambda quine: quine %% quine)(%r))")) From 94b51f6a91def387b82369401a42710cae4ee4e0 Mon Sep 17 00:00:00 2001 From: sadiqebrahim <75269485+sadiqebrahim@users.noreply.github.com> Date: Sun, 30 Oct 2022 17:22:20 +0530 Subject: [PATCH 503/726] Added Builtin Voltage (#7850) * Added Builtin Voltage * Update builtin_voltage.py * Update electronics/builtin_voltage.py Co-authored-by: Caeden Perelli-Harris * Update electronics/builtin_voltage.py Co-authored-by: Caeden Perelli-Harris * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Apply suggestions from code review Co-authored-by: Caeden Perelli-Harris * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Create elf.py Co-authored-by: Caeden Perelli-Harris Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- electronics/builtin_voltage.py | 67 ++++++++++++++++++++++++++++++++++ hashes/elf.py | 14 +++---- 2 files changed, 73 insertions(+), 8 deletions(-) create mode 100644 electronics/builtin_voltage.py diff --git a/electronics/builtin_voltage.py b/electronics/builtin_voltage.py new file mode 100644 index 000000000..38fde4524 --- /dev/null +++ b/electronics/builtin_voltage.py @@ -0,0 +1,67 @@ +from math import log + +from scipy.constants import Boltzmann, physical_constants + +T = 300 # TEMPERATURE (unit = K) + + +def builtin_voltage( + donor_conc: float, # donor concentration + acceptor_conc: float, # acceptor concentration + intrinsic_conc: float, # intrinsic concentration +) -> float: + """ + This function can calculate the Builtin Voltage of a pn junction diode. + This is calculated from the given three values. + Examples - + >>> builtin_voltage(donor_conc=1e17, acceptor_conc=1e17, intrinsic_conc=1e10) + 0.833370010652644 + >>> builtin_voltage(donor_conc=0, acceptor_conc=1600, intrinsic_conc=200) + Traceback (most recent call last): + ... + ValueError: Donor concentration should be positive + >>> builtin_voltage(donor_conc=1000, acceptor_conc=0, intrinsic_conc=1200) + Traceback (most recent call last): + ... + ValueError: Acceptor concentration should be positive + >>> builtin_voltage(donor_conc=1000, acceptor_conc=1000, intrinsic_conc=0) + Traceback (most recent call last): + ... + ValueError: Intrinsic concentration should be positive + >>> builtin_voltage(donor_conc=1000, acceptor_conc=3000, intrinsic_conc=2000) + Traceback (most recent call last): + ... + ValueError: Donor concentration should be greater than intrinsic concentration + >>> builtin_voltage(donor_conc=3000, acceptor_conc=1000, intrinsic_conc=2000) + Traceback (most recent call last): + ... + ValueError: Acceptor concentration should be greater than intrinsic concentration + """ + + if donor_conc <= 0: + raise ValueError("Donor concentration should be positive") + elif acceptor_conc <= 0: + raise ValueError("Acceptor concentration should be positive") + elif intrinsic_conc <= 0: + raise ValueError("Intrinsic concentration should be positive") + elif donor_conc <= intrinsic_conc: + raise ValueError( + "Donor concentration should be greater than intrinsic concentration" + ) + elif acceptor_conc <= intrinsic_conc: + raise ValueError( + "Acceptor concentration should be greater than intrinsic concentration" + ) + else: + return ( + Boltzmann + * T + * log((donor_conc * acceptor_conc) / intrinsic_conc**2) + / physical_constants["electron volt"][0] + ) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() diff --git a/hashes/elf.py b/hashes/elf.py index 87fe339da..e4bfcec22 100644 --- a/hashes/elf.py +++ b/hashes/elf.py @@ -2,19 +2,17 @@ def elf_hash(data: str) -> int: """ Implementation of ElfHash Algorithm, a variant of PJW hash function. - Returns: - [int] -- [32 bit binary int] >>> elf_hash('lorem ipsum') 253956621 """ - hash = x = 0 + hash_ = x = 0 for letter in data: - hash = (hash << 4) + ord(letter) - x = hash & 0xF0000000 + hash_ = (hash_ << 4) + ord(letter) + x = hash_ & 0xF0000000 if x != 0: - hash ^= x >> 24 - hash &= ~x - return hash + hash_ ^= x >> 24 + hash_ &= ~x + return hash_ if __name__ == "__main__": From 69d04ff64468d5b2815c0f22190b741393496a9e Mon Sep 17 00:00:00 2001 From: Kushagra Makharia Date: Sun, 30 Oct 2022 18:12:59 +0530 Subject: [PATCH 504/726] Added mean absolute error in linear regression (#7003) * Added mean absolute error in linear regression * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Code feedback changes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Apply suggestions from code review Co-authored-by: Caeden Perelli-Harris * Apply suggestions from code review * Update linear_regression.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss Co-authored-by: Caeden Perelli-Harris --- machine_learning/linear_regression.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/machine_learning/linear_regression.py b/machine_learning/linear_regression.py index 92ab91c01..75943ac9f 100644 --- a/machine_learning/linear_regression.py +++ b/machine_learning/linear_regression.py @@ -17,9 +17,8 @@ def collect_dataset(): :return : dataset obtained from the link, as matrix """ response = requests.get( - "https://raw.githubusercontent.com/yashLadha/" - + "The_Math_of_Intelligence/master/Week1/ADRvs" - + "Rating.csv" + "https://raw.githubusercontent.com/yashLadha/The_Math_of_Intelligence/" + "master/Week1/ADRvsRating.csv" ) lines = response.text.splitlines() data = [] @@ -87,6 +86,16 @@ def run_linear_regression(data_x, data_y): return theta +def mean_absolute_error(predicted_y, original_y): + """Return sum of square error for error calculation + :param predicted_y : contains the output of prediction (result vector) + :param original_y : contains values of expected outcome + :return : mean absolute error computed from given feature's + """ + total = sum(abs(y - predicted_y[i]) for i, y in enumerate(original_y)) + return total / len(original_y) + + def main(): """Driver function""" data = collect_dataset() From 2c65597093efa80a572a6a739d8f13a8d3579c18 Mon Sep 17 00:00:00 2001 From: kumarsurajsk <104374726+kumarsurajsk@users.noreply.github.com> Date: Sun, 30 Oct 2022 18:22:37 +0530 Subject: [PATCH 505/726] addition_without_arithmetic (#6830) * Addition_without_arithmetic * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * added_param * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * added_param_in_first_sec * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * change_align * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update Addition_without_arithmetic.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Rename Addition_without_arithmetic.py to addition_without_arithmetic.py * Update addition_without_arithmetic.py * Update addition_without_arithmetic.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- maths/addition_without_arithmetic.py | 39 ++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 maths/addition_without_arithmetic.py diff --git a/maths/addition_without_arithmetic.py b/maths/addition_without_arithmetic.py new file mode 100644 index 000000000..409604e4c --- /dev/null +++ b/maths/addition_without_arithmetic.py @@ -0,0 +1,39 @@ +""" +Illustrate how to add the integer without arithmetic operation +Author: suraj Kumar +Time Complexity: 1 +https://en.wikipedia.org/wiki/Bitwise_operation +""" + + +def add(first: int, second: int) -> int: + """ + Implementation of addition of integer + + Examples: + >>> add(3, 5) + 8 + >>> add(13, 5) + 18 + >>> add(-7, 2) + -5 + >>> add(0, -7) + -7 + >>> add(-321, 0) + -321 + """ + while second != 0: + c = first & second + first ^= second + second = c << 1 + return first + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + + first = int(input("Enter the first number: ").strip()) + second = int(input("Enter the second number: ").strip()) + print(f"{add(first, second) = }") From cf915e704285b1b40b6d0f180d60791204486fd3 Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Sun, 30 Oct 2022 17:00:16 +0400 Subject: [PATCH 506/726] add Levinstein distance with Dynamic Programming: up -> down approach (#7171) * add Levinstein distance with Dynamic Programming: up -> down approach * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add type hint * fix flake8 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update dynamic_programming/min_distance_up_bottom.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update min_distance_up_bottom.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- dynamic_programming/min_distance_up_bottom.py | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 dynamic_programming/min_distance_up_bottom.py diff --git a/dynamic_programming/min_distance_up_bottom.py b/dynamic_programming/min_distance_up_bottom.py new file mode 100644 index 000000000..49c361f24 --- /dev/null +++ b/dynamic_programming/min_distance_up_bottom.py @@ -0,0 +1,55 @@ +""" +Author : Alexander Pantyukhin +Date : October 14, 2022 +This is implementation Dynamic Programming up bottom approach +to find edit distance. +The aim is to demonstate up bottom approach for solving the task. +The implementation was tested on the +leetcode: https://leetcode.com/problems/edit-distance/ +""" + +""" +Levinstein distance +Dynamic Programming: up -> down. +""" + + +def min_distance_up_bottom(word1: str, word2: str) -> int: + """ + >>> min_distance_up_bottom("intention", "execution") + 5 + >>> min_distance_up_bottom("intention", "") + 9 + >>> min_distance_up_bottom("", "") + 0 + >>> min_distance_up_bottom("zooicoarchaeologist", "zoologist") + 10 + """ + + from functools import lru_cache + + len_word1 = len(word1) + len_word2 = len(word2) + + @lru_cache(maxsize=None) + def min_distance(index1: int, index2: int) -> int: + # if first word index is overflow - delete all from the second word + if index1 >= len_word1: + return len_word2 - index2 + # if second word index is overflow - delete all from the first word + if index2 >= len_word2: + return len_word1 - index1 + diff = int(word1[index1] != word2[index2]) # current letters not identical + return min( + 1 + min_distance(index1 + 1, index2), + 1 + min_distance(index1, index2 + 1), + diff + min_distance(index1 + 1, index2 + 1), + ) + + return min_distance(0, 0) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From d1430aa36b0a15a9e018367db210061e7a76dec4 Mon Sep 17 00:00:00 2001 From: Wissam Fawaz <55150850+wissamfawaz@users.noreply.github.com> Date: Sun, 30 Oct 2022 15:14:22 +0200 Subject: [PATCH 507/726] Implemented a Pascal triangle generator (#7317) * Added a Pascal triangle implementation to the other folder * Added Pascal triangle implementation to the other folder. * Added Pascal triangle implementation to the other folder. * Added Pascal triangle implementation to the other folder. * Implemented a Pascal triangle generator. * Reversed Changes to DIRECTORY.md * Reversed changed to .md files * Update other/pascal_triangle.py Removed personal info Co-authored-by: Paul <56065602+ZeroDayOwl@users.noreply.github.com> * Update pascal_triangle.py Expanded the description of the algorithm * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Printed output in triangular form * Update CONTRIBUTING.md Co-authored-by: Paul <56065602+ZeroDayOwl@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- other/pascal_triangle.py | 96 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 other/pascal_triangle.py diff --git a/other/pascal_triangle.py b/other/pascal_triangle.py new file mode 100644 index 000000000..5cc3cee8a --- /dev/null +++ b/other/pascal_triangle.py @@ -0,0 +1,96 @@ +""" +This implementation demonstrates how to generate the +elements of a Pascal's triangle. The element having +a row index of r and column index of c can be derived +as follows: +triangle[r][c] = triangle[r-1][c-1]+triangle[r-1][c] +What is Pascal's triangle? +- It is a triangular array containing binomial coefficients. +Refer to (https://en.wikipedia.org/wiki/Pascal%27s_triangle) +for more info about this triangle. +""" + + +def print_pascal_triangle(num_rows: int) -> None: + """ + Print Pascal's triangle for different number of rows + >>> print_pascal_triangle(5) + 1 + 1 1 + 1 2 1 + 1 3 3 1 + 1 4 6 4 1 + """ + triangle = generate_pascal_triangle(num_rows) + for row_idx in range(num_rows): + # Print left spaces + for _ in range(num_rows - row_idx - 1): + print(end=" ") + # Print row values + for col_idx in range(row_idx + 1): + if col_idx != row_idx: + print(triangle[row_idx][col_idx], end=" ") + else: + print(triangle[row_idx][col_idx], end="") + print() + + +def generate_pascal_triangle(num_rows: int) -> list[list[int]]: + """ + Create Pascal's triangle for different number of rows + >>> generate_pascal_triangle(1) + [[1]] + >>> generate_pascal_triangle(2) + [[1], [1, 1]] + >>> generate_pascal_triangle(3) + [[1], [1, 1], [1, 2, 1]] + >>> generate_pascal_triangle(4) + [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1]] + >>> generate_pascal_triangle(5) + [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1]] + """ + triangle: list[list[int]] = [] + for current_row_idx in range(num_rows): + current_row = populate_current_row(triangle, current_row_idx) + triangle.append(current_row) + return triangle + + +def populate_current_row(triangle: list[list[int]], current_row_idx: int) -> list[int]: + """ + >>> triangle = [[1]] + >>> populate_current_row(triangle, 1) + [1, 1] + """ + current_row = [-1] * (current_row_idx + 1) + # first and last elements of current row are equal to 1 + current_row[0], current_row[-1] = 1, 1 + for current_col_idx in range(1, current_row_idx): + calculate_current_element( + triangle, current_row, current_row_idx, current_col_idx + ) + return current_row + + +def calculate_current_element( + triangle: list[list[int]], + current_row: list[int], + current_row_idx: int, + current_col_idx: int, +) -> None: + """ + >>> triangle = [[1], [1, 1]] + >>> current_row = [1, -1, 1] + >>> calculate_current_element(triangle, current_row, 2, 1) + >>> current_row + [1, 2, 1] + """ + above_to_left_elt = triangle[current_row_idx - 1][current_col_idx - 1] + above_to_right_elt = triangle[current_row_idx - 1][current_col_idx] + current_row[current_col_idx] = above_to_left_elt + above_to_right_elt + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 47100b992aef2fd5a7ae001155e3d0411db99ec9 Mon Sep 17 00:00:00 2001 From: Agniv Ghosh <73717822+agnivg@users.noreply.github.com> Date: Sun, 30 Oct 2022 18:45:46 +0530 Subject: [PATCH 508/726] Added code for palindrome partitioning problem under dynamic programming (#7222) * Added code for palindrome partitioning problem under dynamic programming * Updated return type for function * Updated Line 24 according to suggestions * Apply suggestions from code review Co-authored-by: Caeden Perelli-Harris * Update palindrome_partitioning.py * Update palindrome_partitioning.py * is_palindromic Co-authored-by: Christian Clauss Co-authored-by: Caeden Perelli-Harris --- .../palindrome_partitioning.py | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 dynamic_programming/palindrome_partitioning.py diff --git a/dynamic_programming/palindrome_partitioning.py b/dynamic_programming/palindrome_partitioning.py new file mode 100644 index 000000000..c1629440e --- /dev/null +++ b/dynamic_programming/palindrome_partitioning.py @@ -0,0 +1,39 @@ +""" +Given a string s, partition s such that every substring of the +partition is a palindrome. +Find the minimum cuts needed for a palindrome partitioning of s. + +Time Complexity: O(n^2) +Space Complexity: O(n^2) +For other explanations refer to: https://www.youtube.com/watch?v=_H8V5hJUGd0 +""" + + +def find_minimum_partitions(string: str) -> int: + """ + Returns the minimum cuts needed for a palindrome partitioning of string + + >>> find_minimum_partitions("aab") + 1 + >>> find_minimum_partitions("aaa") + 0 + >>> find_minimum_partitions("ababbbabbababa") + 3 + """ + length = len(string) + cut = [0] * length + is_palindromic = [[False for i in range(length)] for j in range(length)] + for i, c in enumerate(string): + mincut = i + for j in range(i + 1): + if c == string[j] and (i - j < 2 or is_palindromic[j + 1][i - 1]): + is_palindromic[j][i] = True + mincut = min(mincut, 0 if j == 0 else (cut[j - 1] + 1)) + cut[i] = mincut + return cut[length - 1] + + +if __name__ == "__main__": + s = input("Enter the string: ").strip() + ans = find_minimum_partitions(s) + print(f"Minimum number of partitions required for the '{s}' is {ans}") From 11e6c6fcc485bf78e5d28c7cf311278a013685d5 Mon Sep 17 00:00:00 2001 From: Gautam Chaurasia <64725629+GautamChaurasia@users.noreply.github.com> Date: Sun, 30 Oct 2022 18:58:27 +0530 Subject: [PATCH 509/726] Added algorithm for finding index of rightmost set bit (#7234) * Added algorithm for finding index of rightmost set bit * applied suggested changes * applied suggested changes * Fixed failing Testcases * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .../index_of_rightmost_set_bit.py | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 bit_manipulation/index_of_rightmost_set_bit.py diff --git a/bit_manipulation/index_of_rightmost_set_bit.py b/bit_manipulation/index_of_rightmost_set_bit.py new file mode 100644 index 000000000..eb52ea4e6 --- /dev/null +++ b/bit_manipulation/index_of_rightmost_set_bit.py @@ -0,0 +1,43 @@ +# Reference: https://www.geeksforgeeks.org/position-of-rightmost-set-bit/ + + +def get_index_of_rightmost_set_bit(number: int) -> int: + """ + Take in a positive integer 'number'. + Returns the zero-based index of first set bit in that 'number' from right. + Returns -1, If no set bit found. + + >>> get_index_of_rightmost_set_bit(0) + -1 + >>> get_index_of_rightmost_set_bit(5) + 0 + >>> get_index_of_rightmost_set_bit(36) + 2 + >>> get_index_of_rightmost_set_bit(8) + 3 + >>> get_index_of_rightmost_set_bit(-18) + Traceback (most recent call last): + ... + ValueError: Input must be a non-negative integer + """ + + if number < 0 or not isinstance(number, int): + raise ValueError("Input must be a non-negative integer") + + intermediate = number & ~(number - 1) + index = 0 + while intermediate: + intermediate >>= 1 + index += 1 + return index - 1 + + +if __name__ == "__main__": + """ + Finding the index of rightmost set bit has some very peculiar use-cases, + especially in finding missing or/and repeating numbers in a list of + positive integers. + """ + import doctest + + doctest.testmod(verbose=True) From e12516debb977e0b3ec9b67d1ddc8770450ae8d1 Mon Sep 17 00:00:00 2001 From: Abhishek Chakraborty Date: Sun, 30 Oct 2022 14:11:05 -0700 Subject: [PATCH 510/726] Shear stress: typo + WIkipedia URL (#7896) --- physics/{sheer_stress.py => shear_stress.py} | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) rename physics/{sheer_stress.py => shear_stress.py} (70%) diff --git a/physics/sheer_stress.py b/physics/shear_stress.py similarity index 70% rename from physics/sheer_stress.py rename to physics/shear_stress.py index 74a2d36b1..129148943 100644 --- a/physics/sheer_stress.py +++ b/physics/shear_stress.py @@ -1,23 +1,31 @@ from __future__ import annotations +""" +Shear stress is a component of stress that is coplanar to the material cross-section. +It arises due to a shear force, the component of the force vector parallel to the +material cross-section. -def sheer_stress( +https://en.wikipedia.org/wiki/Shear_stress +""" + + +def shear_stress( stress: float, tangential_force: float, area: float, ) -> tuple[str, float]: """ This function can calculate any one of the three - - 1. Sheer Stress + 1. Shear Stress 2. Tangential Force 3. Cross-sectional Area This is calculated from the other two provided values Examples - - >>> sheer_stress(stress=25, tangential_force=100, area=0) + >>> shear_stress(stress=25, tangential_force=100, area=0) ('area', 4.0) - >>> sheer_stress(stress=0, tangential_force=1600, area=200) + >>> shear_stress(stress=0, tangential_force=1600, area=200) ('stress', 8.0) - >>> sheer_stress(stress=1000, tangential_force=0, area=1200) + >>> shear_stress(stress=1000, tangential_force=0, area=1200) ('tangential_force', 1200000) """ if (stress, tangential_force, area).count(0) != 1: From c0168cd33f6670f7e32eaa04d77b6be70b3588d4 Mon Sep 17 00:00:00 2001 From: Gmuslow <54784260+Gmuslow@users.noreply.github.com> Date: Sun, 30 Oct 2022 16:33:13 -0500 Subject: [PATCH 511/726] Created equivalent_resistance under Electronics (#6782) * Create resistor_equivalence.py * Update resistor_equivalence.py * Update electronics/resistor_equivalence.py removed an unnecessary space Co-authored-by: Caeden * Update resistor_equivalence.py fixed the snake_case requirement * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update resistor_equivalence.py finalize the naming convention errors (hopefully) * Update resistor_equivalence.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: Caeden Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- electronics/resistor_equivalence.py | 58 +++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 electronics/resistor_equivalence.py diff --git a/electronics/resistor_equivalence.py b/electronics/resistor_equivalence.py new file mode 100644 index 000000000..7142f838a --- /dev/null +++ b/electronics/resistor_equivalence.py @@ -0,0 +1,58 @@ +# https://byjus.com/equivalent-resistance-formula/ + +from __future__ import annotations + + +def resistor_parallel(resistors: list[float]) -> float: + """ + Req = 1/ (1/R1 + 1/R2 + ... + 1/Rn) + + >>> resistor_parallel([3.21389, 2, 3]) + 0.8737571620498019 + >>> resistor_parallel([3.21389, 2, -3]) + Traceback (most recent call last): + ... + ValueError: Resistor at index 2 has a negative or zero value! + >>> resistor_parallel([3.21389, 2, 0.000]) + Traceback (most recent call last): + ... + ValueError: Resistor at index 2 has a negative or zero value! + """ + + first_sum = 0.00 + index = 0 + for resistor in resistors: + if resistor <= 0: + raise ValueError(f"Resistor at index {index} has a negative or zero value!") + first_sum += 1 / float(resistor) + index += 1 + return 1 / first_sum + + +def resistor_series(resistors: list[float]) -> float: + """ + Req = R1 + R2 + ... + Rn + + Calculate the equivalent resistance for any number of resistors in parallel. + + >>> resistor_series([3.21389, 2, 3]) + 8.21389 + >>> resistor_series([3.21389, 2, -3]) + Traceback (most recent call last): + ... + ValueError: Resistor at index 2 has a negative value! + """ + sum_r = 0.00 + index = 0 + for resistor in resistors: + sum_r += resistor + if resistor < 0: + raise ValueError(f"Resistor at index {index} has a negative value!") + index += 1 + return sum_r + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From f8958ebe20522f5b0d32f33fd78870185912a67a Mon Sep 17 00:00:00 2001 From: himanshit0304 <70479061+himanshit0304@users.noreply.github.com> Date: Mon, 31 Oct 2022 04:25:11 +0530 Subject: [PATCH 512/726] Add print_multiplication_table.py (#6607) * Add print_multiplication_table.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Added return type description * Update print_multiplication_table.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- maths/print_multiplication_table.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 maths/print_multiplication_table.py diff --git a/maths/print_multiplication_table.py b/maths/print_multiplication_table.py new file mode 100644 index 000000000..dbe4a4be0 --- /dev/null +++ b/maths/print_multiplication_table.py @@ -0,0 +1,26 @@ +def multiplication_table(number: int, number_of_terms: int) -> str: + """ + Prints the multiplication table of a given number till the given number of terms + + >>> print(multiplication_table(3, 5)) + 3 * 1 = 3 + 3 * 2 = 6 + 3 * 3 = 9 + 3 * 4 = 12 + 3 * 5 = 15 + + >>> print(multiplication_table(-4, 6)) + -4 * 1 = -4 + -4 * 2 = -8 + -4 * 3 = -12 + -4 * 4 = -16 + -4 * 5 = -20 + -4 * 6 = -24 + """ + return "\n".join( + f"{number} * {i} = {number * i}" for i in range(1, number_of_terms + 1) + ) + + +if __name__ == "__main__": + print(multiplication_table(number=5, number_of_terms=10)) From 39e5bc5980254582362ad02bb6616aaa58bfac8a Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Mon, 31 Oct 2022 01:13:21 -0400 Subject: [PATCH 513/726] Refactor bottom-up edit distance function to be class method (#7347) * Refactor bottom-up function to be class method * Add type hints * Update convolve function namespace * Remove depreciated np.float * updating DIRECTORY.md * updating DIRECTORY.md * updating DIRECTORY.md * updating DIRECTORY.md * Renamed function for consistency * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> --- DIRECTORY.md | 15 +++- dynamic_programming/edit_distance.py | 122 +++++++++++++-------------- 2 files changed, 74 insertions(+), 63 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 38fd1d656..be3a121c8 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -46,6 +46,7 @@ * [Count Number Of One Bits](bit_manipulation/count_number_of_one_bits.py) * [Gray Code Sequence](bit_manipulation/gray_code_sequence.py) * [Highest Set Bit](bit_manipulation/highest_set_bit.py) + * [Index Of Rightmost Set Bit](bit_manipulation/index_of_rightmost_set_bit.py) * [Is Even](bit_manipulation/is_even.py) * [Reverse Bits](bit_manipulation/reverse_bits.py) * [Single Bit Manipulation Operations](bit_manipulation/single_bit_manipulation_operations.py) @@ -307,24 +308,28 @@ * [Max Non Adjacent Sum](dynamic_programming/max_non_adjacent_sum.py) * [Max Sub Array](dynamic_programming/max_sub_array.py) * [Max Sum Contiguous Subsequence](dynamic_programming/max_sum_contiguous_subsequence.py) + * [Min Distance Up Bottom](dynamic_programming/min_distance_up_bottom.py) * [Minimum Coin Change](dynamic_programming/minimum_coin_change.py) * [Minimum Cost Path](dynamic_programming/minimum_cost_path.py) * [Minimum Partition](dynamic_programming/minimum_partition.py) * [Minimum Squares To Represent A Number](dynamic_programming/minimum_squares_to_represent_a_number.py) * [Minimum Steps To One](dynamic_programming/minimum_steps_to_one.py) * [Optimal Binary Search Tree](dynamic_programming/optimal_binary_search_tree.py) + * [Palindrome Partitioning](dynamic_programming/palindrome_partitioning.py) * [Rod Cutting](dynamic_programming/rod_cutting.py) * [Subset Generation](dynamic_programming/subset_generation.py) * [Sum Of Subset](dynamic_programming/sum_of_subset.py) * [Viterbi](dynamic_programming/viterbi.py) ## Electronics + * [Builtin Voltage](electronics/builtin_voltage.py) * [Carrier Concentration](electronics/carrier_concentration.py) * [Coulombs Law](electronics/coulombs_law.py) * [Electric Conductivity](electronics/electric_conductivity.py) * [Electric Power](electronics/electric_power.py) * [Electrical Impedance](electronics/electrical_impedance.py) * [Ohms Law](electronics/ohms_law.py) + * [Resistor Equivalence](electronics/resistor_equivalence.py) * [Resonant Frequency](electronics/resonant_frequency.py) ## File Transfer @@ -426,6 +431,7 @@ * [Adler32](hashes/adler32.py) * [Chaos Machine](hashes/chaos_machine.py) * [Djb2](hashes/djb2.py) + * [Elf](hashes/elf.py) * [Enigma Machine](hashes/enigma_machine.py) * [Hamming Code](hashes/hamming_code.py) * [Luhn](hashes/luhn.py) @@ -491,6 +497,7 @@ * [Abs Max](maths/abs_max.py) * [Abs Min](maths/abs_min.py) * [Add](maths/add.py) + * [Addition Without Arithmetic](maths/addition_without_arithmetic.py) * [Aliquot Sum](maths/aliquot_sum.py) * [Allocation Number](maths/allocation_number.py) * [Arc Length](maths/arc_length.py) @@ -581,12 +588,15 @@ * [Points Are Collinear 3D](maths/points_are_collinear_3d.py) * [Pollard Rho](maths/pollard_rho.py) * [Polynomial Evaluation](maths/polynomial_evaluation.py) + * Polynomials + * [Single Indeterminate Operations](maths/polynomials/single_indeterminate_operations.py) * [Power Using Recursion](maths/power_using_recursion.py) * [Prime Check](maths/prime_check.py) * [Prime Factors](maths/prime_factors.py) * [Prime Numbers](maths/prime_numbers.py) * [Prime Sieve Eratosthenes](maths/prime_sieve_eratosthenes.py) * [Primelib](maths/primelib.py) + * [Print Multiplication Table](maths/print_multiplication_table.py) * [Proth Number](maths/proth_number.py) * [Pythagoras](maths/pythagoras.py) * [Qr Decomposition](maths/qr_decomposition.py) @@ -676,12 +686,15 @@ * [Magicdiamondpattern](other/magicdiamondpattern.py) * [Maximum Subarray](other/maximum_subarray.py) * [Nested Brackets](other/nested_brackets.py) + * [Pascal Triangle](other/pascal_triangle.py) * [Password Generator](other/password_generator.py) + * [Quine](other/quine.py) * [Scoring Algorithm](other/scoring_algorithm.py) * [Sdes](other/sdes.py) * [Tower Of Hanoi](other/tower_of_hanoi.py) ## Physics + * [Archimedes Principle](physics/archimedes_principle.py) * [Casimir Effect](physics/casimir_effect.py) * [Centripetal Force](physics/centripetal_force.py) * [Horizontal Projectile Motion](physics/horizontal_projectile_motion.py) @@ -694,7 +707,7 @@ * [Newtons Second Law Of Motion](physics/newtons_second_law_of_motion.py) * [Potential Energy](physics/potential_energy.py) * [Rms Speed Of Molecule](physics/rms_speed_of_molecule.py) - * [Sheer Stress](physics/sheer_stress.py) + * [Shear Stress](physics/shear_stress.py) ## Project Euler * Problem 001 diff --git a/dynamic_programming/edit_distance.py b/dynamic_programming/edit_distance.py index fe23431a7..774aa0473 100644 --- a/dynamic_programming/edit_distance.py +++ b/dynamic_programming/edit_distance.py @@ -19,74 +19,72 @@ class EditDistance: """ def __init__(self): - self.__prepare__() + self.word1 = "" + self.word2 = "" + self.dp = [] - def __prepare__(self, n=0, m=0): - self.dp = [[-1 for y in range(0, m)] for x in range(0, n)] - - def __solve_dp(self, x, y): - if x == -1: - return y + 1 - elif y == -1: - return x + 1 - elif self.dp[x][y] > -1: - return self.dp[x][y] + def __min_dist_top_down_dp(self, m: int, n: int) -> int: + if m == -1: + return n + 1 + elif n == -1: + return m + 1 + elif self.dp[m][n] > -1: + return self.dp[m][n] else: - if self.a[x] == self.b[y]: - self.dp[x][y] = self.__solve_dp(x - 1, y - 1) + if self.word1[m] == self.word2[n]: + self.dp[m][n] = self.__min_dist_top_down_dp(m - 1, n - 1) else: - self.dp[x][y] = 1 + min( - self.__solve_dp(x, y - 1), - self.__solve_dp(x - 1, y), - self.__solve_dp(x - 1, y - 1), - ) + insert = self.__min_dist_top_down_dp(m, n - 1) + delete = self.__min_dist_top_down_dp(m - 1, n) + replace = self.__min_dist_top_down_dp(m - 1, n - 1) + self.dp[m][n] = 1 + min(insert, delete, replace) - return self.dp[x][y] + return self.dp[m][n] - def solve(self, a, b): - if isinstance(a, bytes): - a = a.decode("ascii") + def min_dist_top_down(self, word1: str, word2: str) -> int: + """ + >>> EditDistance().min_dist_top_down("intention", "execution") + 5 + >>> EditDistance().min_dist_top_down("intention", "") + 9 + >>> EditDistance().min_dist_top_down("", "") + 0 + """ + self.word1 = word1 + self.word2 = word2 + self.dp = [[-1 for _ in range(len(word2))] for _ in range(len(word1))] - if isinstance(b, bytes): - b = b.decode("ascii") + return self.__min_dist_top_down_dp(len(word1) - 1, len(word2) - 1) - self.a = str(a) - self.b = str(b) + def min_dist_bottom_up(self, word1: str, word2: str) -> int: + """ + >>> EditDistance().min_dist_bottom_up("intention", "execution") + 5 + >>> EditDistance().min_dist_bottom_up("intention", "") + 9 + >>> EditDistance().min_dist_bottom_up("", "") + 0 + """ + self.word1 = word1 + self.word2 = word2 + m = len(word1) + n = len(word2) + self.dp = [[0 for _ in range(n + 1)] for _ in range(m + 1)] - self.__prepare__(len(a), len(b)) - - return self.__solve_dp(len(a) - 1, len(b) - 1) - - -def min_distance_bottom_up(word1: str, word2: str) -> int: - """ - >>> min_distance_bottom_up("intention", "execution") - 5 - >>> min_distance_bottom_up("intention", "") - 9 - >>> min_distance_bottom_up("", "") - 0 - """ - m = len(word1) - n = len(word2) - dp = [[0 for _ in range(n + 1)] for _ in range(m + 1)] - for i in range(m + 1): - for j in range(n + 1): - - if i == 0: # first string is empty - dp[i][j] = j - elif j == 0: # second string is empty - dp[i][j] = i - elif ( - word1[i - 1] == word2[j - 1] - ): # last character of both substing is equal - dp[i][j] = dp[i - 1][j - 1] - else: - insert = dp[i][j - 1] - delete = dp[i - 1][j] - replace = dp[i - 1][j - 1] - dp[i][j] = 1 + min(insert, delete, replace) - return dp[m][n] + for i in range(m + 1): + for j in range(n + 1): + if i == 0: # first string is empty + self.dp[i][j] = j + elif j == 0: # second string is empty + self.dp[i][j] = i + elif word1[i - 1] == word2[j - 1]: # last characters are equal + self.dp[i][j] = self.dp[i - 1][j - 1] + else: + insert = self.dp[i][j - 1] + delete = self.dp[i - 1][j] + replace = self.dp[i - 1][j - 1] + self.dp[i][j] = 1 + min(insert, delete, replace) + return self.dp[m][n] if __name__ == "__main__": @@ -99,7 +97,7 @@ if __name__ == "__main__": S2 = input("Enter the second string: ").strip() print() - print(f"The minimum Edit Distance is: {solver.solve(S1, S2)}") - print(f"The minimum Edit Distance is: {min_distance_bottom_up(S1, S2)}") + print(f"The minimum edit distance is: {solver.min_dist_top_down(S1, S2)}") + print(f"The minimum edit distance is: {solver.min_dist_bottom_up(S1, S2)}") print() print("*************** End of Testing Edit Distance DP Algorithm ***************") From 0fd1ccb13358feff2d6ea8dd62200cabe363ee8e Mon Sep 17 00:00:00 2001 From: Roberts Date: Mon, 31 Oct 2022 13:31:15 +0200 Subject: [PATCH 514/726] Adding inductive reactance calculation (#6625) * Adding inductive reactance calculation * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * from math import pi * 0007957747154594767 * 36420441699332 * 2199114857512855 Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- electronics/ind_reactance.py | 69 ++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 electronics/ind_reactance.py diff --git a/electronics/ind_reactance.py b/electronics/ind_reactance.py new file mode 100644 index 000000000..3f77ef628 --- /dev/null +++ b/electronics/ind_reactance.py @@ -0,0 +1,69 @@ +# https://en.wikipedia.org/wiki/Electrical_reactance#Inductive_reactance +from __future__ import annotations + +from math import pi + + +def ind_reactance( + inductance: float, frequency: float, reactance: float +) -> dict[str, float]: + """ + Calculate inductive reactance, frequency or inductance from two given electrical + properties then return name/value pair of the zero value in a Python dict. + + Parameters + ---------- + inductance : float with units in Henries + + frequency : float with units in Hertz + + reactance : float with units in Ohms + + >>> ind_reactance(-35e-6, 1e3, 0) + Traceback (most recent call last): + ... + ValueError: Inductance cannot be negative + + >>> ind_reactance(35e-6, -1e3, 0) + Traceback (most recent call last): + ... + ValueError: Frequency cannot be negative + + >>> ind_reactance(35e-6, 0, -1) + Traceback (most recent call last): + ... + ValueError: Inductive reactance cannot be negative + + >>> ind_reactance(0, 10e3, 50) + {'inductance': 0.0007957747154594767} + + >>> ind_reactance(35e-3, 0, 50) + {'frequency': 227.36420441699332} + + >>> ind_reactance(35e-6, 1e3, 0) + {'reactance': 0.2199114857512855} + + """ + + if (inductance, frequency, reactance).count(0) != 1: + raise ValueError("One and only one argument must be 0") + if inductance < 0: + raise ValueError("Inductance cannot be negative") + if frequency < 0: + raise ValueError("Frequency cannot be negative") + if reactance < 0: + raise ValueError("Inductive reactance cannot be negative") + if inductance == 0: + return {"inductance": reactance / (2 * pi * frequency)} + elif frequency == 0: + return {"frequency": reactance / (2 * pi * inductance)} + elif reactance == 0: + return {"reactance": 2 * pi * frequency * inductance} + else: + raise ValueError("Exactly one argument must be 0") + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From b2165a65fcf1a087236d2a1527b10b64a12f69e6 Mon Sep 17 00:00:00 2001 From: Alex de la Cruz <46356295+acrulopez@users.noreply.github.com> Date: Mon, 31 Oct 2022 14:14:33 +0100 Subject: [PATCH 515/726] Added Radix Tree in data structures (#6616) * added radix tree to data structures * added doctests * solved flake8 * added type hints * added description for delete function * Update data_structures/trie/radix_tree.py * Update radix_tree.py * Update radix_tree.py * Update radix_tree.py Co-authored-by: Alex de la Cruz Co-authored-by: Christian Clauss --- data_structures/trie/radix_tree.py | 223 +++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 data_structures/trie/radix_tree.py diff --git a/data_structures/trie/radix_tree.py b/data_structures/trie/radix_tree.py new file mode 100644 index 000000000..66890346e --- /dev/null +++ b/data_structures/trie/radix_tree.py @@ -0,0 +1,223 @@ +""" +A Radix Tree is a data structure that represents a space-optimized +trie (prefix tree) in whicheach node that is the only child is merged +with its parent [https://en.wikipedia.org/wiki/Radix_tree] +""" + + +class RadixNode: + def __init__(self, prefix: str = "", is_leaf: bool = False) -> None: + # Mapping from the first character of the prefix of the node + self.nodes: dict[str, RadixNode] = {} + + # A node will be a leaf if the tree contains its word + self.is_leaf = is_leaf + + self.prefix = prefix + + def match(self, word: str) -> tuple[str, str, str]: + """Compute the common substring of the prefix of the node and a word + + Args: + word (str): word to compare + + Returns: + (str, str, str): common substring, remaining prefix, remaining word + + >>> RadixNode("myprefix").match("mystring") + ('my', 'prefix', 'string') + """ + x = 0 + for q, w in zip(self.prefix, word): + if q != w: + break + + x += 1 + + return self.prefix[:x], self.prefix[x:], word[x:] + + def insert_many(self, words: list[str]) -> None: + """Insert many words in the tree + + Args: + words (list[str]): list of words + + >>> RadixNode("myprefix").insert_many(["mystring", "hello"]) + """ + for word in words: + self.insert(word) + + def insert(self, word: str) -> None: + """Insert a word into the tree + + Args: + word (str): word to insert + + >>> RadixNode("myprefix").insert("mystring") + """ + # Case 1: If the word is the prefix of the node + # Solution: We set the current node as leaf + if self.prefix == word: + self.is_leaf = True + + # Case 2: The node has no edges that have a prefix to the word + # Solution: We create an edge from the current node to a new one + # containing the word + elif word[0] not in self.nodes: + self.nodes[word[0]] = RadixNode(prefix=word, is_leaf=True) + + else: + incoming_node = self.nodes[word[0]] + matching_string, remaining_prefix, remaining_word = incoming_node.match( + word + ) + + # Case 3: The node prefix is equal to the matching + # Solution: We insert remaining word on the next node + if remaining_prefix == "": + self.nodes[matching_string[0]].insert(remaining_word) + + # Case 4: The word is greater equal to the matching + # Solution: Create a node in between both nodes, change + # prefixes and add the new node for the remaining word + else: + incoming_node.prefix = remaining_prefix + + aux_node = self.nodes[matching_string[0]] + self.nodes[matching_string[0]] = RadixNode(matching_string, False) + self.nodes[matching_string[0]].nodes[remaining_prefix[0]] = aux_node + + if remaining_word == "": + self.nodes[matching_string[0]].is_leaf = True + else: + self.nodes[matching_string[0]].insert(remaining_word) + + def find(self, word: str) -> bool: + """Returns if the word is on the tree + + Args: + word (str): word to check + + Returns: + bool: True if the word appears on the tree + + >>> RadixNode("myprefix").find("mystring") + False + """ + incoming_node = self.nodes.get(word[0], None) + if not incoming_node: + return False + else: + matching_string, remaining_prefix, remaining_word = incoming_node.match( + word + ) + # If there is remaining prefix, the word can't be on the tree + if remaining_prefix != "": + return False + # This applies when the word and the prefix are equal + elif remaining_word == "": + return incoming_node.is_leaf + # We have word remaining so we check the next node + else: + return incoming_node.find(remaining_word) + + def delete(self, word: str) -> bool: + """Deletes a word from the tree if it exists + + Args: + word (str): word to be deleted + + Returns: + bool: True if the word was found and deleted. False if word is not found + + >>> RadixNode("myprefix").delete("mystring") + False + """ + incoming_node = self.nodes.get(word[0], None) + if not incoming_node: + return False + else: + matching_string, remaining_prefix, remaining_word = incoming_node.match( + word + ) + # If there is remaining prefix, the word can't be on the tree + if remaining_prefix != "": + return False + # We have word remaining so we check the next node + elif remaining_word != "": + return incoming_node.delete(remaining_word) + else: + # If it is not a leaf, we don't have to delete + if not incoming_node.is_leaf: + return False + else: + # We delete the nodes if no edges go from it + if len(incoming_node.nodes) == 0: + del self.nodes[word[0]] + # We merge the current node with its only child + if len(self.nodes) == 1 and not self.is_leaf: + merging_node = list(self.nodes.values())[0] + self.is_leaf = merging_node.is_leaf + self.prefix += merging_node.prefix + self.nodes = merging_node.nodes + # If there is more than 1 edge, we just mark it as non-leaf + elif len(incoming_node.nodes) > 1: + incoming_node.is_leaf = False + # If there is 1 edge, we merge it with its child + else: + merging_node = list(incoming_node.nodes.values())[0] + incoming_node.is_leaf = merging_node.is_leaf + incoming_node.prefix += merging_node.prefix + incoming_node.nodes = merging_node.nodes + + return True + + def print_tree(self, height: int = 0) -> None: + """Print the tree + + Args: + height (int, optional): Height of the printed node + """ + if self.prefix != "": + print("-" * height, self.prefix, " (leaf)" if self.is_leaf else "") + + for value in self.nodes.values(): + value.print_tree(height + 1) + + +def test_trie() -> bool: + words = "banana bananas bandana band apple all beast".split() + root = RadixNode() + root.insert_many(words) + + assert all(root.find(word) for word in words) + assert not root.find("bandanas") + assert not root.find("apps") + root.delete("all") + assert not root.find("all") + root.delete("banana") + assert not root.find("banana") + assert root.find("bananas") + + return True + + +def pytests() -> None: + assert test_trie() + + +def main() -> None: + """ + >>> pytests() + """ + root = RadixNode() + words = "banana bananas bandanas bandana band apple all beast".split() + root.insert_many(words) + + print("Words:", words) + print("Tree:") + root.print_tree() + + +if __name__ == "__main__": + main() From a31edd4477af958adb840dadd568c38eecc9567b Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 31 Oct 2022 14:50:03 +0100 Subject: [PATCH 516/726] Test on Python 3.11 (#6591) * Test on Python 3.11 release candidate 2 * tensorflow; python<3.11 * tensorflow; python_version < 3.11 * tensorflow; python_version < "3.11" * sympy, tensorflow; python_version < "3.11" * sklearn; python_version < "3.11" * matplotlib, pandas, qiskit * statsmodels; python_version < "3.11" * Bring back Pandas * Problem deps are qiskit, statsmodels, and tensorflow * updating DIRECTORY.md * python-version: 3.11-dev --> 3.11 * updating DIRECTORY.md * Add pytest --ignore to pyproject.toml * Update build.yml * Update pyproject.toml * Update pyproject.toml * Python 3.11 Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .github/workflows/build.yml | 13 +++++++++++-- CONTRIBUTING.md | 2 +- DIRECTORY.md | 1 + requirements.txt | 6 +++--- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 159ce13b3..1069c68d2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: - python-version: 3.x + python-version: 3.11 - uses: actions/cache@v3 with: path: ~/.cache/pip @@ -22,6 +22,15 @@ jobs: python -m pip install --upgrade pip setuptools six wheel python -m pip install pytest-cov -r requirements.txt - name: Run tests - run: pytest --ignore=project_euler/ --ignore=scripts/validate_solutions.py --cov-report=term-missing:skip-covered --cov=. . + # See: #6591 for re-enabling tests on Python v3.11 + run: pytest + --ignore=computer_vision/cnn_classification.py + --ignore=machine_learning/forecasting/run.py + --ignore=machine_learning/lstm/lstm_prediction.py + --ignore=quantum/ + --ignore=project_euler/ + --ignore=scripts/validate_solutions.py + --cov-report=term-missing:skip-covered + --cov=. . - if: ${{ success() }} run: scripts/build_directory_md.py 2>&1 | tee DIRECTORY.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 37e020b8f..3ce5bd1ed 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -66,7 +66,7 @@ pre-commit run --all-files --show-diff-on-failure We want your work to be readable by others; therefore, we encourage you to note the following: -- Please write in Python 3.10+. For instance: `print()` is a function in Python 3 so `print "Hello"` will *not* work but `print("Hello")` will. +- Please write in Python 3.11+. For instance: `print()` is a function in Python 3 so `print "Hello"` will *not* work but `print("Hello")` will. - Please focus hard on the naming of functions, classes, and variables. Help your reader by using __descriptive names__ that can help you to remove redundant comments. - Single letter variable names are *old school* so please avoid them unless their life only spans a few lines. - Expand acronyms because `gcd()` is hard to understand but `greatest_common_divisor()` is not. diff --git a/DIRECTORY.md b/DIRECTORY.md index be3a121c8..0b0d1e6a7 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -328,6 +328,7 @@ * [Electric Conductivity](electronics/electric_conductivity.py) * [Electric Power](electronics/electric_power.py) * [Electrical Impedance](electronics/electrical_impedance.py) + * [Ind Reactance](electronics/ind_reactance.py) * [Ohms Law](electronics/ohms_law.py) * [Resistor Equivalence](electronics/resistor_equivalence.py) * [Resonant Frequency](electronics/resonant_frequency.py) diff --git a/requirements.txt b/requirements.txt index 9ffe784c9..ae6203998 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,14 +8,14 @@ opencv-python pandas pillow projectq -qiskit +qiskit; python_version < "3.11" requests rich scikit-fuzzy sklearn -statsmodels +statsmodels; python_version < "3.11" sympy -tensorflow +tensorflow; python_version < "3.11" texttable tweepy xgboost From fecbf59436702b34b987773aa872d79f5df466df Mon Sep 17 00:00:00 2001 From: TechFreak107 <62158210+TechFreak107@users.noreply.github.com> Date: Mon, 31 Oct 2022 22:28:42 +0530 Subject: [PATCH 517/726] Modified 'pascal_triangle.py' program (#7901) * Added pascals_triangle.py program to maths directory * Deleted 'pascals_triangle.py' because of duplication. Added a optimized function to generate pascal's triangle to 'pascal_triangle.py' program. Added some aadditional doctests to the existing function. Added some type check functionality to the existing function. * Modified type check hints in 'generate_pascal_triangle_optimized' function' q * Modified 'pascal_triangle' prgram * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update pascal_triangle.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- other/pascal_triangle.py | 109 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 101 insertions(+), 8 deletions(-) diff --git a/other/pascal_triangle.py b/other/pascal_triangle.py index 5cc3cee8a..7f6555f9c 100644 --- a/other/pascal_triangle.py +++ b/other/pascal_triangle.py @@ -1,13 +1,10 @@ """ -This implementation demonstrates how to generate the -elements of a Pascal's triangle. The element having -a row index of r and column index of c can be derived -as follows: +This implementation demonstrates how to generate the elements of a Pascal's triangle. +The element havingva row index of r and column index of c can be derivedvas follows: triangle[r][c] = triangle[r-1][c-1]+triangle[r-1][c] -What is Pascal's triangle? -- It is a triangular array containing binomial coefficients. -Refer to (https://en.wikipedia.org/wiki/Pascal%27s_triangle) -for more info about this triangle. + +A Pascal's triangle is a triangular array containing binomial coefficients. +https://en.wikipedia.org/wiki/Pascal%27s_triangle """ @@ -38,6 +35,8 @@ def print_pascal_triangle(num_rows: int) -> None: def generate_pascal_triangle(num_rows: int) -> list[list[int]]: """ Create Pascal's triangle for different number of rows + >>> generate_pascal_triangle(0) + [] >>> generate_pascal_triangle(1) [[1]] >>> generate_pascal_triangle(2) @@ -48,7 +47,26 @@ def generate_pascal_triangle(num_rows: int) -> list[list[int]]: [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1]] >>> generate_pascal_triangle(5) [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1]] + >>> generate_pascal_triangle(-5) + Traceback (most recent call last): + ... + ValueError: The input value of 'num_rows' should be greater than or equal to 0 + >>> generate_pascal_triangle(7.89) + Traceback (most recent call last): + ... + TypeError: The input value of 'num_rows' should be 'int' """ + + if not isinstance(num_rows, int): + raise TypeError("The input value of 'num_rows' should be 'int'") + + if num_rows == 0: + return [] + elif num_rows < 0: + raise ValueError( + "The input value of 'num_rows' should be greater than or equal to 0" + ) + triangle: list[list[int]] = [] for current_row_idx in range(num_rows): current_row = populate_current_row(triangle, current_row_idx) @@ -90,7 +108,82 @@ def calculate_current_element( current_row[current_col_idx] = above_to_left_elt + above_to_right_elt +def generate_pascal_triangle_optimized(num_rows: int) -> list[list[int]]: + """ + This function returns a matrix representing the corresponding pascal's triangle + according to the given input of number of rows of Pascal's triangle to be generated. + It reduces the operations done to generate a row by half + by eliminating redundant calculations. + + :param num_rows: Integer specifying the number of rows in the Pascal's triangle + :return: 2-D List (matrix) representing the Pascal's triangle + + Return the Pascal's triangle of given rows + >>> generate_pascal_triangle_optimized(3) + [[1], [1, 1], [1, 2, 1]] + >>> generate_pascal_triangle_optimized(1) + [[1]] + >>> generate_pascal_triangle_optimized(0) + [] + >>> generate_pascal_triangle_optimized(-5) + Traceback (most recent call last): + ... + ValueError: The input value of 'num_rows' should be greater than or equal to 0 + >>> generate_pascal_triangle_optimized(7.89) + Traceback (most recent call last): + ... + TypeError: The input value of 'num_rows' should be 'int' + """ + + if not isinstance(num_rows, int): + raise TypeError("The input value of 'num_rows' should be 'int'") + + if num_rows == 0: + return [] + elif num_rows < 0: + raise ValueError( + "The input value of 'num_rows' should be greater than or equal to 0" + ) + + result: list[list[int]] = [[1]] + + for row_index in range(1, num_rows): + temp_row = [0] + result[-1] + [0] + row_length = row_index + 1 + # Calculate the number of distinct elements in a row + distinct_elements = sum(divmod(row_length, 2)) + row_first_half = [ + temp_row[i - 1] + temp_row[i] for i in range(1, distinct_elements + 1) + ] + row_second_half = row_first_half[: (row_index + 1) // 2] + row_second_half.reverse() + row = row_first_half + row_second_half + result.append(row) + + return result + + +def benchmark() -> None: + """ + Benchmark multiple functions, with three different length int values. + """ + from collections.abc import Callable + from timeit import timeit + + def benchmark_a_function(func: Callable, value: int) -> None: + call = f"{func.__name__}({value})" + timing = timeit(f"__main__.{call}", setup="import __main__") + # print(f"{call:38} = {func(value)} -- {timing:.4f} seconds") + print(f"{call:38} -- {timing:.4f} seconds") + + for value in range(15): # (1, 7, 14): + for func in (generate_pascal_triangle, generate_pascal_triangle_optimized): + benchmark_a_function(func, value) + print() + + if __name__ == "__main__": import doctest doctest.testmod() + benchmark() From 506b63f02da11691f19c4fd86c120e1d54842ea4 Mon Sep 17 00:00:00 2001 From: Shreyas Kamath <42207943+s18k@users.noreply.github.com> Date: Mon, 31 Oct 2022 22:34:42 +0530 Subject: [PATCH 518/726] Create convert_number_to_words.py (#6788) * Create convert_number_to_words.py A Python Program to convert numerical digits to English words. An Application of this can be in a Payment Application for confirmation * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- web_programming/convert_number_to_words.py | 111 +++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 web_programming/convert_number_to_words.py diff --git a/web_programming/convert_number_to_words.py b/web_programming/convert_number_to_words.py new file mode 100644 index 000000000..50612dec2 --- /dev/null +++ b/web_programming/convert_number_to_words.py @@ -0,0 +1,111 @@ +import math + + +def convert(number: int) -> str: + """ + Given a number return the number in words. + + >>> convert(123) + 'OneHundred,TwentyThree' + """ + if number == 0: + words = "Zero" + return words + else: + digits = math.log10(number) + digits = digits + 1 + singles = {} + singles[0] = "" + singles[1] = "One" + singles[2] = "Two" + singles[3] = "Three" + singles[4] = "Four" + singles[5] = "Five" + singles[6] = "Six" + singles[7] = "Seven" + singles[8] = "Eight" + singles[9] = "Nine" + + doubles = {} + doubles[0] = "" + doubles[2] = "Twenty" + doubles[3] = "Thirty" + doubles[4] = "Forty" + doubles[5] = "Fifty" + doubles[6] = "Sixty" + doubles[7] = "Seventy" + doubles[8] = "Eighty" + doubles[9] = "Ninety" + + teens = {} + teens[0] = "Ten" + teens[1] = "Eleven" + teens[2] = "Twelve" + teens[3] = "Thirteen" + teens[4] = "Fourteen" + teens[5] = "Fifteen" + teens[6] = "Sixteen" + teens[7] = "Seventeen" + teens[8] = "Eighteen" + teens[9] = "Nineteen" + + placevalue = {} + placevalue[2] = "Hundred," + placevalue[3] = "Thousand," + placevalue[5] = "Lakh," + placevalue[7] = "Crore," + + temp_num = number + words = "" + counter = 0 + digits = int(digits) + while counter < digits: + current = temp_num % 10 + if counter % 2 == 0: + addition = "" + if counter in placevalue.keys() and current != 0: + addition = placevalue[counter] + if counter == 2: + words = singles[current] + addition + words + elif counter == 0: + if ((temp_num % 100) // 10) == 1: + words = teens[current] + addition + words + temp_num = temp_num // 10 + counter += 1 + else: + words = singles[current] + addition + words + + else: + words = doubles[current] + addition + words + + else: + if counter == 1: + if current == 1: + words = teens[number % 10] + words + else: + addition = "" + if counter in placevalue.keys(): + addition = placevalue[counter] + words = doubles[current] + addition + words + else: + addition = "" + if counter in placevalue.keys(): + if current == 0 and ((temp_num % 100) // 10) == 0: + addition = "" + else: + addition = placevalue[counter] + if ((temp_num % 100) // 10) == 1: + words = teens[current] + addition + words + temp_num = temp_num // 10 + counter += 1 + else: + words = singles[current] + addition + words + counter += 1 + temp_num = temp_num // 10 + return words + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From ded5deabe9f9f1c8f2a57da8657056480f142b55 Mon Sep 17 00:00:00 2001 From: Shriyans Gandhi <41372639+shri30yans@users.noreply.github.com> Date: Mon, 31 Oct 2022 22:45:37 +0530 Subject: [PATCH 519/726] Dodecahedron surface area and volume (#6606) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Hexagonal number sequence A hexagonal number sequence is a sequence of figurate numbers where the nth hexagonal number hₙ is the number of distinct dots in a pattern of dots consisting of the outlines of regular hexagons with sides up to n dots, when the hexagons are overlaid so that they share one vertex. This program returns the hexagonal number sequence of n length. * Update hexagonalnumbers.py * Update hexagonalnumbers.py * Update hexagonalnumbers.py * Update hexagonalnumbers.py * Update and rename hexagonalnumbers.py to hexagonal_numbers.py * Length must be a positive integer * Create dodecahedron.py * Update dodecahedron.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update dodecahedron.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update dodecahedron.py * Update dodecahedron.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update dodecahedron.py * Update dodecahedron.py * Apply suggestions from code review Co-authored-by: Paul <56065602+ZeroDayOwl@users.noreply.github.com> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Apply suggestions from code review * Update dodecahedron.py Co-authored-by: Christian Clauss Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Paul <56065602+ZeroDayOwl@users.noreply.github.com> --- maths/dodecahedron.py | 73 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 maths/dodecahedron.py diff --git a/maths/dodecahedron.py b/maths/dodecahedron.py new file mode 100644 index 000000000..856245f4a --- /dev/null +++ b/maths/dodecahedron.py @@ -0,0 +1,73 @@ +# dodecahedron.py + +""" +A regular dodecahedron is a three-dimensional figure made up of +12 pentagon faces having the same equal size. +""" + + +def dodecahedron_surface_area(edge: float) -> float: + """ + Calculates the surface area of a regular dodecahedron + a = 3 * ((25 + 10 * (5** (1 / 2))) ** (1 / 2 )) * (e**2) + where: + a --> is the area of the dodecahedron + e --> is the length of the edge + reference-->"Dodecahedron" Study.com + + + :param edge: length of the edge of the dodecahedron + :type edge: float + :return: the surface area of the dodecahedron as a float + + + Tests: + >>> dodecahedron_surface_area(5) + 516.1432201766901 + >>> dodecahedron_surface_area(10) + 2064.5728807067603 + >>> dodecahedron_surface_area(-1) + Traceback (most recent call last): + ... + ValueError: Length must be a positive. + """ + + if edge <= 0 or not isinstance(edge, int): + raise ValueError("Length must be a positive.") + return 3 * ((25 + 10 * (5 ** (1 / 2))) ** (1 / 2)) * (edge**2) + + +def dodecahedron_volume(edge: float) -> float: + """ + Calculates the volume of a regular dodecahedron + v = ((15 + (7 * (5** (1 / 2)))) / 4) * (e**3) + where: + v --> is the volume of the dodecahedron + e --> is the length of the edge + reference-->"Dodecahedron" Study.com + + + :param edge: length of the edge of the dodecahedron + :type edge: float + :return: the volume of the dodecahedron as a float + + Tests: + >>> dodecahedron_volume(5) + 957.8898700780791 + >>> dodecahedron_volume(10) + 7663.118960624633 + >>> dodecahedron_volume(-1) + Traceback (most recent call last): + ... + ValueError: Length must be a positive. + """ + + if edge <= 0 or not isinstance(edge, int): + raise ValueError("Length must be a positive.") + return ((15 + (7 * (5 ** (1 / 2)))) / 4) * (edge**3) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 21601a4070830069101bbb0ddc2d662eac68d627 Mon Sep 17 00:00:00 2001 From: Kevin Joven <59969678+KevinJoven11@users.noreply.github.com> Date: Mon, 31 Oct 2022 13:32:54 -0400 Subject: [PATCH 520/726] create quantum_fourier_transform (#6682) * create quantum_fourier_transform This is part of the #Hacktoberfest. I build the quantum fourier transform for N qubits. (n = 3 in the example) Best, Kevin * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update q_fourier_transform.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Add the doctest! * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update q_fourier_transform.py * Pass first then fail Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- quantum/q_fourier_transform.py | 97 ++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 quantum/q_fourier_transform.py diff --git a/quantum/q_fourier_transform.py b/quantum/q_fourier_transform.py new file mode 100644 index 000000000..d138dfb45 --- /dev/null +++ b/quantum/q_fourier_transform.py @@ -0,0 +1,97 @@ +""" +Build the quantum fourier transform (qft) for a desire +number of quantum bits using Qiskit framework. This +experiment run in IBM Q simulator with 10000 shots. +This circuit can be use as a building block to design +the Shor's algorithm in quantum computing. As well as, +quantum phase estimation among others. +. +References: +https://en.wikipedia.org/wiki/Quantum_Fourier_transform +https://qiskit.org/textbook/ch-algorithms/quantum-fourier-transform.html +""" + +import math + +import numpy as np +import qiskit +from qiskit import Aer, ClassicalRegister, QuantumCircuit, QuantumRegister, execute + + +def quantum_fourier_transform(number_of_qubits: int = 3) -> qiskit.result.counts.Counts: + """ + # >>> quantum_fourier_transform(2) + # {'00': 2500, '01': 2500, '11': 2500, '10': 2500} + # quantum circuit for number_of_qubits = 3: + ┌───┐ + qr_0: ──────■──────────────────────■───────┤ H ├─X─ + │ ┌───┐ │P(π/2) └───┘ │ + qr_1: ──────┼────────■───────┤ H ├─■─────────────┼─ + ┌───┐ │P(π/4) │P(π/2) └───┘ │ + qr_2: ┤ H ├─■────────■───────────────────────────X─ + └───┘ + cr: 3/═════════════════════════════════════════════ + Args: + n : number of qubits + Returns: + qiskit.result.counts.Counts: distribute counts. + + >>> quantum_fourier_transform(2) + {'00': 2500, '01': 2500, '10': 2500, '11': 2500} + >>> quantum_fourier_transform(-1) + Traceback (most recent call last): + ... + ValueError: number of qubits must be > 0. + >>> quantum_fourier_transform('a') + Traceback (most recent call last): + ... + TypeError: number of qubits must be a integer. + >>> quantum_fourier_transform(100) + Traceback (most recent call last): + ... + ValueError: number of qubits too large to simulate(>10). + >>> quantum_fourier_transform(0.5) + Traceback (most recent call last): + ... + ValueError: number of qubits must be exact integer. + """ + if type(number_of_qubits) == str: + raise TypeError("number of qubits must be a integer.") + if not number_of_qubits > 0: + raise ValueError("number of qubits must be > 0.") + if math.floor(number_of_qubits) != number_of_qubits: + raise ValueError("number of qubits must be exact integer.") + if number_of_qubits > 10: + raise ValueError("number of qubits too large to simulate(>10).") + + qr = QuantumRegister(number_of_qubits, "qr") + cr = ClassicalRegister(number_of_qubits, "cr") + + quantum_circuit = QuantumCircuit(qr, cr) + + counter = number_of_qubits + + for i in range(counter): + + quantum_circuit.h(number_of_qubits - i - 1) + counter -= 1 + for j in range(counter): + quantum_circuit.cp(np.pi / 2 ** (counter - j), j, counter) + + for k in range(number_of_qubits // 2): + quantum_circuit.swap(k, number_of_qubits - k - 1) + + # measure all the qubits + quantum_circuit.measure(qr, cr) + # simulate with 10000 shots + backend = Aer.get_backend("qasm_simulator") + job = execute(quantum_circuit, backend, shots=10000) + + return job.result().get_counts(quantum_circuit) + + +if __name__ == "__main__": + print( + f"Total count for quantum fourier transform state is: \ + {quantum_fourier_transform(3)}" + ) From 6cd7c49525b520fc5fe44ac0568fe39393ff85b4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 31 Oct 2022 21:33:08 +0100 Subject: [PATCH 521/726] [pre-commit.ci] pre-commit autoupdate (#7920) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/asottile/pyupgrade: v3.1.0 → v3.2.0](https://github.com/asottile/pyupgrade/compare/v3.1.0...v3.2.0) * updating DIRECTORY.md Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- DIRECTORY.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 004def5e4..a0ea03b9b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,7 +27,7 @@ repos: - --profile=black - repo: https://github.com/asottile/pyupgrade - rev: v3.1.0 + rev: v3.2.0 hooks: - id: pyupgrade args: diff --git a/DIRECTORY.md b/DIRECTORY.md index 0b0d1e6a7..5c4a032db 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -238,6 +238,7 @@ * [Stack With Singly Linked List](data_structures/stacks/stack_with_singly_linked_list.py) * [Stock Span Problem](data_structures/stacks/stock_span_problem.py) * Trie + * [Radix Tree](data_structures/trie/radix_tree.py) * [Trie](data_structures/trie/trie.py) ## Digital Image Processing @@ -526,6 +527,7 @@ * [Collatz Sequence](maths/collatz_sequence.py) * [Combinations](maths/combinations.py) * [Decimal Isolate](maths/decimal_isolate.py) + * [Dodecahedron](maths/dodecahedron.py) * [Double Factorial Iterative](maths/double_factorial_iterative.py) * [Double Factorial Recursive](maths/double_factorial_recursive.py) * [Entropy](maths/entropy.py) @@ -994,6 +996,7 @@ * [Deutsch Jozsa](quantum/deutsch_jozsa.py) * [Half Adder](quantum/half_adder.py) * [Not Gate](quantum/not_gate.py) + * [Q Fourier Transform](quantum/q_fourier_transform.py) * [Q Full Adder](quantum/q_full_adder.py) * [Quantum Entanglement](quantum/quantum_entanglement.py) * [Quantum Teleportation](quantum/quantum_teleportation.py) @@ -1129,6 +1132,7 @@ ## Web Programming * [Co2 Emission](web_programming/co2_emission.py) + * [Convert Number To Words](web_programming/convert_number_to_words.py) * [Covid Stats Via Xpath](web_programming/covid_stats_via_xpath.py) * [Crawl Google Results](web_programming/crawl_google_results.py) * [Crawl Google Scholar Citation](web_programming/crawl_google_scholar_citation.py) From 6c15f526e58dbb3d3a67e613323781df39b58620 Mon Sep 17 00:00:00 2001 From: Paradact <44441385+Paradact@users.noreply.github.com> Date: Mon, 31 Oct 2022 22:50:50 +0100 Subject: [PATCH 522/726] Added Torus surface area (#7906) * Added Torus surface area * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixed error in test Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/area.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/maths/area.py b/maths/area.py index 5db7dac38..ea7216c8f 100644 --- a/maths/area.py +++ b/maths/area.py @@ -201,6 +201,40 @@ def surface_area_cylinder(radius: float, height: float) -> float: return 2 * pi * radius * (height + radius) +def surface_area_torus(torus_radius: float, tube_radius: float) -> float: + """Calculate the Area of a Torus. + Wikipedia reference: https://en.wikipedia.org/wiki/Torus + :return 4pi^2 * torus_radius * tube_radius + >>> surface_area_torus(1, 1) + 39.47841760435743 + >>> surface_area_torus(4, 3) + 473.7410112522892 + >>> surface_area_torus(3, 4) + Traceback (most recent call last): + ... + ValueError: surface_area_torus() does not support spindle or self intersecting tori + >>> surface_area_torus(1.6, 1.6) + 101.06474906715503 + >>> surface_area_torus(0, 0) + 0.0 + >>> surface_area_torus(-1, 1) + Traceback (most recent call last): + ... + ValueError: surface_area_torus() only accepts non-negative values + >>> surface_area_torus(1, -1) + Traceback (most recent call last): + ... + ValueError: surface_area_torus() only accepts non-negative values + """ + if torus_radius < 0 or tube_radius < 0: + raise ValueError("surface_area_torus() only accepts non-negative values") + if torus_radius < tube_radius: + raise ValueError( + "surface_area_torus() does not support spindle or self intersecting tori" + ) + return 4 * pow(pi, 2) * torus_radius * tube_radius + + def area_rectangle(length: float, width: float) -> float: """ Calculate the area of a rectangle. @@ -543,6 +577,7 @@ if __name__ == "__main__": print(f"Cone: {surface_area_cone(10, 20) = }") print(f"Conical Frustum: {surface_area_conical_frustum(10, 20, 30) = }") print(f"Cylinder: {surface_area_cylinder(10, 20) = }") + print(f"Torus: {surface_area_torus(20, 10) = }") print(f"Equilateral Triangle: {area_reg_polygon(3, 10) = }") print(f"Square: {area_reg_polygon(4, 10) = }") print(f"Reqular Pentagon: {area_reg_polygon(5, 10) = }") From 7addbccee72d2b18e6d095ab6675cbcb290412ce Mon Sep 17 00:00:00 2001 From: Paradact <44441385+Paradact@users.noreply.github.com> Date: Mon, 31 Oct 2022 22:51:45 +0100 Subject: [PATCH 523/726] Torus volume (#7905) * Added Torus volume algorithm * Updated Torus volume for simplicity (removed ref to vol_sphere()) * Refactoring * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/volume.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/maths/volume.py b/maths/volume.py index da4054646..1da4584c8 100644 --- a/maths/volume.py +++ b/maths/volume.py @@ -441,6 +441,34 @@ def vol_conical_frustum(height: float, radius_1: float, radius_2: float) -> floa ) +def vol_torus(torus_radius: float, tube_radius: float) -> float: + """Calculate the Volume of a Torus. + Wikipedia reference: https://en.wikipedia.org/wiki/Torus + :return 2pi^2 * torus_radius * tube_radius^2 + >>> vol_torus(1, 1) + 19.739208802178716 + >>> vol_torus(4, 3) + 710.6115168784338 + >>> vol_torus(3, 4) + 947.4820225045784 + >>> vol_torus(1.6, 1.6) + 80.85179925372404 + >>> vol_torus(0, 0) + 0.0 + >>> vol_torus(-1, 1) + Traceback (most recent call last): + ... + ValueError: vol_torus() only accepts non-negative values + >>> vol_torus(1, -1) + Traceback (most recent call last): + ... + ValueError: vol_torus() only accepts non-negative values + """ + if torus_radius < 0 or tube_radius < 0: + raise ValueError("vol_torus() only accepts non-negative values") + return 2 * pow(pi, 2) * torus_radius * pow(tube_radius, 2) + + def main(): """Print the Results of Various Volume Calculations.""" print("Volumes:") @@ -453,6 +481,7 @@ def main(): print(f"Sphere: {vol_sphere(2) = }") # ~= 33.5 print(f"Hemisphere: {vol_hemisphere(2) = }") # ~= 16.75 print(f"Circular Cylinder: {vol_circular_cylinder(2, 2) = }") # ~= 25.1 + print(f"Torus: {vol_torus(2, 2) = }") # ~= 157.9 print(f"Conical Frustum: {vol_conical_frustum(2, 2, 4) = }") # ~= 58.6 print(f"Spherical cap: {vol_spherical_cap(1, 2) = }") # ~= 5.24 print(f"Spheres intersetion: {vol_spheres_intersect(2, 2, 1) = }") # ~= 21.21 From 74aa9efa1d164e7dba56a88b4b3546232f3c3024 Mon Sep 17 00:00:00 2001 From: Gustavobflh <43830003+Gustavobflh@users.noreply.github.com> Date: Mon, 31 Oct 2022 19:04:42 -0300 Subject: [PATCH 524/726] Added a Hubble Parameter calculator file (#7921) --- physics/hubble_parameter.py | 110 ++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 physics/hubble_parameter.py diff --git a/physics/hubble_parameter.py b/physics/hubble_parameter.py new file mode 100644 index 000000000..798564722 --- /dev/null +++ b/physics/hubble_parameter.py @@ -0,0 +1,110 @@ +""" +Title : Calculating the Hubble Parameter + +Description : The Hubble parameter H is the Universe expansion rate +in any time. In cosmology is customary to use the redshift redshift +in place of time, becausethe redshift is directily mensure +in the light of galaxies moving away from us. + +So, the general relation that we obtain is + +H = hubble_constant*(radiation_density*(redshift+1)**4 + + matter_density*(redshift+1)**3 + + curvature*(redshift+1)**2 + dark_energy)**(1/2) + +where radiation_density, matter_density, dark_energy are the relativity +(the percentage) energy densities that exist +in the Universe today. Here, matter_density is the +sum of the barion density and the +dark matter. Curvature is the curvature parameter and can be written in term +of the densities by the completeness + + +curvature = 1 - (matter_density + radiation_density + dark_energy) + +Source : +https://www.sciencedirect.com/topics/mathematics/hubble-parameter +""" + + +def hubble_parameter( + hubble_constant: float, + radiation_density: float, + matter_density: float, + dark_energy: float, + redshift: float, +) -> float: + + """ + Input Parameters + ---------------- + hubble_constant: Hubble constante is the expansion rate today usually + given in km/(s*Mpc) + + radiation_density: relative radiation density today + + matter_density: relative mass density today + + dark_energy: relative dark energy density today + + redshift: the light redshift + + Returns + ------- + result : Hubble parameter in and the unit km/s/Mpc (the unit can be + changed if you want, just need to change the unit of the Hubble constant) + + >>> hubble_parameter(hubble_constant=68.3, radiation_density=1e-4, + ... matter_density=-0.3, dark_energy=0.7, redshift=1) + Traceback (most recent call last): + ... + ValueError: All input parameters must be positive + + >>> hubble_parameter(hubble_constant=68.3, radiation_density=1e-4, + ... matter_density= 1.2, dark_energy=0.7, redshift=1) + Traceback (most recent call last): + ... + ValueError: Relative densities cannot be greater than one + + >>> hubble_parameter(hubble_constant=68.3, radiation_density=1e-4, + ... matter_density= 0.3, dark_energy=0.7, redshift=0) + 68.3 + """ + parameters = [redshift, radiation_density, matter_density, dark_energy] + if any(0 > p for p in parameters): + raise ValueError("All input parameters must be positive") + + if any(1 < p for p in parameters[1:4]): + raise ValueError("Relative densities cannot be greater than one") + else: + curvature = 1 - (matter_density + radiation_density + dark_energy) + + e_2 = ( + radiation_density * (redshift + 1) ** 4 + + matter_density * (redshift + 1) ** 3 + + curvature * (redshift + 1) ** 2 + + dark_energy + ) + + hubble = hubble_constant * e_2 ** (1 / 2) + return hubble + + +if __name__ == "__main__": + import doctest + + # run doctest + doctest.testmod() + + # demo LCDM approximation + matter_density = 0.3 + + print( + hubble_parameter( + hubble_constant=68.3, + radiation_density=1e-4, + matter_density=matter_density, + dark_energy=1 - matter_density, + redshift=0, + ) + ) From 7d139ee7f1e48648cc8cf176b293d23d2ba85d13 Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Tue, 1 Nov 2022 06:50:43 +0000 Subject: [PATCH 525/726] refactor(abs): Condense `abs_min` and `abs_max` (#7881) * refactor(abs): Condense `abs_min` and `abs_max` * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/abs.py | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ maths/abs_max.py | 50 ------------------------------------ maths/abs_min.py | 35 ------------------------- 3 files changed, 66 insertions(+), 85 deletions(-) delete mode 100644 maths/abs_max.py delete mode 100644 maths/abs_min.py diff --git a/maths/abs.py b/maths/abs.py index dfea52dfb..cb0ffc8a5 100644 --- a/maths/abs.py +++ b/maths/abs.py @@ -15,6 +15,62 @@ def abs_val(num: float) -> float: return -num if num < 0 else num +def abs_min(x: list[int]) -> int: + """ + >>> abs_min([0,5,1,11]) + 0 + >>> abs_min([3,-10,-2]) + -2 + >>> abs_min([]) + Traceback (most recent call last): + ... + ValueError: abs_min() arg is an empty sequence + """ + if len(x) == 0: + raise ValueError("abs_min() arg is an empty sequence") + j = x[0] + for i in x: + if abs_val(i) < abs_val(j): + j = i + return j + + +def abs_max(x: list[int]) -> int: + """ + >>> abs_max([0,5,1,11]) + 11 + >>> abs_max([3,-10,-2]) + -10 + >>> abs_max([]) + Traceback (most recent call last): + ... + ValueError: abs_max() arg is an empty sequence + """ + if len(x) == 0: + raise ValueError("abs_max() arg is an empty sequence") + j = x[0] + for i in x: + if abs(i) > abs(j): + j = i + return j + + +def abs_max_sort(x: list[int]) -> int: + """ + >>> abs_max_sort([0,5,1,11]) + 11 + >>> abs_max_sort([3,-10,-2]) + -10 + >>> abs_max_sort([]) + Traceback (most recent call last): + ... + ValueError: abs_max_sort() arg is an empty sequence + """ + if len(x) == 0: + raise ValueError("abs_max_sort() arg is an empty sequence") + return sorted(x, key=abs)[-1] + + def test_abs_val(): """ >>> test_abs_val() @@ -23,6 +79,16 @@ def test_abs_val(): assert 34 == abs_val(34) assert 100000000000 == abs_val(-100000000000) + a = [-3, -1, 2, -11] + assert abs_max(a) == -11 + assert abs_max_sort(a) == -11 + assert abs_min(a) == -1 + if __name__ == "__main__": + import doctest + + doctest.testmod() + + test_abs_val() print(abs_val(-34)) # --> 34 diff --git a/maths/abs_max.py b/maths/abs_max.py deleted file mode 100644 index 4a4b4d9eb..000000000 --- a/maths/abs_max.py +++ /dev/null @@ -1,50 +0,0 @@ -from __future__ import annotations - - -def abs_max(x: list[int]) -> int: - """ - >>> abs_max([0,5,1,11]) - 11 - >>> abs_max([3,-10,-2]) - -10 - >>> abs_max([]) - Traceback (most recent call last): - ... - ValueError: abs_max() arg is an empty sequence - """ - if len(x) == 0: - raise ValueError("abs_max() arg is an empty sequence") - j = x[0] - for i in x: - if abs(i) > abs(j): - j = i - return j - - -def abs_max_sort(x: list[int]) -> int: - """ - >>> abs_max_sort([0,5,1,11]) - 11 - >>> abs_max_sort([3,-10,-2]) - -10 - >>> abs_max_sort([]) - Traceback (most recent call last): - ... - ValueError: abs_max_sort() arg is an empty sequence - """ - if len(x) == 0: - raise ValueError("abs_max_sort() arg is an empty sequence") - return sorted(x, key=abs)[-1] - - -def main(): - a = [1, 2, -11] - assert abs_max(a) == -11 - assert abs_max_sort(a) == -11 - - -if __name__ == "__main__": - import doctest - - doctest.testmod(verbose=True) - main() diff --git a/maths/abs_min.py b/maths/abs_min.py deleted file mode 100644 index 00dbcb025..000000000 --- a/maths/abs_min.py +++ /dev/null @@ -1,35 +0,0 @@ -from __future__ import annotations - -from .abs import abs_val - - -def abs_min(x: list[int]) -> int: - """ - >>> abs_min([0,5,1,11]) - 0 - >>> abs_min([3,-10,-2]) - -2 - >>> abs_min([]) - Traceback (most recent call last): - ... - ValueError: abs_min() arg is an empty sequence - """ - if len(x) == 0: - raise ValueError("abs_min() arg is an empty sequence") - j = x[0] - for i in x: - if abs_val(i) < abs_val(j): - j = i - return j - - -def main(): - a = [-3, -1, 2, -11] - print(abs_min(a)) # = -1 - - -if __name__ == "__main__": - import doctest - - doctest.testmod(verbose=True) - main() From d23e709aea75647540e6ba57b3a5979854e80117 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 1 Nov 2022 14:07:11 +0100 Subject: [PATCH 526/726] maths/sum_of_digits.py: Streamline benchmarks (#7914) * maths/sum_of_digits.py: Streamline benchmarks ``` sum_of_digits(262144): 19 -- 0.3128329170285724 seconds sum_of_digits_recursion(262144): 19 -- 0.34008108399575576 seconds sum_of_digits_compact(262144): 19 -- 0.6086010000435635 seconds sum_of_digits(1125899906842624): 76 -- 0.8079068749793805 seconds sum_of_digits_recursion(1125899906842624): 76 -- 0.8435653329943307 seconds sum_of_digits_compact(1125899906842624): 76 -- 1.247976207989268 seconds sum_of_digits(1267650600228229401496703205376): 115 -- 1.6441589999594726 seconds sum_of_digits_recursion(1267650600228229401496703205376): 115 -- 1.713684624992311 seconds sum_of_digits_compact(1267650600228229401496703205376): 115 -- 2.2197747920290567 seconds ``` * updating DIRECTORY.md * Update sum_of_digits.py * Update sum_of_digits.py Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- maths/sum_of_digits.py | 99 +++++------------------------------------- 1 file changed, 12 insertions(+), 87 deletions(-) diff --git a/maths/sum_of_digits.py b/maths/sum_of_digits.py index 5ad5fe6c9..d5488bb9e 100644 --- a/maths/sum_of_digits.py +++ b/maths/sum_of_digits.py @@ -1,10 +1,6 @@ -from timeit import timeit - - def sum_of_digits(n: int) -> int: """ Find the sum of digits of a number. - >>> sum_of_digits(12345) 15 >>> sum_of_digits(123) @@ -25,7 +21,6 @@ def sum_of_digits(n: int) -> int: def sum_of_digits_recursion(n: int) -> int: """ Find the sum of digits of a number using recursion - >>> sum_of_digits_recursion(12345) 15 >>> sum_of_digits_recursion(123) @@ -42,7 +37,6 @@ def sum_of_digits_recursion(n: int) -> int: def sum_of_digits_compact(n: int) -> int: """ Find the sum of digits of a number - >>> sum_of_digits_compact(12345) 15 >>> sum_of_digits_compact(123) @@ -57,93 +51,24 @@ def sum_of_digits_compact(n: int) -> int: def benchmark() -> None: """ - Benchmark code for comparing 3 functions, - with 3 different length int values. + Benchmark multiple functions, with three different length int values. """ - print("\nFor small_num = ", small_num, ":") - print( - "> sum_of_digits()", - "\t\tans =", - sum_of_digits(small_num), - "\ttime =", - timeit("z.sum_of_digits(z.small_num)", setup="import __main__ as z"), - "seconds", - ) - print( - "> sum_of_digits_recursion()", - "\tans =", - sum_of_digits_recursion(small_num), - "\ttime =", - timeit("z.sum_of_digits_recursion(z.small_num)", setup="import __main__ as z"), - "seconds", - ) - print( - "> sum_of_digits_compact()", - "\tans =", - sum_of_digits_compact(small_num), - "\ttime =", - timeit("z.sum_of_digits_compact(z.small_num)", setup="import __main__ as z"), - "seconds", - ) + from collections.abc import Callable + from timeit import timeit - print("\nFor medium_num = ", medium_num, ":") - print( - "> sum_of_digits()", - "\t\tans =", - sum_of_digits(medium_num), - "\ttime =", - timeit("z.sum_of_digits(z.medium_num)", setup="import __main__ as z"), - "seconds", - ) - print( - "> sum_of_digits_recursion()", - "\tans =", - sum_of_digits_recursion(medium_num), - "\ttime =", - timeit("z.sum_of_digits_recursion(z.medium_num)", setup="import __main__ as z"), - "seconds", - ) - print( - "> sum_of_digits_compact()", - "\tans =", - sum_of_digits_compact(medium_num), - "\ttime =", - timeit("z.sum_of_digits_compact(z.medium_num)", setup="import __main__ as z"), - "seconds", - ) + def benchmark_a_function(func: Callable, value: int) -> None: + call = f"{func.__name__}({value})" + timing = timeit(f"__main__.{call}", setup="import __main__") + print(f"{call:56} = {func(value)} -- {timing:.4f} seconds") - print("\nFor large_num = ", large_num, ":") - print( - "> sum_of_digits()", - "\t\tans =", - sum_of_digits(large_num), - "\ttime =", - timeit("z.sum_of_digits(z.large_num)", setup="import __main__ as z"), - "seconds", - ) - print( - "> sum_of_digits_recursion()", - "\tans =", - sum_of_digits_recursion(large_num), - "\ttime =", - timeit("z.sum_of_digits_recursion(z.large_num)", setup="import __main__ as z"), - "seconds", - ) - print( - "> sum_of_digits_compact()", - "\tans =", - sum_of_digits_compact(large_num), - "\ttime =", - timeit("z.sum_of_digits_compact(z.large_num)", setup="import __main__ as z"), - "seconds", - ) + for value in (262144, 1125899906842624, 1267650600228229401496703205376): + for func in (sum_of_digits, sum_of_digits_recursion, sum_of_digits_compact): + benchmark_a_function(func, value) + print() if __name__ == "__main__": - small_num = 262144 - medium_num = 1125899906842624 - large_num = 1267650600228229401496703205376 - benchmark() import doctest doctest.testmod() + benchmark() From 4e6c1c049dffdc984232fe1fce1e4791fc527d11 Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Tue, 1 Nov 2022 21:43:03 +0400 Subject: [PATCH 527/726] Is power of two (#7936) * add is power of two * fix comment * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Deal with negative numbers * Spelling: negative Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- bit_manipulation/is_power_of_two.py | 57 +++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 bit_manipulation/is_power_of_two.py diff --git a/bit_manipulation/is_power_of_two.py b/bit_manipulation/is_power_of_two.py new file mode 100644 index 000000000..023e979fe --- /dev/null +++ b/bit_manipulation/is_power_of_two.py @@ -0,0 +1,57 @@ +""" +Author : Alexander Pantyukhin +Date : November 1, 2022 + +Task: +Given a positive int number. Return True if this number is power of 2 +or False otherwise. + +Implementation notes: Use bit manipulation. +For example if the number is the power of two it's bits representation: +n = 0..100..00 +n - 1 = 0..011..11 + +n & (n - 1) - no intersections = 0 +""" + + +def is_power_of_two(number: int) -> bool: + """ + Return True if this number is power of 2 or False otherwise. + + >>> is_power_of_two(0) + True + >>> is_power_of_two(1) + True + >>> is_power_of_two(2) + True + >>> is_power_of_two(4) + True + >>> is_power_of_two(6) + False + >>> is_power_of_two(8) + True + >>> is_power_of_two(17) + False + >>> is_power_of_two(-1) + Traceback (most recent call last): + ... + ValueError: number must not be negative + >>> is_power_of_two(1.2) + Traceback (most recent call last): + ... + TypeError: unsupported operand type(s) for &: 'float' and 'float' + + # Test all powers of 2 from 0 to 10,000 + >>> all(is_power_of_two(int(2 ** i)) for i in range(10000)) + True + """ + if number < 0: + raise ValueError("number must not be negative") + return number & (number - 1) == 0 + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From f512b4d105b6f3188deced19761b6ed288378f0d Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Tue, 1 Nov 2022 19:25:39 +0000 Subject: [PATCH 528/726] refactor: Move pascals triange to maths/ (#7932) * refactor: Move pascals triange to maths/ * Update xgboost_classifier.py * statsmodels is now compatible with Python 3.11 * statsmodels is now compatible with Python 3.11 * cython>=0.29.28 * cython>=0.29.28 # For statsmodels on Python 3.11 Co-authored-by: Christian Clauss --- .github/workflows/build.yml | 1 - machine_learning/xgboost_classifier.py | 2 +- {other => matrix}/pascal_triangle.py | 0 requirements.txt | 3 ++- 4 files changed, 3 insertions(+), 3 deletions(-) rename {other => matrix}/pascal_triangle.py (100%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1069c68d2..6b9cc890b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,7 +25,6 @@ jobs: # See: #6591 for re-enabling tests on Python v3.11 run: pytest --ignore=computer_vision/cnn_classification.py - --ignore=machine_learning/forecasting/run.py --ignore=machine_learning/lstm/lstm_prediction.py --ignore=quantum/ --ignore=project_euler/ diff --git a/machine_learning/xgboost_classifier.py b/machine_learning/xgboost_classifier.py index 62a1b331b..08967f171 100644 --- a/machine_learning/xgboost_classifier.py +++ b/machine_learning/xgboost_classifier.py @@ -23,7 +23,7 @@ def data_handling(data: dict) -> tuple: def xgboost(features: np.ndarray, target: np.ndarray) -> XGBClassifier: """ - >>> xgboost(np.array([[5.1, 3.6, 1.4, 0.2]]), np.array([0])) + # THIS TEST IS BROKEN!! >>> xgboost(np.array([[5.1, 3.6, 1.4, 0.2]]), np.array([0])) XGBClassifier(base_score=0.5, booster='gbtree', callbacks=None, colsample_bylevel=1, colsample_bynode=1, colsample_bytree=1, early_stopping_rounds=None, enable_categorical=False, diff --git a/other/pascal_triangle.py b/matrix/pascal_triangle.py similarity index 100% rename from other/pascal_triangle.py rename to matrix/pascal_triangle.py diff --git a/requirements.txt b/requirements.txt index ae6203998..2e2782455 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ beautifulsoup4 +cython>=0.29.28 # For statsmodels on Python 3.11 fake_useragent keras lxml @@ -13,7 +14,7 @@ requests rich scikit-fuzzy sklearn -statsmodels; python_version < "3.11" +statsmodels sympy tensorflow; python_version < "3.11" texttable From f05baa2b2b9aeb5a9ae8184ff418a5ccdc56960a Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Wed, 2 Nov 2022 16:25:19 +0400 Subject: [PATCH 529/726] add dp up - down minimum cost for tickets (#7934) * add dp up - down minimum cost for tickets * add typints * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add new tests and checks. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add more tests * add types for the dp function * Update dynamic_programming/minimum_tickets_cost.py Co-authored-by: Christian Clauss * fix review notes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * small fix * Update dynamic_programming/minimum_tickets_cost.py Co-authored-by: Christian Clauss * Update dynamic_programming/minimum_tickets_cost.py Co-authored-by: Christian Clauss * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix tests * Update dynamic_programming/minimum_tickets_cost.py Co-authored-by: Christian Clauss * Update dynamic_programming/minimum_tickets_cost.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- dynamic_programming/minimum_tickets_cost.py | 129 ++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 dynamic_programming/minimum_tickets_cost.py diff --git a/dynamic_programming/minimum_tickets_cost.py b/dynamic_programming/minimum_tickets_cost.py new file mode 100644 index 000000000..261a5a7cf --- /dev/null +++ b/dynamic_programming/minimum_tickets_cost.py @@ -0,0 +1,129 @@ +""" +Author : Alexander Pantyukhin +Date : November 1, 2022 + +Task: +Given a list of days when you need to travel. Each day is integer from 1 to 365. +You are able to use tickets for 1 day, 7 days and 30 days. +Each ticket has a cost. + +Find the minimum cost you need to travel every day in the given list of days. + +Implementation notes: +implementation Dynamic Programming up bottom approach. + +Runtime complexity: O(n) + +The implementation was tested on the +leetcode: https://leetcode.com/problems/minimum-cost-for-tickets/ + + +Minimum Cost For Tickets +Dynamic Programming: up -> down. +""" + +from functools import lru_cache + + +def mincost_tickets(days: list[int], costs: list[int]) -> int: + """ + >>> mincost_tickets([1, 4, 6, 7, 8, 20], [2, 7, 15]) + 11 + + >>> mincost_tickets([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 30, 31], [2, 7, 15]) + 17 + + >>> mincost_tickets([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 30, 31], [2, 90, 150]) + 24 + + >>> mincost_tickets([2], [2, 90, 150]) + 2 + + >>> mincost_tickets([], [2, 90, 150]) + 0 + + >>> mincost_tickets('hello', [2, 90, 150]) + Traceback (most recent call last): + ... + ValueError: The parameter days should be a list of integers + + >>> mincost_tickets([], 'world') + Traceback (most recent call last): + ... + ValueError: The parameter costs should be a list of three integers + + >>> mincost_tickets([0.25, 2, 3, 4, 5, 6, 7, 8, 9, 10, 30, 31], [2, 90, 150]) + Traceback (most recent call last): + ... + ValueError: The parameter days should be a list of integers + + >>> mincost_tickets([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 30, 31], [2, 0.9, 150]) + Traceback (most recent call last): + ... + ValueError: The parameter costs should be a list of three integers + + >>> mincost_tickets([-1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 30, 31], [2, 90, 150]) + Traceback (most recent call last): + ... + ValueError: All days elements should be greater than 0 + + >>> mincost_tickets([2, 367], [2, 90, 150]) + Traceback (most recent call last): + ... + ValueError: All days elements should be less than 366 + + >>> mincost_tickets([2, 3, 4, 5, 6, 7, 8, 9, 10, 30, 31], []) + Traceback (most recent call last): + ... + ValueError: The parameter costs should be a list of three integers + + >>> mincost_tickets([], []) + Traceback (most recent call last): + ... + ValueError: The parameter costs should be a list of three integers + + >>> mincost_tickets([2, 3, 4, 5, 6, 7, 8, 9, 10, 30, 31], [1, 2, 3, 4]) + Traceback (most recent call last): + ... + ValueError: The parameter costs should be a list of three integers + """ + + # Validation + if not isinstance(days, list) or not all(isinstance(day, int) for day in days): + raise ValueError("The parameter days should be a list of integers") + + if len(costs) != 3 or not all(isinstance(cost, int) for cost in costs): + raise ValueError("The parameter costs should be a list of three integers") + + if len(days) == 0: + return 0 + + if min(days) <= 0: + raise ValueError("All days elements should be greater than 0") + + if max(days) >= 366: + raise ValueError("All days elements should be less than 366") + + days_set = set(days) + + @lru_cache(maxsize=None) + def dynamic_programming(index: int) -> int: + if index > 365: + return 0 + + if index not in days_set: + return dp(index + 1) + + return min( + costs[0] + dp(index + 1), + costs[1] + dp(index + 7), + costs[2] + dp(index + 30), + ) + + return dynamic_programming(1) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 598f6a26a14d815f5fd079f43787995b0f076c03 Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Wed, 2 Nov 2022 16:20:57 +0000 Subject: [PATCH 530/726] refactor: Condense `password` related files in one (#7939) * refactor: Condense `password` related files in one * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update other/password.py Co-authored-by: Christian Clauss * dynamic_programming * test: Make test input `str` * requirements.txt: Remove cython>=0.29.28 # For statsmodels on Python 3.11 Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- dynamic_programming/minimum_tickets_cost.py | 8 ++-- other/check_strong_password.py | 47 -------------------- other/{password_generator.py => password.py} | 44 +++++++++++++++++- requirements.txt | 1 - 4 files changed, 46 insertions(+), 54 deletions(-) delete mode 100644 other/check_strong_password.py rename other/{password_generator.py => password.py} (58%) diff --git a/dynamic_programming/minimum_tickets_cost.py b/dynamic_programming/minimum_tickets_cost.py index 261a5a7cf..d07056d92 100644 --- a/dynamic_programming/minimum_tickets_cost.py +++ b/dynamic_programming/minimum_tickets_cost.py @@ -112,12 +112,12 @@ def mincost_tickets(days: list[int], costs: list[int]) -> int: return 0 if index not in days_set: - return dp(index + 1) + return dynamic_programming(index + 1) return min( - costs[0] + dp(index + 1), - costs[1] + dp(index + 7), - costs[2] + dp(index + 30), + costs[0] + dynamic_programming(index + 1), + costs[1] + dynamic_programming(index + 7), + costs[2] + dynamic_programming(index + 30), ) return dynamic_programming(1) diff --git a/other/check_strong_password.py b/other/check_strong_password.py deleted file mode 100644 index 95bb327ad..000000000 --- a/other/check_strong_password.py +++ /dev/null @@ -1,47 +0,0 @@ -# This Will Check Whether A Given Password Is Strong Or Not -# It Follows The Rule that Length Of Password Should Be At Least 8 Characters -# And At Least 1 Lower, 1 Upper, 1 Number And 1 Special Character - -from string import ascii_lowercase, ascii_uppercase, digits, punctuation - - -def strong_password_detector(password: str, min_length: int = 8) -> str: - """ - >>> strong_password_detector('Hwea7$2!') - 'This is a strong Password' - - >>> strong_password_detector('Sh0r1') - 'Your Password must be at least 8 characters long' - - >>> strong_password_detector('Hello123') - 'Password should contain UPPERCASE, lowercase, numbers, special characters' - - >>> strong_password_detector('Hello1238udfhiaf038fajdvjjf!jaiuFhkqi1') - 'This is a strong Password' - - >>> strong_password_detector(0) - 'Your Password must be at least 8 characters long' - """ - - if len(str(password)) < 8: - return "Your Password must be at least 8 characters long" - - upper = any(char in ascii_uppercase for char in password) - lower = any(char in ascii_lowercase for char in password) - num = any(char in digits for char in password) - spec_char = any(char in punctuation for char in password) - - if upper and lower and num and spec_char: - return "This is a strong Password" - - else: - return ( - "Password should contain UPPERCASE, lowercase, " - "numbers, special characters" - ) - - -if __name__ == "__main__": - import doctest - - doctest.testmod() diff --git a/other/password_generator.py b/other/password.py similarity index 58% rename from other/password_generator.py rename to other/password.py index 8f9d58a33..8f6833073 100644 --- a/other/password_generator.py +++ b/other/password.py @@ -1,11 +1,12 @@ -"""Password Generator allows you to generate a random password of length N.""" import secrets from random import shuffle -from string import ascii_letters, digits, punctuation +from string import ascii_letters, ascii_lowercase, ascii_uppercase, digits, punctuation def password_generator(length: int = 8) -> str: """ + Password Generator allows you to generate a random password of length N. + >>> len(password_generator()) 8 >>> len(password_generator(length=16)) @@ -62,6 +63,45 @@ def random_characters(chars_incl, i): pass # Put your code here... +# This Will Check Whether A Given Password Is Strong Or Not +# It Follows The Rule that Length Of Password Should Be At Least 8 Characters +# And At Least 1 Lower, 1 Upper, 1 Number And 1 Special Character +def strong_password_detector(password: str, min_length: int = 8) -> str: + """ + >>> strong_password_detector('Hwea7$2!') + 'This is a strong Password' + + >>> strong_password_detector('Sh0r1') + 'Your Password must be at least 8 characters long' + + >>> strong_password_detector('Hello123') + 'Password should contain UPPERCASE, lowercase, numbers, special characters' + + >>> strong_password_detector('Hello1238udfhiaf038fajdvjjf!jaiuFhkqi1') + 'This is a strong Password' + + >>> strong_password_detector('0') + 'Your Password must be at least 8 characters long' + """ + + if len(password) < min_length: + return "Your Password must be at least 8 characters long" + + upper = any(char in ascii_uppercase for char in password) + lower = any(char in ascii_lowercase for char in password) + num = any(char in digits for char in password) + spec_char = any(char in punctuation for char in password) + + if upper and lower and num and spec_char: + return "This is a strong Password" + + else: + return ( + "Password should contain UPPERCASE, lowercase, " + "numbers, special characters" + ) + + def main(): length = int(input("Please indicate the max length of your password: ").strip()) chars_incl = input( diff --git a/requirements.txt b/requirements.txt index 2e2782455..00f31b85e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,4 @@ beautifulsoup4 -cython>=0.29.28 # For statsmodels on Python 3.11 fake_useragent keras lxml From 45b3383c3952f646e985972d1fcd772d3d9f5d3f Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 2 Nov 2022 19:20:45 +0100 Subject: [PATCH 531/726] Flake8: Drop ignore of issue A003 (#7949) * Flake8: Drop ignore of issue A003 * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .flake8 | 4 +-- DIRECTORY.md | 10 +++--- data_structures/binary_tree/fenwick_tree.py | 8 ++--- data_structures/heap/heap.py | 7 ----- .../linked_list/merge_two_lists.py | 4 +-- data_structures/queue/double_ended_queue.py | 31 +++++++++---------- linear_algebra/src/lib.py | 12 ------- other/lfu_cache.py | 14 ++++----- other/lru_cache.py | 14 ++++----- 9 files changed, 42 insertions(+), 62 deletions(-) diff --git a/.flake8 b/.flake8 index 0d9ef18d1..2bb36b71a 100644 --- a/.flake8 +++ b/.flake8 @@ -1,8 +1,8 @@ [flake8] max-line-length = 88 -max-complexity = 25 +# max-complexity should be 10 +max-complexity = 23 extend-ignore = - A003 # Class attribute is shadowing a python builtin # Formatting style for `black` E203 # Whitespace before ':' W503 # Line break occurred before a binary operator diff --git a/DIRECTORY.md b/DIRECTORY.md index 5c4a032db..a2112bcfb 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -48,6 +48,7 @@ * [Highest Set Bit](bit_manipulation/highest_set_bit.py) * [Index Of Rightmost Set Bit](bit_manipulation/index_of_rightmost_set_bit.py) * [Is Even](bit_manipulation/is_even.py) + * [Is Power Of Two](bit_manipulation/is_power_of_two.py) * [Reverse Bits](bit_manipulation/reverse_bits.py) * [Single Bit Manipulation Operations](bit_manipulation/single_bit_manipulation_operations.py) @@ -315,6 +316,7 @@ * [Minimum Partition](dynamic_programming/minimum_partition.py) * [Minimum Squares To Represent A Number](dynamic_programming/minimum_squares_to_represent_a_number.py) * [Minimum Steps To One](dynamic_programming/minimum_steps_to_one.py) + * [Minimum Tickets Cost](dynamic_programming/minimum_tickets_cost.py) * [Optimal Binary Search Tree](dynamic_programming/optimal_binary_search_tree.py) * [Palindrome Partitioning](dynamic_programming/palindrome_partitioning.py) * [Rod Cutting](dynamic_programming/rod_cutting.py) @@ -496,8 +498,6 @@ ## Maths * [3N Plus 1](maths/3n_plus_1.py) * [Abs](maths/abs.py) - * [Abs Max](maths/abs_max.py) - * [Abs Min](maths/abs_min.py) * [Add](maths/add.py) * [Addition Without Arithmetic](maths/addition_without_arithmetic.py) * [Aliquot Sum](maths/aliquot_sum.py) @@ -653,6 +653,7 @@ * [Matrix Operation](matrix/matrix_operation.py) * [Max Area Of Island](matrix/max_area_of_island.py) * [Nth Fibonacci Using Matrix Exponentiation](matrix/nth_fibonacci_using_matrix_exponentiation.py) + * [Pascal Triangle](matrix/pascal_triangle.py) * [Rotate Matrix](matrix/rotate_matrix.py) * [Searching In Sorted Matrix](matrix/searching_in_sorted_matrix.py) * [Sherman Morrison](matrix/sherman_morrison.py) @@ -674,7 +675,6 @@ ## Other * [Activity Selection](other/activity_selection.py) * [Alternative List Arrange](other/alternative_list_arrange.py) - * [Check Strong Password](other/check_strong_password.py) * [Davisb Putnamb Logemannb Loveland](other/davisb_putnamb_logemannb_loveland.py) * [Dijkstra Bankers Algorithm](other/dijkstra_bankers_algorithm.py) * [Doomsday](other/doomsday.py) @@ -689,8 +689,7 @@ * [Magicdiamondpattern](other/magicdiamondpattern.py) * [Maximum Subarray](other/maximum_subarray.py) * [Nested Brackets](other/nested_brackets.py) - * [Pascal Triangle](other/pascal_triangle.py) - * [Password Generator](other/password_generator.py) + * [Password](other/password.py) * [Quine](other/quine.py) * [Scoring Algorithm](other/scoring_algorithm.py) * [Sdes](other/sdes.py) @@ -701,6 +700,7 @@ * [Casimir Effect](physics/casimir_effect.py) * [Centripetal Force](physics/centripetal_force.py) * [Horizontal Projectile Motion](physics/horizontal_projectile_motion.py) + * [Hubble Parameter](physics/hubble_parameter.py) * [Ideal Gas Law](physics/ideal_gas_law.py) * [Kinetic Energy](physics/kinetic_energy.py) * [Lorentz Transformation Four Vector](physics/lorentz_transformation_four_vector.py) diff --git a/data_structures/binary_tree/fenwick_tree.py b/data_structures/binary_tree/fenwick_tree.py index 96020d142..babd75ac4 100644 --- a/data_structures/binary_tree/fenwick_tree.py +++ b/data_structures/binary_tree/fenwick_tree.py @@ -46,7 +46,7 @@ class FenwickTree: self.size = len(arr) self.tree = deepcopy(arr) for i in range(1, self.size): - j = self.next(i) + j = self.next_(i) if j < self.size: self.tree[j] += self.tree[i] @@ -64,13 +64,13 @@ class FenwickTree: """ arr = self.tree[:] for i in range(self.size - 1, 0, -1): - j = self.next(i) + j = self.next_(i) if j < self.size: arr[j] -= arr[i] return arr @staticmethod - def next(index: int) -> int: + def next_(index: int) -> int: return index + (index & (-index)) @staticmethod @@ -102,7 +102,7 @@ class FenwickTree: return while index < self.size: self.tree[index] += value - index = self.next(index) + index = self.next_(index) def update(self, index: int, value: int) -> None: """ diff --git a/data_structures/heap/heap.py b/data_structures/heap/heap.py index 071790d18..b14c55d9d 100644 --- a/data_structures/heap/heap.py +++ b/data_structures/heap/heap.py @@ -88,13 +88,6 @@ class Heap: for i in range(self.heap_size // 2 - 1, -1, -1): self.max_heapify(i) - def max(self) -> float: - """return the max in the heap""" - if self.heap_size >= 1: - return self.h[0] - else: - raise Exception("Empty heap") - def extract_max(self) -> float: """get and remove max from heap""" if self.heap_size >= 2: diff --git a/data_structures/linked_list/merge_two_lists.py b/data_structures/linked_list/merge_two_lists.py index 93cf7a7e1..61e2412aa 100644 --- a/data_structures/linked_list/merge_two_lists.py +++ b/data_structures/linked_list/merge_two_lists.py @@ -13,7 +13,7 @@ test_data_even = (4, 6, 2, 0, 8, 10, 3, -2) @dataclass class Node: data: int - next: Node | None + next_node: Node | None class SortedLinkedList: @@ -32,7 +32,7 @@ class SortedLinkedList: node = self.head while node: yield node.data - node = node.next + node = node.next_node def __len__(self) -> int: """ diff --git a/data_structures/queue/double_ended_queue.py b/data_structures/queue/double_ended_queue.py index 7053879d4..11942db83 100644 --- a/data_structures/queue/double_ended_queue.py +++ b/data_structures/queue/double_ended_queue.py @@ -42,8 +42,8 @@ class Deque: """ val: Any = None - next: Deque._Node | None = None - prev: Deque._Node | None = None + next_node: Deque._Node | None = None + prev_node: Deque._Node | None = None class _Iterator: """ @@ -81,7 +81,7 @@ class Deque: # finished iterating raise StopIteration val = self._cur.val - self._cur = self._cur.next + self._cur = self._cur.next_node return val @@ -128,8 +128,8 @@ class Deque: self._len = 1 else: # connect nodes - self._back.next = node - node.prev = self._back + self._back.next_node = node + node.prev_node = self._back self._back = node # assign new back to the new node self._len += 1 @@ -170,8 +170,8 @@ class Deque: self._len = 1 else: # connect nodes - node.next = self._front - self._front.prev = node + node.next_node = self._front + self._front.prev_node = node self._front = node # assign new front to the new node self._len += 1 @@ -264,10 +264,9 @@ class Deque: assert not self.is_empty(), "Deque is empty." topop = self._back - self._back = self._back.prev # set new back - self._back.next = ( - None # drop the last node - python will deallocate memory automatically - ) + self._back = self._back.prev_node # set new back + # drop the last node - python will deallocate memory automatically + self._back.next_node = None self._len -= 1 @@ -300,8 +299,8 @@ class Deque: assert not self.is_empty(), "Deque is empty." topop = self._front - self._front = self._front.next # set new front and drop the first node - self._front.prev = None + self._front = self._front.next_node # set new front and drop the first node + self._front.prev_node = None self._len -= 1 @@ -385,8 +384,8 @@ class Deque: # compare every value if me.val != oth.val: return False - me = me.next - oth = oth.next + me = me.next_node + oth = oth.next_node return True @@ -424,7 +423,7 @@ class Deque: while aux is not None: # append the values in a list to display values_list.append(aux.val) - aux = aux.next + aux = aux.next_node return "[" + ", ".join(repr(val) for val in values_list) + "]" diff --git a/linear_algebra/src/lib.py b/linear_algebra/src/lib.py index 079731487..775e0244a 100644 --- a/linear_algebra/src/lib.py +++ b/linear_algebra/src/lib.py @@ -40,7 +40,6 @@ class Vector: __sub__(other: Vector): vector subtraction __mul__(other: float): scalar multiplication __mul__(other: Vector): dot product - set(components: Collection[float]): changes the vector components copy(): copies this vector and returns it component(i): gets the i-th component (0-indexed) change_component(pos: int, value: float): changes specified component @@ -119,17 +118,6 @@ class Vector: else: # error case raise Exception("invalid operand!") - def set(self, components: Collection[float]) -> None: - """ - input: new components - changes the components of the vector. - replaces the components with newer one. - """ - if len(components) > 0: - self.__components = list(components) - else: - raise Exception("please give any vector") - def copy(self) -> Vector: """ copies this vector and returns it. diff --git a/other/lfu_cache.py b/other/lfu_cache.py index 2f26bb6cc..b68ba3a46 100644 --- a/other/lfu_cache.py +++ b/other/lfu_cache.py @@ -166,14 +166,14 @@ class LFUCache(Generic[T, U]): or as a function decorator. >>> cache = LFUCache(2) - >>> cache.set(1, 1) - >>> cache.set(2, 2) + >>> cache.put(1, 1) + >>> cache.put(2, 2) >>> cache.get(1) 1 - >>> cache.set(3, 3) + >>> cache.put(3, 3) >>> cache.get(2) is None True - >>> cache.set(4, 4) + >>> cache.put(4, 4) >>> cache.get(1) is None True >>> cache.get(3) @@ -224,7 +224,7 @@ class LFUCache(Generic[T, U]): >>> 1 in cache False - >>> cache.set(1, 1) + >>> cache.put(1, 1) >>> 1 in cache True """ @@ -250,7 +250,7 @@ class LFUCache(Generic[T, U]): self.miss += 1 return None - def set(self, key: T, value: U) -> None: + def put(self, key: T, value: U) -> None: """ Sets the value for the input key and updates the Double Linked List """ @@ -297,7 +297,7 @@ class LFUCache(Generic[T, U]): result = cls.decorator_function_to_instance_map[func].get(args[0]) if result is None: result = func(*args) - cls.decorator_function_to_instance_map[func].set(args[0], result) + cls.decorator_function_to_instance_map[func].put(args[0], result) return result def cache_info() -> LFUCache[T, U]: diff --git a/other/lru_cache.py b/other/lru_cache.py index aa910e487..1e5eeac45 100644 --- a/other/lru_cache.py +++ b/other/lru_cache.py @@ -150,8 +150,8 @@ class LRUCache(Generic[T, U]): >>> cache = LRUCache(2) - >>> cache.set(1, 1) - >>> cache.set(2, 2) + >>> cache.put(1, 1) + >>> cache.put(2, 2) >>> cache.get(1) 1 @@ -166,7 +166,7 @@ class LRUCache(Generic[T, U]): {1: Node: key: 1, val: 1, has next: True, has prev: True, \ 2: Node: key: 2, val: 2, has next: True, has prev: True} - >>> cache.set(3, 3) + >>> cache.put(3, 3) >>> cache.list DoubleLinkedList, @@ -182,7 +182,7 @@ class LRUCache(Generic[T, U]): >>> cache.get(2) is None True - >>> cache.set(4, 4) + >>> cache.put(4, 4) >>> cache.get(1) is None True @@ -238,7 +238,7 @@ class LRUCache(Generic[T, U]): >>> 1 in cache False - >>> cache.set(1, 1) + >>> cache.put(1, 1) >>> 1 in cache True @@ -266,7 +266,7 @@ class LRUCache(Generic[T, U]): self.miss += 1 return None - def set(self, key: T, value: U) -> None: + def put(self, key: T, value: U) -> None: """ Sets the value for the input key and updates the Double Linked List """ @@ -315,7 +315,7 @@ class LRUCache(Generic[T, U]): result = cls.decorator_function_to_instance_map[func].get(args[0]) if result is None: result = func(*args) - cls.decorator_function_to_instance_map[func].set(args[0], result) + cls.decorator_function_to_instance_map[func].put(args[0], result) return result def cache_info() -> LRUCache[T, U]: From db5215f60e31820dba5525e8b5fbf3e73b76b8df Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Wed, 2 Nov 2022 21:40:25 +0300 Subject: [PATCH 532/726] Reduce the complexity of linear_algebra/src/polynom_for_points.py (#7948) * updating DIRECTORY.md * updating DIRECTORY.md * updating DIRECTORY.md * Lower the --max-complexity threshold in the file .flake8 * Reduce the complexity of linear_algebra/src/polynom_for_points.py * Update linear_algebra/src/polynom_for_points.py Co-authored-by: Christian Clauss * Update linear_algebra/src/polynom_for_points.py Co-authored-by: Christian Clauss * Fix Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss --- .flake8 | 2 +- linear_algebra/src/polynom_for_points.py | 139 ++++++++++------------- 2 files changed, 62 insertions(+), 79 deletions(-) diff --git a/.flake8 b/.flake8 index 2bb36b71a..1a62d57f9 100644 --- a/.flake8 +++ b/.flake8 @@ -1,7 +1,7 @@ [flake8] max-line-length = 88 # max-complexity should be 10 -max-complexity = 23 +max-complexity = 21 extend-ignore = # Formatting style for `black` E203 # Whitespace before ':' diff --git a/linear_algebra/src/polynom_for_points.py b/linear_algebra/src/polynom_for_points.py index 091849542..1d702deb1 100644 --- a/linear_algebra/src/polynom_for_points.py +++ b/linear_algebra/src/polynom_for_points.py @@ -24,96 +24,79 @@ def points_to_polynomial(coordinates: list[list[int]]) -> str: >>> print(points_to_polynomial([[1, 5], [2, 2], [3, 9]])) f(x)=x^2*5.0+x^1*-18.0+x^0*18.0 """ - try: - check = 1 - more_check = 0 - d = coordinates[0][0] - for j in range(len(coordinates)): - if j == 0: - continue - if d == coordinates[j][0]: - more_check += 1 - solved = "x=" + str(coordinates[j][0]) - if more_check == len(coordinates) - 1: - check = 2 - break - elif more_check > 0 and more_check != len(coordinates) - 1: - check = 3 - else: - check = 1 + if len(coordinates) == 0 or not all(len(pair) == 2 for pair in coordinates): + return "The program cannot work out a fitting polynomial." - if len(coordinates) == 1 and coordinates[0][0] == 0: - check = 2 - solved = "x=0" - except Exception: - check = 3 + if len({tuple(pair) for pair in coordinates}) != len(coordinates): + return "The program cannot work out a fitting polynomial." + + set_x = {x for x, _ in coordinates} + if len(set_x) == 1: + return f"x={coordinates[0][0]}" + + if len(set_x) != len(coordinates): + return "The program cannot work out a fitting polynomial." x = len(coordinates) - if check == 1: - count_of_line = 0 - matrix: list[list[float]] = [] - # put the x and x to the power values in a matrix - while count_of_line < x: - count_in_line = 0 - a = coordinates[count_of_line][0] - count_line: list[float] = [] - while count_in_line < x: - count_line.append(a ** (x - (count_in_line + 1))) - count_in_line += 1 - matrix.append(count_line) - count_of_line += 1 + count_of_line = 0 + matrix: list[list[float]] = [] + # put the x and x to the power values in a matrix + while count_of_line < x: + count_in_line = 0 + a = coordinates[count_of_line][0] + count_line: list[float] = [] + while count_in_line < x: + count_line.append(a ** (x - (count_in_line + 1))) + count_in_line += 1 + matrix.append(count_line) + count_of_line += 1 - count_of_line = 0 - # put the y values into a vector - vector: list[float] = [] - while count_of_line < x: - vector.append(coordinates[count_of_line][1]) - count_of_line += 1 + count_of_line = 0 + # put the y values into a vector + vector: list[float] = [] + while count_of_line < x: + vector.append(coordinates[count_of_line][1]) + count_of_line += 1 - count = 0 + count = 0 - while count < x: - zahlen = 0 - while zahlen < x: - if count == zahlen: - zahlen += 1 - if zahlen == x: - break - bruch = matrix[zahlen][count] / matrix[count][count] - for counting_columns, item in enumerate(matrix[count]): - # manipulating all the values in the matrix - matrix[zahlen][counting_columns] -= item * bruch - # manipulating the values in the vector - vector[zahlen] -= vector[count] * bruch + while count < x: + zahlen = 0 + while zahlen < x: + if count == zahlen: zahlen += 1 - count += 1 + if zahlen == x: + break + bruch = matrix[zahlen][count] / matrix[count][count] + for counting_columns, item in enumerate(matrix[count]): + # manipulating all the values in the matrix + matrix[zahlen][counting_columns] -= item * bruch + # manipulating the values in the vector + vector[zahlen] -= vector[count] * bruch + zahlen += 1 + count += 1 - count = 0 - # make solutions - solution: list[str] = [] - while count < x: - solution.append(str(vector[count] / matrix[count][count])) - count += 1 + count = 0 + # make solutions + solution: list[str] = [] + while count < x: + solution.append(str(vector[count] / matrix[count][count])) + count += 1 - count = 0 - solved = "f(x)=" + count = 0 + solved = "f(x)=" - while count < x: - remove_e: list[str] = solution[count].split("E") - if len(remove_e) > 1: - solution[count] = remove_e[0] + "*10^" + remove_e[1] - solved += "x^" + str(x - (count + 1)) + "*" + str(solution[count]) - if count + 1 != x: - solved += "+" - count += 1 + while count < x: + remove_e: list[str] = solution[count].split("E") + if len(remove_e) > 1: + solution[count] = f"{remove_e[0]}*10^{remove_e[1]}" + solved += f"x^{x - (count + 1)}*{solution[count]}" + if count + 1 != x: + solved += "+" + count += 1 - return solved - - elif check == 2: - return solved - else: - return "The program cannot work out a fitting polynomial." + return solved if __name__ == "__main__": From a02de964d137b803aad9bb9c9d7096eff62539fd Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Thu, 3 Nov 2022 00:16:44 +0300 Subject: [PATCH 533/726] Reduce the complexity of graphs/minimum_spanning_tree_prims.py (#7952) * Lower the --max-complexity threshold in the file .flake8 * Add test * Reduce the complexity of graphs/minimum_spanning_tree_prims.py * Remove backslashes * Remove # noqa: E741 * Fix the flake8 E741 issues * Refactor * Fix --- .flake8 | 2 +- graphs/minimum_spanning_tree_prims.py | 127 +++++++++++++++----------- 2 files changed, 76 insertions(+), 53 deletions(-) diff --git a/.flake8 b/.flake8 index 1a62d57f9..834d1f63d 100644 --- a/.flake8 +++ b/.flake8 @@ -1,7 +1,7 @@ [flake8] max-line-length = 88 # max-complexity should be 10 -max-complexity = 21 +max-complexity = 20 extend-ignore = # Formatting style for `black` E203 # Whitespace before ':' diff --git a/graphs/minimum_spanning_tree_prims.py b/graphs/minimum_spanning_tree_prims.py index 5b2eaa4bf..f577866f0 100644 --- a/graphs/minimum_spanning_tree_prims.py +++ b/graphs/minimum_spanning_tree_prims.py @@ -2,40 +2,45 @@ import sys from collections import defaultdict -def prisms_algorithm(l): # noqa: E741 +class Heap: + def __init__(self): + self.node_position = [] - node_position = [] + def get_position(self, vertex): + return self.node_position[vertex] - def get_position(vertex): - return node_position[vertex] + def set_position(self, vertex, pos): + self.node_position[vertex] = pos - def set_position(vertex, pos): - node_position[vertex] = pos - - def top_to_bottom(heap, start, size, positions): + def top_to_bottom(self, heap, start, size, positions): if start > size // 2 - 1: return else: if 2 * start + 2 >= size: - m = 2 * start + 1 + smallest_child = 2 * start + 1 else: if heap[2 * start + 1] < heap[2 * start + 2]: - m = 2 * start + 1 + smallest_child = 2 * start + 1 else: - m = 2 * start + 2 - if heap[m] < heap[start]: - temp, temp1 = heap[m], positions[m] - heap[m], positions[m] = heap[start], positions[start] + smallest_child = 2 * start + 2 + if heap[smallest_child] < heap[start]: + temp, temp1 = heap[smallest_child], positions[smallest_child] + heap[smallest_child], positions[smallest_child] = ( + heap[start], + positions[start], + ) heap[start], positions[start] = temp, temp1 - temp = get_position(positions[m]) - set_position(positions[m], get_position(positions[start])) - set_position(positions[start], temp) + temp = self.get_position(positions[smallest_child]) + self.set_position( + positions[smallest_child], self.get_position(positions[start]) + ) + self.set_position(positions[start], temp) - top_to_bottom(heap, m, size, positions) + self.top_to_bottom(heap, smallest_child, size, positions) # Update function if value of any node in min-heap decreases - def bottom_to_top(val, index, heap, position): + def bottom_to_top(self, val, index, heap, position): temp = position[index] while index != 0: @@ -47,70 +52,88 @@ def prisms_algorithm(l): # noqa: E741 if val < heap[parent]: heap[index] = heap[parent] position[index] = position[parent] - set_position(position[parent], index) + self.set_position(position[parent], index) else: heap[index] = val position[index] = temp - set_position(temp, index) + self.set_position(temp, index) break index = parent else: heap[0] = val position[0] = temp - set_position(temp, 0) + self.set_position(temp, 0) - def heapify(heap, positions): + def heapify(self, heap, positions): start = len(heap) // 2 - 1 for i in range(start, -1, -1): - top_to_bottom(heap, i, len(heap), positions) + self.top_to_bottom(heap, i, len(heap), positions) - def delete_minimum(heap, positions): + def delete_minimum(self, heap, positions): temp = positions[0] heap[0] = sys.maxsize - top_to_bottom(heap, 0, len(heap), positions) + self.top_to_bottom(heap, 0, len(heap), positions) return temp - visited = [0 for i in range(len(l))] - nbr_tv = [-1 for i in range(len(l))] # Neighboring Tree Vertex of selected vertex + +def prisms_algorithm(adjacency_list): + """ + >>> adjacency_list = {0: [[1, 1], [3, 3]], + ... 1: [[0, 1], [2, 6], [3, 5], [4, 1]], + ... 2: [[1, 6], [4, 5], [5, 2]], + ... 3: [[0, 3], [1, 5], [4, 1]], + ... 4: [[1, 1], [2, 5], [3, 1], [5, 4]], + ... 5: [[2, 2], [4, 4]]} + >>> prisms_algorithm(adjacency_list) + [(0, 1), (1, 4), (4, 3), (4, 5), (5, 2)] + """ + + heap = Heap() + + visited = [0] * len(adjacency_list) + nbr_tv = [-1] * len(adjacency_list) # Neighboring Tree Vertex of selected vertex # Minimum Distance of explored vertex with neighboring vertex of partial tree # formed in graph distance_tv = [] # Heap of Distance of vertices from their neighboring vertex positions = [] - for x in range(len(l)): - p = sys.maxsize - distance_tv.append(p) - positions.append(x) - node_position.append(x) + for vertex in range(len(adjacency_list)): + distance_tv.append(sys.maxsize) + positions.append(vertex) + heap.node_position.append(vertex) tree_edges = [] visited[0] = 1 distance_tv[0] = sys.maxsize - for x in l[0]: - nbr_tv[x[0]] = 0 - distance_tv[x[0]] = x[1] - heapify(distance_tv, positions) + for neighbor, distance in adjacency_list[0]: + nbr_tv[neighbor] = 0 + distance_tv[neighbor] = distance + heap.heapify(distance_tv, positions) - for _ in range(1, len(l)): - vertex = delete_minimum(distance_tv, positions) + for _ in range(1, len(adjacency_list)): + vertex = heap.delete_minimum(distance_tv, positions) if visited[vertex] == 0: tree_edges.append((nbr_tv[vertex], vertex)) visited[vertex] = 1 - for v in l[vertex]: - if visited[v[0]] == 0 and v[1] < distance_tv[get_position(v[0])]: - distance_tv[get_position(v[0])] = v[1] - bottom_to_top(v[1], get_position(v[0]), distance_tv, positions) - nbr_tv[v[0]] = vertex + for neighbor, distance in adjacency_list[vertex]: + if ( + visited[neighbor] == 0 + and distance < distance_tv[heap.get_position(neighbor)] + ): + distance_tv[heap.get_position(neighbor)] = distance + heap.bottom_to_top( + distance, heap.get_position(neighbor), distance_tv, positions + ) + nbr_tv[neighbor] = vertex return tree_edges if __name__ == "__main__": # pragma: no cover # < --------- Prims Algorithm --------- > - n = int(input("Enter number of vertices: ").strip()) - e = int(input("Enter number of edges: ").strip()) - adjlist = defaultdict(list) - for x in range(e): - l = [int(x) for x in input().strip().split()] # noqa: E741 - adjlist[l[0]].append([l[1], l[2]]) - adjlist[l[1]].append([l[0], l[2]]) - print(prisms_algorithm(adjlist)) + edges_number = int(input("Enter number of edges: ").strip()) + adjacency_list = defaultdict(list) + for _ in range(edges_number): + edge = [int(x) for x in input().strip().split()] + adjacency_list[edge[0]].append([edge[1], edge[2]]) + adjacency_list[edge[1]].append([edge[0], edge[2]]) + print(prisms_algorithm(adjacency_list)) From 978414bd50ae294352e0e4d93566f49074450857 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Thu, 3 Nov 2022 01:56:30 +0300 Subject: [PATCH 534/726] Reduce the complexity of other/graham_scan.py (#7953) * Reduce the complexity of other/graham_scan.py * Lower the --max-complexity threshold in the file .flake8 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix tests * Update other/graham_scan.py Co-authored-by: Christian Clauss * Update graham_scan.py * Update other/graham_scan.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .flake8 | 2 +- other/graham_scan.py | 150 ++++++++++++++++++++++--------------------- 2 files changed, 77 insertions(+), 75 deletions(-) diff --git a/.flake8 b/.flake8 index 834d1f63d..2f74f421d 100644 --- a/.flake8 +++ b/.flake8 @@ -1,7 +1,7 @@ [flake8] max-line-length = 88 # max-complexity should be 10 -max-complexity = 20 +max-complexity = 19 extend-ignore = # Formatting style for `black` E203 # Whitespace before ':' diff --git a/other/graham_scan.py b/other/graham_scan.py index 91bb6812f..8e83bfcf4 100644 --- a/other/graham_scan.py +++ b/other/graham_scan.py @@ -14,6 +14,82 @@ from math import atan2, degrees from sys import maxsize +# traversal from the lowest and the most left point in anti-clockwise direction +# if direction gets right, the previous point is not the convex hull. +class Direction(Enum): + left = 1 + straight = 2 + right = 3 + + def __repr__(self): + return f"{self.__class__.__name__}.{self.name}" + + +def angle_comparer(point: tuple[int, int], minx: int, miny: int) -> float: + """Return the angle toward to point from (minx, miny) + + :param point: The target point + minx: The starting point's x + miny: The starting point's y + :return: the angle + + Examples: + >>> angle_comparer((1,1), 0, 0) + 45.0 + + >>> angle_comparer((100,1), 10, 10) + -5.710593137499642 + + >>> angle_comparer((5,5), 2, 3) + 33.690067525979785 + """ + # sort the points accorgind to the angle from the lowest and the most left point + x, y = point + return degrees(atan2(y - miny, x - minx)) + + +def check_direction( + starting: tuple[int, int], via: tuple[int, int], target: tuple[int, int] +) -> Direction: + """Return the direction toward to the line from via to target from starting + + :param starting: The starting point + via: The via point + target: The target point + :return: the Direction + + Examples: + >>> check_direction((1,1), (2,2), (3,3)) + Direction.straight + + >>> check_direction((60,1), (-50,199), (30,2)) + Direction.left + + >>> check_direction((0,0), (5,5), (10,0)) + Direction.right + """ + x0, y0 = starting + x1, y1 = via + x2, y2 = target + via_angle = degrees(atan2(y1 - y0, x1 - x0)) + via_angle %= 360 + target_angle = degrees(atan2(y2 - y0, x2 - x0)) + target_angle %= 360 + # t- + # \ \ + # \ v + # \| + # s + # via_angle is always lower than target_angle, if direction is left. + # If they are same, it means they are on a same line of convex hull. + if target_angle > via_angle: + return Direction.left + elif target_angle == via_angle: + return Direction.straight + else: + return Direction.right + + def graham_scan(points: list[tuple[int, int]]) -> list[tuple[int, int]]: """Pure implementation of graham scan algorithm in Python @@ -57,86 +133,12 @@ def graham_scan(points: list[tuple[int, int]]) -> list[tuple[int, int]]: # remove the lowest and the most left point from points for preparing for sort points.pop(minidx) - def angle_comparer(point: tuple[int, int], minx: int, miny: int) -> float: - """Return the angle toward to point from (minx, miny) - - :param point: The target point - minx: The starting point's x - miny: The starting point's y - :return: the angle - - Examples: - >>> angle_comparer((1,1), 0, 0) - 45.0 - - >>> angle_comparer((100,1), 10, 10) - -5.710593137499642 - - >>> angle_comparer((5,5), 2, 3) - 33.690067525979785 - """ - # sort the points accorgind to the angle from the lowest and the most left point - x = point[0] - y = point[1] - angle = degrees(atan2(y - miny, x - minx)) - return angle - sorted_points = sorted(points, key=lambda point: angle_comparer(point, minx, miny)) # This insert actually costs complexity, # and you should instead add (minx, miny) into stack later. # I'm using insert just for easy understanding. sorted_points.insert(0, (minx, miny)) - # traversal from the lowest and the most left point in anti-clockwise direction - # if direction gets right, the previous point is not the convex hull. - class Direction(Enum): - left = 1 - straight = 2 - right = 3 - - def check_direction( - starting: tuple[int, int], via: tuple[int, int], target: tuple[int, int] - ) -> Direction: - """Return the direction toward to the line from via to target from starting - - :param starting: The starting point - via: The via point - target: The target point - :return: the Direction - - Examples: - >>> check_direction((1,1), (2,2), (3,3)) - Direction.straight - - >>> check_direction((60,1), (-50,199), (30,2)) - Direction.left - - >>> check_direction((0,0), (5,5), (10,0)) - Direction.right - """ - x0, y0 = starting - x1, y1 = via - x2, y2 = target - via_angle = degrees(atan2(y1 - y0, x1 - x0)) - if via_angle < 0: - via_angle += 360 - target_angle = degrees(atan2(y2 - y0, x2 - x0)) - if target_angle < 0: - target_angle += 360 - # t- - # \ \ - # \ v - # \| - # s - # via_angle is always lower than target_angle, if direction is left. - # If they are same, it means they are on a same line of convex hull. - if target_angle > via_angle: - return Direction.left - elif target_angle == via_angle: - return Direction.straight - else: - return Direction.right - stack: deque[tuple[int, int]] = deque() stack.append(sorted_points[0]) stack.append(sorted_points[1]) From 3e1cb70abf9997af3a4903f77cb3506a301de893 Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Fri, 4 Nov 2022 00:03:37 +0400 Subject: [PATCH 535/726] add algorithm to check binary search tree (#7947) * add algorithm to check binary search tree * add tests * add leetcode link * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix typehints * typehints fixes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update data_structures/binary_tree/is_bst.py Co-authored-by: Caeden Perelli-Harris * Update data_structures/binary_tree/is_bst.py Co-authored-by: Caeden Perelli-Harris * Update data_structures/binary_tree/is_bst.py Co-authored-by: Caeden Perelli-Harris * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix flake8 * fix typehint * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add TreeNode resolving * Update data_structures/binary_tree/is_bst.py Co-authored-by: Caeden Perelli-Harris * Update data_structures/binary_tree/is_bst.py Co-authored-by: Caeden Perelli-Harris * Update data_structures/binary_tree/is_bst.py Co-authored-by: Caeden Perelli-Harris * Update data_structures/binary_tree/is_bst.py Co-authored-by: Christian Clauss * change func name * Update data_structures/binary_tree/is_bst.py Co-authored-by: Christian Clauss * review notes fixes. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix flake8 * fix flake 8 * fix doctest * Update data_structures/binary_tree/is_bst.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Caeden Perelli-Harris Co-authored-by: Christian Clauss --- data_structures/binary_tree/is_bst.py | 131 ++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 data_structures/binary_tree/is_bst.py diff --git a/data_structures/binary_tree/is_bst.py b/data_structures/binary_tree/is_bst.py new file mode 100644 index 000000000..0b2ef8c9f --- /dev/null +++ b/data_structures/binary_tree/is_bst.py @@ -0,0 +1,131 @@ +""" +Author : Alexander Pantyukhin +Date : November 2, 2022 + +Task: +Given the root of a binary tree, determine if it is a valid binary search +tree (BST). + +A valid binary search tree is defined as follows: + +- The left subtree of a node contains only nodes with keys less than the node's key. +- The right subtree of a node contains only nodes with keys greater than the node's key. +- Both the left and right subtrees must also be binary search trees. + +Implementation notes: +Depth-first search approach. + +leetcode: https://leetcode.com/problems/validate-binary-search-tree/ + +Let n is the number of nodes in tree +Runtime: O(n) +Space: O(1) +""" + +from __future__ import annotations + +from dataclasses import dataclass + + +@dataclass +class TreeNode: + data: float + left: TreeNode | None = None + right: TreeNode | None = None + + +def is_binary_search_tree(root: TreeNode | None) -> bool: + """ + >>> is_binary_search_tree(TreeNode(data=2, + ... left=TreeNode(data=1), + ... right=TreeNode(data=3)) + ... ) + True + + >>> is_binary_search_tree(TreeNode(data=0, + ... left=TreeNode(data=-11), + ... right=TreeNode(data=3)) + ... ) + True + + >>> is_binary_search_tree(TreeNode(data=5, + ... left=TreeNode(data=1), + ... right=TreeNode(data=4, left=TreeNode(data=3))) + ... ) + False + + >>> is_binary_search_tree(TreeNode(data='a', + ... left=TreeNode(data=1), + ... right=TreeNode(data=4, left=TreeNode(data=3))) + ... ) + Traceback (most recent call last): + ... + ValueError: Each node should be type of TreeNode and data should be float. + + >>> is_binary_search_tree(TreeNode(data=2, + ... left=TreeNode([]), + ... right=TreeNode(data=4, left=TreeNode(data=3))) + ... ) + Traceback (most recent call last): + ... + ValueError: Each node should be type of TreeNode and data should be float. + """ + + # Validation + def is_valid_tree(node: TreeNode | None) -> bool: + """ + >>> is_valid_tree(None) + True + >>> is_valid_tree('abc') + False + >>> is_valid_tree(TreeNode(data='not a float')) + False + >>> is_valid_tree(TreeNode(data=1, left=TreeNode('123'))) + False + """ + if node is None: + return True + + if not isinstance(node, TreeNode): + return False + + try: + float(node.data) + except (TypeError, ValueError): + return False + + return is_valid_tree(node.left) and is_valid_tree(node.right) + + if not is_valid_tree(root): + raise ValueError( + "Each node should be type of TreeNode and data should be float." + ) + + def is_binary_search_tree_recursive_check( + node: TreeNode | None, left_bound: float, right_bound: float + ) -> bool: + """ + >>> is_binary_search_tree_recursive_check(None) + True + >>> is_binary_search_tree_recursive_check(TreeNode(data=1), 10, 20) + False + """ + + if node is None: + return True + + return ( + left_bound < node.data < right_bound + and is_binary_search_tree_recursive_check(node.left, left_bound, node.data) + and is_binary_search_tree_recursive_check( + node.right, node.data, right_bound + ) + ) + + return is_binary_search_tree_recursive_check(root, -float("inf"), float("inf")) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 7f1a5521f4b73d15df409a81f3da48427f9c6cdc Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Fri, 4 Nov 2022 11:30:32 +0400 Subject: [PATCH 536/726] add prefix sum (#7959) * add prefix sum * updating DIRECTORY.md * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- DIRECTORY.md | 2 + data_structures/arrays/prefix_sum.py | 78 ++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 data_structures/arrays/prefix_sum.py diff --git a/DIRECTORY.md b/DIRECTORY.md index a2112bcfb..76c7f9dea 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -162,6 +162,7 @@ ## Data Structures * Arrays * [Permutations](data_structures/arrays/permutations.py) + * [Prefix Sum](data_structures/arrays/prefix_sum.py) * Binary Tree * [Avl Tree](data_structures/binary_tree/avl_tree.py) * [Basic Binary Tree](data_structures/binary_tree/basic_binary_tree.py) @@ -174,6 +175,7 @@ * [Diff Views Of Binary Tree](data_structures/binary_tree/diff_views_of_binary_tree.py) * [Fenwick Tree](data_structures/binary_tree/fenwick_tree.py) * [Inorder Tree Traversal 2022](data_structures/binary_tree/inorder_tree_traversal_2022.py) + * [Is Bst](data_structures/binary_tree/is_bst.py) * [Lazy Segment Tree](data_structures/binary_tree/lazy_segment_tree.py) * [Lowest Common Ancestor](data_structures/binary_tree/lowest_common_ancestor.py) * [Maximum Fenwick Tree](data_structures/binary_tree/maximum_fenwick_tree.py) diff --git a/data_structures/arrays/prefix_sum.py b/data_structures/arrays/prefix_sum.py new file mode 100644 index 000000000..2243a5308 --- /dev/null +++ b/data_structures/arrays/prefix_sum.py @@ -0,0 +1,78 @@ +""" +Author : Alexander Pantyukhin +Date : November 3, 2022 + +Implement the class of prefix sum with useful functions based on it. + +""" + + +class PrefixSum: + def __init__(self, array: list[int]) -> None: + len_array = len(array) + self.prefix_sum = [0] * len_array + + if len_array > 0: + self.prefix_sum[0] = array[0] + + for i in range(1, len_array): + self.prefix_sum[i] = self.prefix_sum[i - 1] + array[i] + + def get_sum(self, start: int, end: int) -> int: + """ + The function returns the sum of array from the start to the end indexes. + Runtime : O(1) + Space: O(1) + + >>> PrefixSum([1,2,3]).get_sum(0, 2) + 6 + >>> PrefixSum([1,2,3]).get_sum(1, 2) + 5 + >>> PrefixSum([1,2,3]).get_sum(2, 2) + 3 + >>> PrefixSum([1,2,3]).get_sum(2, 3) + Traceback (most recent call last): + ... + IndexError: list index out of range + """ + if start == 0: + return self.prefix_sum[end] + + return self.prefix_sum[end] - self.prefix_sum[start - 1] + + def contains_sum(self, target_sum: int) -> bool: + """ + The function returns True if array contains the target_sum, + False otherwise. + + Runtime : O(n) + Space: O(n) + + >>> PrefixSum([1,2,3]).contains_sum(6) + True + >>> PrefixSum([1,2,3]).contains_sum(5) + True + >>> PrefixSum([1,2,3]).contains_sum(3) + True + >>> PrefixSum([1,2,3]).contains_sum(4) + False + >>> PrefixSum([1,2,3]).contains_sum(7) + False + >>> PrefixSum([1,-2,3]).contains_sum(2) + True + """ + + sums = {0} + for sum_item in self.prefix_sum: + if sum_item - target_sum in sums: + return True + + sums.add(sum_item) + + return False + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 51708530b6a46a5e53d12e750521a11c6bf5c986 Mon Sep 17 00:00:00 2001 From: Sanders Lin Date: Sun, 6 Nov 2022 17:35:40 +0800 Subject: [PATCH 537/726] Update 3n_plus_1.py (#7966) * Update 3n_plus_1.py 1. Minor issue with ValueError message: Given integer should be positive, not greater than 1, as 1 is allowed. 2. += calls underlying list extend method which might be slower. Calling apend seems more appropriate. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/3n_plus_1.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/maths/3n_plus_1.py b/maths/3n_plus_1.py index e455a158e..59fdec48e 100644 --- a/maths/3n_plus_1.py +++ b/maths/3n_plus_1.py @@ -11,15 +11,15 @@ def n31(a: int) -> tuple[list[int], int]: if not isinstance(a, int): raise TypeError(f"Must be int, not {type(a).__name__}") if a < 1: - raise ValueError(f"Given integer must be greater than 1, not {a}") + raise ValueError(f"Given integer must be positive, not {a}") path = [a] while a != 1: if a % 2 == 0: - a = a // 2 + a //= 2 else: a = 3 * a + 1 - path += [a] + path.append(a) return path, len(path) From daa1c7529ac6491338adb81622d5041a4ba1f446 Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Sun, 6 Nov 2022 14:54:44 +0000 Subject: [PATCH 538/726] Raise error not string (#7945) * ci: Add `B023` to `.flake8` ignores * refactor: Return `bool`/raise Exception * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * revert: Remove previous branch commit * Update data_structures/binary_tree/segment_tree_other.py Co-authored-by: Christian Clauss * feat: Apply `__repr__` changes * chore: Fix failing tests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update data_structures/binary_tree/segment_tree_other.py Co-authored-by: Christian Clauss * test: Fix doctests * random.choice(population_score[:N_SELECTED])[0] * Update basic_string.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- boolean_algebra/quine_mc_cluskey.py | 11 +- ciphers/shuffled_shift_cipher.py | 2 +- computer_vision/harris_corner.py | 3 +- .../binary_tree/segment_tree_other.py | 121 +++++++++--------- data_structures/binary_tree/wavelet_tree.py | 6 +- .../linked_list/doubly_linked_list.py | 2 +- data_structures/queue/double_ended_queue.py | 2 +- graphs/breadth_first_search_shortest_path.py | 8 +- graphs/page_rank.py | 2 +- linear_algebra/src/polynom_for_points.py | 14 +- maths/monte_carlo_dice.py | 3 - matrix/cramers_rule_2x2.py | 16 ++- other/password.py | 38 +++--- strings/dna.py | 15 ++- 14 files changed, 123 insertions(+), 120 deletions(-) diff --git a/boolean_algebra/quine_mc_cluskey.py b/boolean_algebra/quine_mc_cluskey.py index 5bd7117bb..6788dfb28 100644 --- a/boolean_algebra/quine_mc_cluskey.py +++ b/boolean_algebra/quine_mc_cluskey.py @@ -1,15 +1,16 @@ from __future__ import annotations from collections.abc import Sequence +from typing import Literal -def compare_string(string1: str, string2: str) -> str: +def compare_string(string1: str, string2: str) -> str | Literal[False]: """ >>> compare_string('0010','0110') '0_10' >>> compare_string('0110','1101') - 'X' + False """ list1 = list(string1) list2 = list(string2) @@ -19,7 +20,7 @@ def compare_string(string1: str, string2: str) -> str: count += 1 list1[i] = "_" if count > 1: - return "X" + return False else: return "".join(list1) @@ -36,10 +37,10 @@ def check(binary: list[str]) -> list[str]: for i in range(len(binary)): for j in range(i + 1, len(binary)): k = compare_string(binary[i], binary[j]) - if k != "X": + if k is False: check1[i] = "*" check1[j] = "*" - temp.append(k) + temp.append("X") for i in range(len(binary)): if check1[i] == "$": pi.append(binary[i]) diff --git a/ciphers/shuffled_shift_cipher.py b/ciphers/shuffled_shift_cipher.py index 714acd4b1..08b2cab97 100644 --- a/ciphers/shuffled_shift_cipher.py +++ b/ciphers/shuffled_shift_cipher.py @@ -42,7 +42,7 @@ class ShuffledShiftCipher: """ :return: passcode of the cipher object """ - return "Passcode is: " + "".join(self.__passcode) + return "".join(self.__passcode) def __neg_pos(self, iterlist: list[int]) -> list[int]: """ diff --git a/computer_vision/harris_corner.py b/computer_vision/harris_corner.py index 7850085f8..c8905bb6a 100644 --- a/computer_vision/harris_corner.py +++ b/computer_vision/harris_corner.py @@ -22,8 +22,7 @@ class HarrisCorner: raise ValueError("invalid k value") def __str__(self) -> str: - - return f"Harris Corner detection with k : {self.k}" + return str(self.k) def detect(self, img_path: str) -> tuple[cv2.Mat, list[list[int]]]: diff --git a/data_structures/binary_tree/segment_tree_other.py b/data_structures/binary_tree/segment_tree_other.py index 90afd7ca8..cc77c4951 100644 --- a/data_structures/binary_tree/segment_tree_other.py +++ b/data_structures/binary_tree/segment_tree_other.py @@ -16,40 +16,36 @@ class SegmentTreeNode: self.left = left self.right = right - def __str__(self): - return f"val: {self.val}, start: {self.start}, end: {self.end}" + def __repr__(self): + return f"SegmentTreeNode(start={self.start}, end={self.end}, val={self.val})" class SegmentTree: """ >>> import operator >>> num_arr = SegmentTree([2, 1, 5, 3, 4], operator.add) - >>> for node in num_arr.traverse(): - ... print(node) - ... - val: 15, start: 0, end: 4 - val: 8, start: 0, end: 2 - val: 7, start: 3, end: 4 - val: 3, start: 0, end: 1 - val: 5, start: 2, end: 2 - val: 3, start: 3, end: 3 - val: 4, start: 4, end: 4 - val: 2, start: 0, end: 0 - val: 1, start: 1, end: 1 + >>> tuple(num_arr.traverse()) # doctest: +NORMALIZE_WHITESPACE + (SegmentTreeNode(start=0, end=4, val=15), + SegmentTreeNode(start=0, end=2, val=8), + SegmentTreeNode(start=3, end=4, val=7), + SegmentTreeNode(start=0, end=1, val=3), + SegmentTreeNode(start=2, end=2, val=5), + SegmentTreeNode(start=3, end=3, val=3), + SegmentTreeNode(start=4, end=4, val=4), + SegmentTreeNode(start=0, end=0, val=2), + SegmentTreeNode(start=1, end=1, val=1)) >>> >>> num_arr.update(1, 5) - >>> for node in num_arr.traverse(): - ... print(node) - ... - val: 19, start: 0, end: 4 - val: 12, start: 0, end: 2 - val: 7, start: 3, end: 4 - val: 7, start: 0, end: 1 - val: 5, start: 2, end: 2 - val: 3, start: 3, end: 3 - val: 4, start: 4, end: 4 - val: 2, start: 0, end: 0 - val: 5, start: 1, end: 1 + >>> tuple(num_arr.traverse()) # doctest: +NORMALIZE_WHITESPACE + (SegmentTreeNode(start=0, end=4, val=19), + SegmentTreeNode(start=0, end=2, val=12), + SegmentTreeNode(start=3, end=4, val=7), + SegmentTreeNode(start=0, end=1, val=7), + SegmentTreeNode(start=2, end=2, val=5), + SegmentTreeNode(start=3, end=3, val=3), + SegmentTreeNode(start=4, end=4, val=4), + SegmentTreeNode(start=0, end=0, val=2), + SegmentTreeNode(start=1, end=1, val=5)) >>> >>> num_arr.query_range(3, 4) 7 @@ -62,29 +58,29 @@ class SegmentTree: >>> for node in max_arr.traverse(): ... print(node) ... - val: 5, start: 0, end: 4 - val: 5, start: 0, end: 2 - val: 4, start: 3, end: 4 - val: 2, start: 0, end: 1 - val: 5, start: 2, end: 2 - val: 3, start: 3, end: 3 - val: 4, start: 4, end: 4 - val: 2, start: 0, end: 0 - val: 1, start: 1, end: 1 + SegmentTreeNode(start=0, end=4, val=5) + SegmentTreeNode(start=0, end=2, val=5) + SegmentTreeNode(start=3, end=4, val=4) + SegmentTreeNode(start=0, end=1, val=2) + SegmentTreeNode(start=2, end=2, val=5) + SegmentTreeNode(start=3, end=3, val=3) + SegmentTreeNode(start=4, end=4, val=4) + SegmentTreeNode(start=0, end=0, val=2) + SegmentTreeNode(start=1, end=1, val=1) >>> >>> max_arr.update(1, 5) >>> for node in max_arr.traverse(): ... print(node) ... - val: 5, start: 0, end: 4 - val: 5, start: 0, end: 2 - val: 4, start: 3, end: 4 - val: 5, start: 0, end: 1 - val: 5, start: 2, end: 2 - val: 3, start: 3, end: 3 - val: 4, start: 4, end: 4 - val: 2, start: 0, end: 0 - val: 5, start: 1, end: 1 + SegmentTreeNode(start=0, end=4, val=5) + SegmentTreeNode(start=0, end=2, val=5) + SegmentTreeNode(start=3, end=4, val=4) + SegmentTreeNode(start=0, end=1, val=5) + SegmentTreeNode(start=2, end=2, val=5) + SegmentTreeNode(start=3, end=3, val=3) + SegmentTreeNode(start=4, end=4, val=4) + SegmentTreeNode(start=0, end=0, val=2) + SegmentTreeNode(start=1, end=1, val=5) >>> >>> max_arr.query_range(3, 4) 4 @@ -97,29 +93,29 @@ class SegmentTree: >>> for node in min_arr.traverse(): ... print(node) ... - val: 1, start: 0, end: 4 - val: 1, start: 0, end: 2 - val: 3, start: 3, end: 4 - val: 1, start: 0, end: 1 - val: 5, start: 2, end: 2 - val: 3, start: 3, end: 3 - val: 4, start: 4, end: 4 - val: 2, start: 0, end: 0 - val: 1, start: 1, end: 1 + SegmentTreeNode(start=0, end=4, val=1) + SegmentTreeNode(start=0, end=2, val=1) + SegmentTreeNode(start=3, end=4, val=3) + SegmentTreeNode(start=0, end=1, val=1) + SegmentTreeNode(start=2, end=2, val=5) + SegmentTreeNode(start=3, end=3, val=3) + SegmentTreeNode(start=4, end=4, val=4) + SegmentTreeNode(start=0, end=0, val=2) + SegmentTreeNode(start=1, end=1, val=1) >>> >>> min_arr.update(1, 5) >>> for node in min_arr.traverse(): ... print(node) ... - val: 2, start: 0, end: 4 - val: 2, start: 0, end: 2 - val: 3, start: 3, end: 4 - val: 2, start: 0, end: 1 - val: 5, start: 2, end: 2 - val: 3, start: 3, end: 3 - val: 4, start: 4, end: 4 - val: 2, start: 0, end: 0 - val: 5, start: 1, end: 1 + SegmentTreeNode(start=0, end=4, val=2) + SegmentTreeNode(start=0, end=2, val=2) + SegmentTreeNode(start=3, end=4, val=3) + SegmentTreeNode(start=0, end=1, val=2) + SegmentTreeNode(start=2, end=2, val=5) + SegmentTreeNode(start=3, end=3, val=3) + SegmentTreeNode(start=4, end=4, val=4) + SegmentTreeNode(start=0, end=0, val=2) + SegmentTreeNode(start=1, end=1, val=5) >>> >>> min_arr.query_range(3, 4) 3 @@ -128,7 +124,6 @@ class SegmentTree: >>> min_arr.query_range(1, 3) 3 >>> - """ def __init__(self, collection: Sequence, function): diff --git a/data_structures/binary_tree/wavelet_tree.py b/data_structures/binary_tree/wavelet_tree.py index 8d7145189..041e140f5 100644 --- a/data_structures/binary_tree/wavelet_tree.py +++ b/data_structures/binary_tree/wavelet_tree.py @@ -24,11 +24,11 @@ class Node: """ >>> node = Node(length=27) >>> repr(node) - 'min_value: -1, max_value: -1' + 'Node(min_value=-1 max_value=-1)' >>> repr(node) == str(node) True """ - return f"min_value: {self.minn}, max_value: {self.maxx}" + return f"Node(min_value={self.minn} max_value={self.maxx})" def build_tree(arr: list[int]) -> Node | None: @@ -37,7 +37,7 @@ def build_tree(arr: list[int]) -> Node | None: of the constructed tree >>> build_tree(test_array) - min_value: 0, max_value: 9 + Node(min_value=0 max_value=9) """ root = Node(len(arr)) root.minn, root.maxx = min(arr), max(arr) diff --git a/data_structures/linked_list/doubly_linked_list.py b/data_structures/linked_list/doubly_linked_list.py index 90b6b6eb2..6c81493ff 100644 --- a/data_structures/linked_list/doubly_linked_list.py +++ b/data_structures/linked_list/doubly_linked_list.py @@ -159,7 +159,7 @@ class DoublyLinkedList: if current.next: current = current.next else: # We have reached the end an no value matches - return "No data matching given value" + raise ValueError("No data matching given value") if current == self.head: self.delete_head() diff --git a/data_structures/queue/double_ended_queue.py b/data_structures/queue/double_ended_queue.py index 11942db83..637b7f62f 100644 --- a/data_structures/queue/double_ended_queue.py +++ b/data_structures/queue/double_ended_queue.py @@ -425,7 +425,7 @@ class Deque: values_list.append(aux.val) aux = aux.next_node - return "[" + ", ".join(repr(val) for val in values_list) + "]" + return f"[{', '.join(repr(val) for val in values_list)}]" if __name__ == "__main__": diff --git a/graphs/breadth_first_search_shortest_path.py b/graphs/breadth_first_search_shortest_path.py index 697a8c634..cb21076f9 100644 --- a/graphs/breadth_first_search_shortest_path.py +++ b/graphs/breadth_first_search_shortest_path.py @@ -58,7 +58,9 @@ class Graph: Case 1 - No path is found. >>> g.shortest_path("Foo") - 'No path from vertex:G to vertex:Foo' + Traceback (most recent call last): + ... + ValueError: No path from vertex: G to vertex: Foo Case 2 - The path is found. >>> g.shortest_path("D") @@ -71,7 +73,9 @@ class Graph: target_vertex_parent = self.parent.get(target_vertex) if target_vertex_parent is None: - return f"No path from vertex:{self.source_vertex} to vertex:{target_vertex}" + raise ValueError( + f"No path from vertex: {self.source_vertex} to vertex: {target_vertex}" + ) return self.shortest_path(target_vertex_parent) + f"->{target_vertex}" diff --git a/graphs/page_rank.py b/graphs/page_rank.py index e1af35b34..b9e4c4a72 100644 --- a/graphs/page_rank.py +++ b/graphs/page_rank.py @@ -27,7 +27,7 @@ class Node: self.outbound.append(node) def __repr__(self): - return f"Node {self.name}: Inbound: {self.inbound} ; Outbound: {self.outbound}" + return f"" def page_rank(nodes, limit=3, d=0.85): diff --git a/linear_algebra/src/polynom_for_points.py b/linear_algebra/src/polynom_for_points.py index 1d702deb1..f5e3db0cb 100644 --- a/linear_algebra/src/polynom_for_points.py +++ b/linear_algebra/src/polynom_for_points.py @@ -4,9 +4,13 @@ def points_to_polynomial(coordinates: list[list[int]]) -> str: number of points you want to use >>> print(points_to_polynomial([])) - The program cannot work out a fitting polynomial. + Traceback (most recent call last): + ... + ValueError: The program cannot work out a fitting polynomial. >>> print(points_to_polynomial([[]])) - The program cannot work out a fitting polynomial. + Traceback (most recent call last): + ... + ValueError: The program cannot work out a fitting polynomial. >>> print(points_to_polynomial([[1, 0], [2, 0], [3, 0]])) f(x)=x^2*0.0+x^1*-0.0+x^0*0.0 >>> print(points_to_polynomial([[1, 1], [2, 1], [3, 1]])) @@ -25,17 +29,17 @@ def points_to_polynomial(coordinates: list[list[int]]) -> str: f(x)=x^2*5.0+x^1*-18.0+x^0*18.0 """ if len(coordinates) == 0 or not all(len(pair) == 2 for pair in coordinates): - return "The program cannot work out a fitting polynomial." + raise ValueError("The program cannot work out a fitting polynomial.") if len({tuple(pair) for pair in coordinates}) != len(coordinates): - return "The program cannot work out a fitting polynomial." + raise ValueError("The program cannot work out a fitting polynomial.") set_x = {x for x, _ in coordinates} if len(set_x) == 1: return f"x={coordinates[0][0]}" if len(set_x) != len(coordinates): - return "The program cannot work out a fitting polynomial." + raise ValueError("The program cannot work out a fitting polynomial.") x = len(coordinates) diff --git a/maths/monte_carlo_dice.py b/maths/monte_carlo_dice.py index c4150b88f..362f70b49 100644 --- a/maths/monte_carlo_dice.py +++ b/maths/monte_carlo_dice.py @@ -13,9 +13,6 @@ class Dice: def roll(self): return random.choice(self.sides) - def _str_(self): - return "Fair Dice" - def throw_dice(num_throws: int, num_dice: int = 2) -> list[float]: """ diff --git a/matrix/cramers_rule_2x2.py b/matrix/cramers_rule_2x2.py index a635d66fb..4f52dbe64 100644 --- a/matrix/cramers_rule_2x2.py +++ b/matrix/cramers_rule_2x2.py @@ -2,7 +2,7 @@ # https://en.wikipedia.org/wiki/Cramer%27s_rule -def cramers_rule_2x2(equation1: list[int], equation2: list[int]) -> str: +def cramers_rule_2x2(equation1: list[int], equation2: list[int]) -> tuple[float, float]: """ Solves the system of linear equation in 2 variables. :param: equation1: list of 3 numbers @@ -14,13 +14,13 @@ def cramers_rule_2x2(equation1: list[int], equation2: list[int]) -> str: determinant_y = [[a1, d1], [a2, d2]] >>> cramers_rule_2x2([2, 3, 0], [5, 1, 0]) - 'Trivial solution. (Consistent system) x = 0 and y = 0' + (0.0, 0.0) >>> cramers_rule_2x2([0, 4, 50], [2, 0, 26]) - 'Non-Trivial Solution (Consistent system) x = 13.0, y = 12.5' + (13.0, 12.5) >>> cramers_rule_2x2([11, 2, 30], [1, 0, 4]) - 'Non-Trivial Solution (Consistent system) x = 4.0, y = -7.0' + (4.0, -7.0) >>> cramers_rule_2x2([4, 7, 1], [1, 2, 0]) - 'Non-Trivial Solution (Consistent system) x = 2.0, y = -1.0' + (2.0, -1.0) >>> cramers_rule_2x2([1, 2, 3], [2, 4, 6]) Traceback (most recent call last): @@ -75,8 +75,10 @@ def cramers_rule_2x2(equation1: list[int], equation2: list[int]) -> str: raise ValueError("No solution. (Inconsistent system)") else: if determinant_x == determinant_y == 0: - return "Trivial solution. (Consistent system) x = 0 and y = 0" + # Trivial solution (Inconsistent system) + return (0.0, 0.0) else: x = determinant_x / determinant y = determinant_y / determinant - return f"Non-Trivial Solution (Consistent system) x = {x}, y = {y}" + # Non-Trivial Solution (Consistent system) + return (x, y) diff --git a/other/password.py b/other/password.py index 8f6833073..f463c7564 100644 --- a/other/password.py +++ b/other/password.py @@ -66,26 +66,23 @@ def random_characters(chars_incl, i): # This Will Check Whether A Given Password Is Strong Or Not # It Follows The Rule that Length Of Password Should Be At Least 8 Characters # And At Least 1 Lower, 1 Upper, 1 Number And 1 Special Character -def strong_password_detector(password: str, min_length: int = 8) -> str: +def is_strong_password(password: str, min_length: int = 8) -> bool: """ - >>> strong_password_detector('Hwea7$2!') - 'This is a strong Password' - - >>> strong_password_detector('Sh0r1') - 'Your Password must be at least 8 characters long' - - >>> strong_password_detector('Hello123') - 'Password should contain UPPERCASE, lowercase, numbers, special characters' - - >>> strong_password_detector('Hello1238udfhiaf038fajdvjjf!jaiuFhkqi1') - 'This is a strong Password' - - >>> strong_password_detector('0') - 'Your Password must be at least 8 characters long' + >>> is_strong_password('Hwea7$2!') + True + >>> is_strong_password('Sh0r1') + False + >>> is_strong_password('Hello123') + False + >>> is_strong_password('Hello1238udfhiaf038fajdvjjf!jaiuFhkqi1') + True + >>> is_strong_password('0') + False """ if len(password) < min_length: - return "Your Password must be at least 8 characters long" + # Your Password must be at least 8 characters long + return False upper = any(char in ascii_uppercase for char in password) lower = any(char in ascii_lowercase for char in password) @@ -93,13 +90,12 @@ def strong_password_detector(password: str, min_length: int = 8) -> str: spec_char = any(char in punctuation for char in password) if upper and lower and num and spec_char: - return "This is a strong Password" + return True else: - return ( - "Password should contain UPPERCASE, lowercase, " - "numbers, special characters" - ) + # Passwords should contain UPPERCASE, lowerase + # numbers, and special characters + return False def main(): diff --git a/strings/dna.py b/strings/dna.py index 46e271d68..c2b96110b 100644 --- a/strings/dna.py +++ b/strings/dna.py @@ -14,13 +14,18 @@ def dna(dna: str) -> str: >>> dna("CTGA") 'GACT' >>> dna("GFGG") - 'Invalid Strand' + Traceback (most recent call last): + ... + ValueError: Invalid Strand """ - r = len(re.findall("[ATCG]", dna)) != len(dna) - val = dna.translate(dna.maketrans("ATCG", "TAGC")) - return "Invalid Strand" if r else val + if len(re.findall("[ATCG]", dna)) != len(dna): + raise ValueError("Invalid Strand") + + return dna.translate(dna.maketrans("ATCG", "TAGC")) if __name__ == "__main__": - __import__("doctest").testmod() + import doctest + + doctest.testmod() From 6aaf0a2c77b671f3e35e71dfccc569f51d8e3b00 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 8 Nov 2022 12:49:47 +0100 Subject: [PATCH 539/726] maths/number_of_digits.py: Streamline benchmarks (#7913) * maths/number_of_digits.py: Streamline benchmarks ``` num_digits(262144): 6 -- 0.2226011250168085 seconds num_digits_fast(262144): 6 -- 0.13145116699161008 seconds num_digits_faster(262144): 6 -- 0.09273383300751448 seconds num_digits(1125899906842624): 16 -- 0.6056742920191027 seconds num_digits_fast(1125899906842624): 16 -- 0.15698366600554436 seconds num_digits_faster(1125899906842624): 16 -- 0.1027024170034565 seconds num_digits(1267650600228229401496703205376): 31 -- 1.1957934170495719 seconds num_digits_fast(1267650600228229401496703205376): 31 -- 0.15552304196171463 seconds num_digits_faster(1267650600228229401496703205376): 31 -- 0.13062308297958225 seconds ``` * updating DIRECTORY.md * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update number_of_digits.py Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/number_of_digits.py | 92 +++++---------------------------------- 1 file changed, 11 insertions(+), 81 deletions(-) diff --git a/maths/number_of_digits.py b/maths/number_of_digits.py index 3c0eb7b38..86bc67f72 100644 --- a/maths/number_of_digits.py +++ b/maths/number_of_digits.py @@ -67,93 +67,23 @@ def num_digits_faster(n: int) -> int: def benchmark() -> None: """ - Benchmark code for comparing 3 functions, - with 3 different length int values. + Benchmark multiple functions, with three different length int values. """ - print("\nFor small_num = ", small_num, ":") - print( - "> num_digits()", - "\t\tans =", - num_digits(small_num), - "\ttime =", - timeit("z.num_digits(z.small_num)", setup="import __main__ as z"), - "seconds", - ) - print( - "> num_digits_fast()", - "\tans =", - num_digits_fast(small_num), - "\ttime =", - timeit("z.num_digits_fast(z.small_num)", setup="import __main__ as z"), - "seconds", - ) - print( - "> num_digits_faster()", - "\tans =", - num_digits_faster(small_num), - "\ttime =", - timeit("z.num_digits_faster(z.small_num)", setup="import __main__ as z"), - "seconds", - ) + from collections.abc import Callable - print("\nFor medium_num = ", medium_num, ":") - print( - "> num_digits()", - "\t\tans =", - num_digits(medium_num), - "\ttime =", - timeit("z.num_digits(z.medium_num)", setup="import __main__ as z"), - "seconds", - ) - print( - "> num_digits_fast()", - "\tans =", - num_digits_fast(medium_num), - "\ttime =", - timeit("z.num_digits_fast(z.medium_num)", setup="import __main__ as z"), - "seconds", - ) - print( - "> num_digits_faster()", - "\tans =", - num_digits_faster(medium_num), - "\ttime =", - timeit("z.num_digits_faster(z.medium_num)", setup="import __main__ as z"), - "seconds", - ) + def benchmark_a_function(func: Callable, value: int) -> None: + call = f"{func.__name__}({value})" + timing = timeit(f"__main__.{call}", setup="import __main__") + print(f"{call}: {func(value)} -- {timing} seconds") - print("\nFor large_num = ", large_num, ":") - print( - "> num_digits()", - "\t\tans =", - num_digits(large_num), - "\ttime =", - timeit("z.num_digits(z.large_num)", setup="import __main__ as z"), - "seconds", - ) - print( - "> num_digits_fast()", - "\tans =", - num_digits_fast(large_num), - "\ttime =", - timeit("z.num_digits_fast(z.large_num)", setup="import __main__ as z"), - "seconds", - ) - print( - "> num_digits_faster()", - "\tans =", - num_digits_faster(large_num), - "\ttime =", - timeit("z.num_digits_faster(z.large_num)", setup="import __main__ as z"), - "seconds", - ) + for value in (262144, 1125899906842624, 1267650600228229401496703205376): + for func in (num_digits, num_digits_fast, num_digits_faster): + benchmark_a_function(func, value) + print() if __name__ == "__main__": - small_num = 262144 - medium_num = 1125899906842624 - large_num = 1267650600228229401496703205376 - benchmark() import doctest doctest.testmod() + benchmark() From 8951d857fea2f30d30f64e63d906dc986c32308a Mon Sep 17 00:00:00 2001 From: Abhishek Chakraborty Date: Tue, 8 Nov 2022 09:24:21 -0800 Subject: [PATCH 540/726] BB84 QKD algorithm (#7898) * Added BB84 algorithm. * Function name lowercase + imports fix I thought uppercase was appropriate because they're initials. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update quantum/bb84.py Co-authored-by: Christian Clauss * Removed python < 3.11 restriction from qiskit * Removed python < 3.11 restriction from qiskit * scikit-learn * Update quantum/bb84.py Correct typo in `default_rng()` call Co-authored-by: Maxim Smolskiy Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss Co-authored-by: Maxim Smolskiy --- quantum/bb84.py | 133 +++++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 4 +- 2 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 quantum/bb84.py diff --git a/quantum/bb84.py b/quantum/bb84.py new file mode 100644 index 000000000..60d64371f --- /dev/null +++ b/quantum/bb84.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python3 +""" +Simulation of the Quantum Key Distribution (QKD) protocol called BB84, +created by Charles Bennett and Gilles Brassard in 1984. + +BB84 is a key-distribution protocol that ensures secure key distribution +using qubits instead of classical bits. The generated key is the result +of simulating a quantum circuit. Our algorithm to construct the circuit +is as follows: + +Alice generates two binary strings. One encodes the basis for each qubit: + + - 0 -> {0,1} basis. + - 1 -> {+,-} basis. + +The other encodes the state: + + - 0 -> |0> or |+>. + - 1 -> |1> or |->. + +Bob also generates a binary string and uses the same convention to choose +a basis for measurement. Based on the following results, we follow the +algorithm below: + +X|0> = |1> + +H|0> = |+> + +HX|0> = |-> + +1. Whenever Alice wants to encode 1 in a qubit, she applies an +X (NOT) gate to the qubit. To encode 0, no action is needed. + +2. Wherever she wants to encode it in the {+,-} basis, she applies +an H (Hadamard) gate. No action is necessary to encode a qubit in +the {0,1} basis. + +3. She then sends the qubits to Bob (symbolically represented in +this circuit using wires). + +4. Bob measures the qubits according to his binary string for +measurement. To measure a qubit in the {+,-} basis, he applies +an H gate to the corresponding qubit and then performs a measurement. + +References: +https://en.wikipedia.org/wiki/BB84 +https://qiskit.org/textbook/ch-algorithms/quantum-key-distribution.html +""" +import numpy as np +import qiskit + + +def bb84(key_len: int = 8, seed: int | None = None) -> str: + """ + Performs the BB84 protocol using a key made of `key_len` bits. + The two parties in the key distribution are called Alice and Bob. + Args: + key_len: The length of the generated key in bits. The default is 8. + + seed: Seed for the random number generator. + Mostly used for testing. Default is None. + + Returns: + key: The key generated using BB84 protocol. + + >>> bb84(16, seed=0) + '1101101100010000' + + >>> bb84(8, seed=0) + '01011011' + """ + # Set up the random number generator. + rng = np.random.default_rng(seed=seed) + + # Roughly 25% of the qubits will contribute to the key. + # So we take more than we need. + num_qubits = 6 * key_len + # Measurement basis for Alice's qubits. + alice_basis = rng.integers(2, size=num_qubits) + # The set of states Alice will prepare. + alice_state = rng.integers(2, size=num_qubits) + # Measurement basis for Bob's qubits. + bob_basis = rng.integers(2, size=num_qubits) + + # Quantum Circuit to simulate BB84 + bb84_circ = qiskit.QuantumCircuit(num_qubits, name="BB84") + + # Alice prepares her qubits according to rules above. + for index, _ in enumerate(alice_basis): + if alice_state[index] == 1: + bb84_circ.x(index) + if alice_basis[index] == 1: + bb84_circ.h(index) + bb84_circ.barrier() + + # Bob measures the received qubits according to rules above. + for index, _ in enumerate(bob_basis): + if bob_basis[index] == 1: + bb84_circ.h(index) + + bb84_circ.barrier() + bb84_circ.measure_all() + + # Simulate the quantum circuit. + sim = qiskit.Aer.get_backend("aer_simulator") + # We only need to run one shot because the key is unique. + # Multiple shots will produce the same key. + job = qiskit.execute(bb84_circ, sim, shots=1, seed_simulator=seed) + # Returns the result of measurement. + result = job.result().get_counts(bb84_circ).most_frequent() + + # Extracting the generated key from the simulation results. + # Only keep measurement results where Alice and Bob chose the same basis. + gen_key = "".join( + [ + result_bit + for alice_basis_bit, bob_basis_bit, result_bit in zip( + alice_basis, bob_basis, result + ) + if alice_basis_bit == bob_basis_bit + ] + ) + + # Get final key. Pad with 0 if too short, otherwise truncate. + key = gen_key[:key_len] if len(gen_key) >= key_len else gen_key.ljust(key_len, "0") + return key + + +if __name__ == "__main__": + print(f"The generated key is : {bb84(8, seed=0)}") + from doctest import testmod + + testmod() diff --git a/requirements.txt b/requirements.txt index 00f31b85e..a1d607df0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,11 +8,11 @@ opencv-python pandas pillow projectq -qiskit; python_version < "3.11" +qiskit requests rich scikit-fuzzy -sklearn +scikit-learn statsmodels sympy tensorflow; python_version < "3.11" From 3f9aae149dba5c9b68ff6f7fd83cadf3fd6b1d7d Mon Sep 17 00:00:00 2001 From: Akshay Dubey <38462415+itsAkshayDubey@users.noreply.github.com> Date: Wed, 9 Nov 2022 21:06:38 +0530 Subject: [PATCH 541/726] feat: Add automorphic number implementation (#7978) * feat: Add automorphic number implementation * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * refactor: Add type checking for number * refactor: Rename variable n to number * test: Add doctest * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * test: Add unit test for number=0 Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/automorphic_number.py | 58 +++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 maths/automorphic_number.py diff --git a/maths/automorphic_number.py b/maths/automorphic_number.py new file mode 100644 index 000000000..103fc7301 --- /dev/null +++ b/maths/automorphic_number.py @@ -0,0 +1,58 @@ +""" +== Automorphic Numbers == +A number n is said to be a Automorphic number if +the square of n "ends" in the same digits as n itself. + +Examples of Automorphic Numbers: 0, 1, 5, 6, 25, 76, 376, 625, 9376, 90625, ... +https://en.wikipedia.org/wiki/Automorphic_number +""" + +# Author : Akshay Dubey (https://github.com/itsAkshayDubey) +# Time Complexity : O(log10n) + + +def is_automorphic_number(number: int) -> bool: + """ + # doctest: +NORMALIZE_WHITESPACE + This functions takes an integer number as input. + returns True if the number is automorphic. + >>> is_automorphic_number(-1) + False + >>> is_automorphic_number(0) + True + >>> is_automorphic_number(5) + True + >>> is_automorphic_number(6) + True + >>> is_automorphic_number(7) + False + >>> is_automorphic_number(25) + True + >>> is_automorphic_number(259918212890625) + True + >>> is_automorphic_number(259918212890636) + False + >>> is_automorphic_number(740081787109376) + True + >>> is_automorphic_number(5.0) + Traceback (most recent call last): + ... + TypeError: Input value of [number=5.0] must be an integer + """ + if not isinstance(number, int): + raise TypeError(f"Input value of [number={number}] must be an integer") + if number < 0: + return False + number_square = number * number + while number > 0: + if number % 10 != number_square % 10: + return False + number //= 10 + number_square //= 10 + return True + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 076193eefa161a2030ca4b1ee60b285d4a50e4c6 Mon Sep 17 00:00:00 2001 From: Akshay Dubey <38462415+itsAkshayDubey@users.noreply.github.com> Date: Thu, 10 Nov 2022 08:09:47 +0530 Subject: [PATCH 542/726] feat: Add pronic number implementation (#7979) * feat: Add pronic number implementation * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/pronic_number.py | 54 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 maths/pronic_number.py diff --git a/maths/pronic_number.py b/maths/pronic_number.py new file mode 100644 index 000000000..8b554dbbd --- /dev/null +++ b/maths/pronic_number.py @@ -0,0 +1,54 @@ +""" +== Pronic Number == +A number n is said to be a Proic number if +there exists an integer m such that n = m * (m + 1) + +Examples of Proic Numbers: 0, 2, 6, 12, 20, 30, 42, 56, 72, 90, 110 ... +https://en.wikipedia.org/wiki/Pronic_number +""" + +# Author : Akshay Dubey (https://github.com/itsAkshayDubey) + + +def is_pronic(number: int) -> bool: + """ + # doctest: +NORMALIZE_WHITESPACE + This functions takes an integer number as input. + returns True if the number is pronic. + >>> is_pronic(-1) + False + >>> is_pronic(0) + True + >>> is_pronic(2) + True + >>> is_pronic(5) + False + >>> is_pronic(6) + True + >>> is_pronic(8) + False + >>> is_pronic(30) + True + >>> is_pronic(32) + False + >>> is_pronic(2147441940) + True + >>> is_pronic(9223372033963249500) + True + >>> is_pronic(6.0) + Traceback (most recent call last): + ... + TypeError: Input value of [number=6.0] must be an integer + """ + if not isinstance(number, int): + raise TypeError(f"Input value of [number={number}] must be an integer") + if number < 0 or number % 2 == 1: + return False + number_sqrt = int(number**0.5) + return number == number_sqrt * (number_sqrt + 1) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 4cddb26908bde48047e4b6e383c4b061c289a5e5 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 10 Nov 2022 03:41:28 +0100 Subject: [PATCH 543/726] atbash.py: Tighten up the benchmarks (#7977) * atbash.py: Tighten up the benchmarks * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 1 + ciphers/atbash.py | 21 ++++----------------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 76c7f9dea..5f314c317 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -995,6 +995,7 @@ * [Sol1](project_euler/problem_686/sol1.py) ## Quantum + * [Bb84](quantum/bb84.py) * [Deutsch Jozsa](quantum/deutsch_jozsa.py) * [Half Adder](quantum/half_adder.py) * [Not Gate](quantum/not_gate.py) diff --git a/ciphers/atbash.py b/ciphers/atbash.py index 5c2aea610..0a86a800c 100644 --- a/ciphers/atbash.py +++ b/ciphers/atbash.py @@ -38,26 +38,13 @@ def atbash(sequence: str) -> str: def benchmark() -> None: - """Let's benchmark them side-by-side...""" + """Let's benchmark our functions side-by-side...""" from timeit import timeit print("Running performance benchmarks...") - print( - "> atbash_slow()", - timeit( - "atbash_slow(printable)", - setup="from string import printable ; from __main__ import atbash_slow", - ), - "seconds", - ) - print( - "> atbash()", - timeit( - "atbash(printable)", - setup="from string import printable ; from __main__ import atbash", - ), - "seconds", - ) + setup = "from string import printable ; from __main__ import atbash, atbash_slow" + print(f"> atbash_slow(): {timeit('atbash_slow(printable)', setup=setup)} seconds") + print(f"> atbash(): {timeit('atbash(printable)', setup=setup)} seconds") if __name__ == "__main__": From 5c92b7390e650494f49e1f9298c1a79421673385 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 10 Nov 2022 03:42:14 +0100 Subject: [PATCH 544/726] prime_numbers.py: Tighten up the benchmarks (#7976) * prime_numbers.py: Tighten up the benchmarks * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- maths/prime_numbers.py | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/maths/prime_numbers.py b/maths/prime_numbers.py index 4e076fe31..c5297ed92 100644 --- a/maths/prime_numbers.py +++ b/maths/prime_numbers.py @@ -90,32 +90,20 @@ def fast_primes(max_n: int) -> Generator[int, None, None]: yield i +def benchmark(): + """ + Let's benchmark our functions side-by-side... + """ + from timeit import timeit + + setup = "from __main__ import slow_primes, primes, fast_primes" + print(timeit("slow_primes(1_000_000_000_000)", setup=setup, number=1_000_000)) + print(timeit("primes(1_000_000_000_000)", setup=setup, number=1_000_000)) + print(timeit("fast_primes(1_000_000_000_000)", setup=setup, number=1_000_000)) + + if __name__ == "__main__": number = int(input("Calculate primes up to:\n>> ").strip()) for ret in primes(number): print(ret) - - # Let's benchmark them side-by-side... - from timeit import timeit - - print( - timeit( - "slow_primes(1_000_000_000_000)", - setup="from __main__ import slow_primes", - number=1_000_000, - ) - ) - print( - timeit( - "primes(1_000_000_000_000)", - setup="from __main__ import primes", - number=1_000_000, - ) - ) - print( - timeit( - "fast_primes(1_000_000_000_000)", - setup="from __main__ import fast_primes", - number=1_000_000, - ) - ) + benchmark() From 7b2eca0243f5c4454875e17971cb527037d2e281 Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Thu, 10 Nov 2022 06:49:38 +0400 Subject: [PATCH 545/726] add distribute coins (#7975) * add distribute coins * updating DIRECTORY.md * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix review notes * fix typehint * fix type in TreeNode Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- DIRECTORY.md | 1 + .../binary_tree/distribute_coins.py | 135 ++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 data_structures/binary_tree/distribute_coins.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 5f314c317..74243cd06 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -173,6 +173,7 @@ * [Binary Tree Path Sum](data_structures/binary_tree/binary_tree_path_sum.py) * [Binary Tree Traversals](data_structures/binary_tree/binary_tree_traversals.py) * [Diff Views Of Binary Tree](data_structures/binary_tree/diff_views_of_binary_tree.py) + * [Distribute Coins](data_structures/binary_tree/distribute_coins.py) * [Fenwick Tree](data_structures/binary_tree/fenwick_tree.py) * [Inorder Tree Traversal 2022](data_structures/binary_tree/inorder_tree_traversal_2022.py) * [Is Bst](data_structures/binary_tree/is_bst.py) diff --git a/data_structures/binary_tree/distribute_coins.py b/data_structures/binary_tree/distribute_coins.py new file mode 100644 index 000000000..ea02afc2c --- /dev/null +++ b/data_structures/binary_tree/distribute_coins.py @@ -0,0 +1,135 @@ +""" +Author : Alexander Pantyukhin +Date : November 7, 2022 + +Task: +You are given a tree root of a binary tree with n nodes, where each node has +node.data coins. There are exactly n coins in whole tree. + +In one move, we may choose two adjacent nodes and move one coin from one node +to another. A move may be from parent to child, or from child to parent. + +Return the minimum number of moves required to make every node have exactly one coin. + +Example 1: + + 3 + / \ + 0 0 + +Result: 2 + +Example 2: + + 0 + / \ + 3 0 + +Result 3 + +leetcode: https://leetcode.com/problems/distribute-coins-in-binary-tree/ + +Implementation notes: +User depth-first search approach. + +Let n is the number of nodes in tree +Runtime: O(n) +Space: O(1) +""" + +from __future__ import annotations + +from collections import namedtuple +from dataclasses import dataclass + + +@dataclass +class TreeNode: + data: int + left: TreeNode | None = None + right: TreeNode | None = None + + +CoinsDistribResult = namedtuple("CoinsDistribResult", "moves excess") + + +def distribute_coins(root: TreeNode | None) -> int: + """ + >>> distribute_coins(TreeNode(3, TreeNode(0), TreeNode(0))) + 2 + >>> distribute_coins(TreeNode(0, TreeNode(3), TreeNode(0))) + 3 + >>> distribute_coins(TreeNode(0, TreeNode(0), TreeNode(3))) + 3 + >>> distribute_coins(None) + 0 + >>> distribute_coins(TreeNode(0, TreeNode(0), TreeNode(0))) + Traceback (most recent call last): + ... + ValueError: The nodes number should be same as the number of coins + >>> distribute_coins(TreeNode(0, TreeNode(1), TreeNode(1))) + Traceback (most recent call last): + ... + ValueError: The nodes number should be same as the number of coins + """ + + if root is None: + return 0 + + # Validation + def count_nodes(node: TreeNode | None) -> int: + """ + >>> count_nodes(None): + 0 + """ + if node is None: + return 0 + + return count_nodes(node.left) + count_nodes(node.right) + 1 + + def count_coins(node: TreeNode | None) -> int: + """ + >>> count_coins(None): + 0 + """ + if node is None: + return 0 + + return count_coins(node.left) + count_coins(node.right) + node.data + + if count_nodes(root) != count_coins(root): + raise ValueError("The nodes number should be same as the number of coins") + + # Main calculation + def get_distrib(node: TreeNode | None) -> CoinsDistribResult: + """ + >>> get_distrib(None) + namedtuple("CoinsDistribResult", "0 2") + """ + + if node is None: + return CoinsDistribResult(0, 1) + + left_distrib_moves, left_distrib_excess = get_distrib(node.left) + right_distrib_moves, right_distrib_excess = get_distrib(node.right) + + coins_to_left = 1 - left_distrib_excess + coins_to_right = 1 - right_distrib_excess + + result_moves = ( + left_distrib_moves + + right_distrib_moves + + abs(coins_to_left) + + abs(coins_to_right) + ) + result_excess = node.data - coins_to_left - coins_to_right + + return CoinsDistribResult(result_moves, result_excess) + + return get_distrib(root)[0] + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From e1be882f72f85d5f7267b46f0ffd5203a6d81e2e Mon Sep 17 00:00:00 2001 From: Akshay Dubey <38462415+itsAkshayDubey@users.noreply.github.com> Date: Thu, 10 Nov 2022 16:25:50 +0530 Subject: [PATCH 546/726] algorithm: Twin prime (#7980) * feat: Add twin prime algorithm * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix: Fix broken import statement Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/twin_prime.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 maths/twin_prime.py diff --git a/maths/twin_prime.py b/maths/twin_prime.py new file mode 100644 index 000000000..e6ac0cc78 --- /dev/null +++ b/maths/twin_prime.py @@ -0,0 +1,45 @@ +""" +== Twin Prime == +A number n+2 is said to be a Twin prime of number n if +both n and n+2 are prime. + +Examples of Twin pairs: (3, 5), (5, 7), (11, 13), (17, 19), (29, 31), (41, 43), ... +https://en.wikipedia.org/wiki/Twin_prime +""" + +# Author : Akshay Dubey (https://github.com/itsAkshayDubey) +from maths.prime_check import is_prime + + +def twin_prime(number: int) -> int: + """ + # doctest: +NORMALIZE_WHITESPACE + This functions takes an integer number as input. + returns n+2 if n and n+2 are prime numbers and -1 otherwise. + >>> twin_prime(3) + 5 + >>> twin_prime(4) + -1 + >>> twin_prime(5) + 7 + >>> twin_prime(17) + 19 + >>> twin_prime(0) + -1 + >>> twin_prime(6.0) + Traceback (most recent call last): + ... + TypeError: Input value of [number=6.0] must be an integer + """ + if not isinstance(number, int): + raise TypeError(f"Input value of [number={number}] must be an integer") + if is_prime(number) and is_prime(number + 2): + return number + 2 + else: + return -1 + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 316e71b03448b6adb8a32d96cb4d6488ee7b7787 Mon Sep 17 00:00:00 2001 From: Gayathri Krishnan Date: Tue, 15 Nov 2022 19:07:59 +0530 Subject: [PATCH 547/726] Additional intro blockchain doc (#7974) * A deeper introduction to blockchain technology * Update README.md Rectified errors as image was not visible * Delete img1.jpg Deleting the image as it is not getting accepted in PR merge * Delete img2.jpg Deleting the image as it is not getting accepted in PR merge * Update README.md Removed all image s in the document * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update README.md Commited the suggested changes and submitting for review. * Update README.md Changed a sentence that needed grammatical correction. * Update README.md Added the changes suggested by review panel Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- blockchain/README.md | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/blockchain/README.md b/blockchain/README.md index 5ae7f95ec..b5fab7b36 100644 --- a/blockchain/README.md +++ b/blockchain/README.md @@ -1,7 +1,44 @@ # Blockchain -A Blockchain is a type of distributed ledger technology (DLT) that consists of growing list of records, called blocks, that are securely linked together using cryptography. +A Blockchain is a type of **distributed ledger** technology (DLT) that consists of growing list of records, called **blocks**, that are securely linked together using **cryptography**. +Let's breakdown the terminologies in the above definition. We find below terminologies, + +- Digital Ledger Technology (DLT) +- Blocks +- Cryptography + +## Digital Ledger Technology + + It is otherwise called as distributed ledger technology. It is simply the opposite of centralized database. Firstly, what is a **ledger**? A ledger is a book or collection of accounts that records account transactions. + + *Why is Blockchain addressed as digital ledger if it can record more than account transactions? What other transaction details and information can it hold?* + +Digital Ledger Technology is just a ledger which is shared among multiple nodes. This way there exist no need for central authority to hold the info. Okay, how is it differentiated from central database and what are their benefits? + +There is an organization which has 4 branches whose data are stored in a centralized database. So even if one branch needs any data from ledger they need an approval from database in charge. And if one hacks the central database he gets to tamper and control all the data. + +Now lets assume every branch has a copy of the ledger and then once anything is added to the ledger by anyone branch it is gonna automatically reflect in all other ledgers available in other branch. This is done using Peer-to-peer network. + +So this means even if information is tampered in one branch we can find out. If one branch is hacked we can be alerted ,so we can safeguard other branches. Now, assume these branches as computers or nodes and the ledger is a transaction record or digital receipt. If one ledger is hacked in a node we can detect since there will be a mismatch in comparison with other node information. So this is the concept of Digital Ledger Technology. + +*Is it required for all nodes to have access to all information in other nodes? Wouldn't this require enormous storage space in each node?* + +## Blocks + +In short a block is nothing but collections of records with a labelled header. These are connected cryptographically. Once a new block is added to a chain, the previous block is connected, more precisely said as locked and hence, will remain unaltered. We can understand this concept once we get a clear understanding of working mechanism of blockchain. + +## Cryptography + +It is the practice and study of secure communication techniques in the midst of adversarial behavior. More broadly, cryptography is the creation and analysis of protocols that prevent third parties or the general public from accessing private messages. + +*Which cryptography technology is most widely used in blockchain and why?* + +So, in general, blockchain technology is a distributed record holder which records the information about ownership of an asset. To define precisely, +> Blockchain is a distributed, immutable ledger that makes it easier to record transactions and track assets in a corporate network. +An asset could be tangible (such as a house, car, cash, or land) or intangible (such as a business) (intellectual property, patents, copyrights, branding). A blockchain network can track and sell almost anything of value, lowering risk and costs for everyone involved. + +So this is all about introduction to blockchain technology. To learn more about the topic refer below links.... * * * From 3bf86b91e7d438eb2b9ecbab68060c007d270332 Mon Sep 17 00:00:00 2001 From: Dhruv Manilawala Date: Tue, 15 Nov 2022 19:25:14 +0530 Subject: [PATCH 548/726] fix: no implicit optional (#7984) --- data_structures/binary_tree/fenwick_tree.py | 2 +- fractals/julia_sets.py | 2 +- linear_algebra/src/schur_complement.py | 2 +- machine_learning/linear_discriminant_analysis.py | 2 +- project_euler/problem_074/sol1.py | 2 +- sorts/strand_sort.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/data_structures/binary_tree/fenwick_tree.py b/data_structures/binary_tree/fenwick_tree.py index babd75ac4..88b0873a1 100644 --- a/data_structures/binary_tree/fenwick_tree.py +++ b/data_structures/binary_tree/fenwick_tree.py @@ -8,7 +8,7 @@ class FenwickTree: More info: https://en.wikipedia.org/wiki/Fenwick_tree """ - def __init__(self, arr: list[int] = None, size: int = None) -> None: + def __init__(self, arr: list[int] | None = None, size: int | None = None) -> None: """ Constructor for the Fenwick tree diff --git a/fractals/julia_sets.py b/fractals/julia_sets.py index 35fdc45d0..77d1d7c04 100644 --- a/fractals/julia_sets.py +++ b/fractals/julia_sets.py @@ -89,7 +89,7 @@ def iterate_function( function_params: Any, nb_iterations: int, z_0: numpy.ndarray, - infinity: float = None, + infinity: float | None = None, ) -> numpy.ndarray: """ Iterate the function "eval_function" exactly nb_iterations times. diff --git a/linear_algebra/src/schur_complement.py b/linear_algebra/src/schur_complement.py index f3cb736d9..3a5f4443a 100644 --- a/linear_algebra/src/schur_complement.py +++ b/linear_algebra/src/schur_complement.py @@ -7,7 +7,7 @@ def schur_complement( mat_a: np.ndarray, mat_b: np.ndarray, mat_c: np.ndarray, - pseudo_inv: np.ndarray = None, + pseudo_inv: np.ndarray | None = None, ) -> np.ndarray: """ Schur complement of a symmetric matrix X given as a 2x2 block matrix diff --git a/machine_learning/linear_discriminant_analysis.py b/machine_learning/linear_discriminant_analysis.py index 9ef42ed19..f4fb5ba76 100644 --- a/machine_learning/linear_discriminant_analysis.py +++ b/machine_learning/linear_discriminant_analysis.py @@ -256,7 +256,7 @@ def valid_input( input_msg: str, err_msg: str, condition: Callable[[num], bool] = lambda x: True, - default: str = None, + default: str | None = None, ) -> num: """ Ask for user value and validate that it fulfill a condition. diff --git a/project_euler/problem_074/sol1.py b/project_euler/problem_074/sol1.py index a40a62903..a257d4d94 100644 --- a/project_euler/problem_074/sol1.py +++ b/project_euler/problem_074/sol1.py @@ -71,7 +71,7 @@ def sum_digit_factorials(n: int) -> int: return ret -def chain_length(n: int, previous: set = None) -> int: +def chain_length(n: int, previous: set | None = None) -> int: """ Calculate the length of the chain of non-repeating terms starting with n. Previous is a set containing the previous member of the chain. diff --git a/sorts/strand_sort.py b/sorts/strand_sort.py index a89135a06..4cadd3961 100644 --- a/sorts/strand_sort.py +++ b/sorts/strand_sort.py @@ -1,7 +1,7 @@ import operator -def strand_sort(arr: list, reverse: bool = False, solution: list = None) -> list: +def strand_sort(arr: list, reverse: bool = False, solution: list | None = None) -> list: """ Strand sort implementation source: https://en.wikipedia.org/wiki/Strand_sort From 4ce8ad9ce6e554360089e77e088df6dd8b4a69df Mon Sep 17 00:00:00 2001 From: Akshay Dubey <38462415+itsAkshayDubey@users.noreply.github.com> Date: Tue, 15 Nov 2022 22:58:49 +0530 Subject: [PATCH 549/726] algorithm: Liouville lambda function (#7986) * feat: Add liouville lambda function * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * refactor: Refactor if-else block * refactor: Refactor error handling for -ve numbers * refactor: Remove # doctest: +NORMALIZE_WHITESPACE Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/liouville_lambda.py | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 maths/liouville_lambda.py diff --git a/maths/liouville_lambda.py b/maths/liouville_lambda.py new file mode 100644 index 000000000..5993efa42 --- /dev/null +++ b/maths/liouville_lambda.py @@ -0,0 +1,45 @@ +""" +== Liouville Lambda Function == +The Liouville Lambda function, denoted by λ(n) +and λ(n) is 1 if n is the product of an even number of prime numbers, +and -1 if it is the product of an odd number of primes. + +https://en.wikipedia.org/wiki/Liouville_function +""" + +# Author : Akshay Dubey (https://github.com/itsAkshayDubey) +from maths.prime_factors import prime_factors + + +def liouville_lambda(number: int) -> int: + """ + This functions takes an integer number as input. + returns 1 if n has even number of prime factors and -1 otherwise. + >>> liouville_lambda(10) + 1 + >>> liouville_lambda(11) + -1 + >>> liouville_lambda(0) + Traceback (most recent call last): + ... + ValueError: Input must be a positive integer + >>> liouville_lambda(-1) + Traceback (most recent call last): + ... + ValueError: Input must be a positive integer + >>> liouville_lambda(11.0) + Traceback (most recent call last): + ... + TypeError: Input value of [number=11.0] must be an integer + """ + if not isinstance(number, int): + raise TypeError(f"Input value of [number={number}] must be an integer") + if number < 1: + raise ValueError("Input must be a positive integer") + return -1 if len(prime_factors(number)) % 2 else 1 + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 8bfd1c844b388cb78b03952c7da28f07f3838fd1 Mon Sep 17 00:00:00 2001 From: Dhruv Manilawala Date: Tue, 15 Nov 2022 22:59:14 +0530 Subject: [PATCH 550/726] fix: mypy 0.991 issues (#7988) * fix: mypy 0.991 issues * fix: invalid condition for base case --- conversions/decimal_to_any.py | 5 +- data_structures/linked_list/__init__.py | 2 +- matrix/matrix_class.py | 732 ++++++++++++------------ 3 files changed, 370 insertions(+), 369 deletions(-) diff --git a/conversions/decimal_to_any.py b/conversions/decimal_to_any.py index 11a2af294..c9c2e9a5f 100644 --- a/conversions/decimal_to_any.py +++ b/conversions/decimal_to_any.py @@ -76,8 +76,9 @@ def decimal_to_any(num: int, base: int) -> str: div, mod = divmod(num, base) if base >= 11 and 9 < mod < 36: actual_value = ALPHABET_VALUES[str(mod)] - mod = actual_value - new_value += str(mod) + else: + actual_value = str(mod) + new_value += actual_value div = num // base num = div if div == 0: diff --git a/data_structures/linked_list/__init__.py b/data_structures/linked_list/__init__.py index 85660a6d2..56b0e51ba 100644 --- a/data_structures/linked_list/__init__.py +++ b/data_structures/linked_list/__init__.py @@ -49,7 +49,7 @@ class LinkedList: >>> print(linked_list) 9 --> 14 --> 23 """ - if not self.is_empty: + if self.is_empty(): return "" else: iterate = self.head diff --git a/matrix/matrix_class.py b/matrix/matrix_class.py index 0c3078fe6..a73e8b92a 100644 --- a/matrix/matrix_class.py +++ b/matrix/matrix_class.py @@ -1,366 +1,366 @@ -# An OOP approach to representing and manipulating matrices - -from __future__ import annotations - - -class Matrix: - """ - Matrix object generated from a 2D array where each element is an array representing - a row. - Rows can contain type int or float. - Common operations and information available. - >>> rows = [ - ... [1, 2, 3], - ... [4, 5, 6], - ... [7, 8, 9] - ... ] - >>> matrix = Matrix(rows) - >>> print(matrix) - [[1. 2. 3.] - [4. 5. 6.] - [7. 8. 9.]] - - Matrix rows and columns are available as 2D arrays - >>> matrix.rows - [[1, 2, 3], [4, 5, 6], [7, 8, 9]] - >>> matrix.columns() - [[1, 4, 7], [2, 5, 8], [3, 6, 9]] - - Order is returned as a tuple - >>> matrix.order - (3, 3) - - Squareness and invertability are represented as bool - >>> matrix.is_square - True - >>> matrix.is_invertable() - False - - Identity, Minors, Cofactors and Adjugate are returned as Matrices. Inverse can be - a Matrix or Nonetype - >>> print(matrix.identity()) - [[1. 0. 0.] - [0. 1. 0.] - [0. 0. 1.]] - >>> print(matrix.minors()) - [[-3. -6. -3.] - [-6. -12. -6.] - [-3. -6. -3.]] - >>> print(matrix.cofactors()) - [[-3. 6. -3.] - [6. -12. 6.] - [-3. 6. -3.]] - >>> # won't be apparent due to the nature of the cofactor matrix - >>> print(matrix.adjugate()) - [[-3. 6. -3.] - [6. -12. 6.] - [-3. 6. -3.]] - >>> matrix.inverse() - Traceback (most recent call last): - ... - TypeError: Only matrices with a non-zero determinant have an inverse - - Determinant is an int, float, or Nonetype - >>> matrix.determinant() - 0 - - Negation, scalar multiplication, addition, subtraction, multiplication and - exponentiation are available and all return a Matrix - >>> print(-matrix) - [[-1. -2. -3.] - [-4. -5. -6.] - [-7. -8. -9.]] - >>> matrix2 = matrix * 3 - >>> print(matrix2) - [[3. 6. 9.] - [12. 15. 18.] - [21. 24. 27.]] - >>> print(matrix + matrix2) - [[4. 8. 12.] - [16. 20. 24.] - [28. 32. 36.]] - >>> print(matrix - matrix2) - [[-2. -4. -6.] - [-8. -10. -12.] - [-14. -16. -18.]] - >>> print(matrix ** 3) - [[468. 576. 684.] - [1062. 1305. 1548.] - [1656. 2034. 2412.]] - - Matrices can also be modified - >>> matrix.add_row([10, 11, 12]) - >>> print(matrix) - [[1. 2. 3.] - [4. 5. 6.] - [7. 8. 9.] - [10. 11. 12.]] - >>> matrix2.add_column([8, 16, 32]) - >>> print(matrix2) - [[3. 6. 9. 8.] - [12. 15. 18. 16.] - [21. 24. 27. 32.]] - >>> print(matrix * matrix2) - [[90. 108. 126. 136.] - [198. 243. 288. 304.] - [306. 378. 450. 472.] - [414. 513. 612. 640.]] - """ - - def __init__(self, rows: list[list[int]]): - error = TypeError( - "Matrices must be formed from a list of zero or more lists containing at " - "least one and the same number of values, each of which must be of type " - "int or float." - ) - if len(rows) != 0: - cols = len(rows[0]) - if cols == 0: - raise error - for row in rows: - if len(row) != cols: - raise error - for value in row: - if not isinstance(value, (int, float)): - raise error - self.rows = rows - else: - self.rows = [] - - # MATRIX INFORMATION - def columns(self) -> list[list[int]]: - return [[row[i] for row in self.rows] for i in range(len(self.rows[0]))] - - @property - def num_rows(self) -> int: - return len(self.rows) - - @property - def num_columns(self) -> int: - return len(self.rows[0]) - - @property - def order(self) -> tuple[int, int]: - return (self.num_rows, self.num_columns) - - @property - def is_square(self) -> bool: - return self.order[0] == self.order[1] - - def identity(self) -> Matrix: - values = [ - [0 if column_num != row_num else 1 for column_num in range(self.num_rows)] - for row_num in range(self.num_rows) - ] - return Matrix(values) - - def determinant(self) -> int: - if not self.is_square: - return 0 - if self.order == (0, 0): - return 1 - if self.order == (1, 1): - return int(self.rows[0][0]) - if self.order == (2, 2): - return int( - (self.rows[0][0] * self.rows[1][1]) - - (self.rows[0][1] * self.rows[1][0]) - ) - else: - return sum( - self.rows[0][column] * self.cofactors().rows[0][column] - for column in range(self.num_columns) - ) - - def is_invertable(self) -> bool: - return bool(self.determinant()) - - def get_minor(self, row: int, column: int) -> int: - values = [ - [ - self.rows[other_row][other_column] - for other_column in range(self.num_columns) - if other_column != column - ] - for other_row in range(self.num_rows) - if other_row != row - ] - return Matrix(values).determinant() - - def get_cofactor(self, row: int, column: int) -> int: - if (row + column) % 2 == 0: - return self.get_minor(row, column) - return -1 * self.get_minor(row, column) - - def minors(self) -> Matrix: - return Matrix( - [ - [self.get_minor(row, column) for column in range(self.num_columns)] - for row in range(self.num_rows) - ] - ) - - def cofactors(self) -> Matrix: - return Matrix( - [ - [ - self.minors().rows[row][column] - if (row + column) % 2 == 0 - else self.minors().rows[row][column] * -1 - for column in range(self.minors().num_columns) - ] - for row in range(self.minors().num_rows) - ] - ) - - def adjugate(self) -> Matrix: - values = [ - [self.cofactors().rows[column][row] for column in range(self.num_columns)] - for row in range(self.num_rows) - ] - return Matrix(values) - - def inverse(self) -> Matrix: - determinant = self.determinant() - if not determinant: - raise TypeError("Only matrices with a non-zero determinant have an inverse") - return self.adjugate() * (1 / determinant) - - def __repr__(self) -> str: - return str(self.rows) - - def __str__(self) -> str: - if self.num_rows == 0: - return "[]" - if self.num_rows == 1: - return "[[" + ". ".join(str(self.rows[0])) + "]]" - return ( - "[" - + "\n ".join( - [ - "[" + ". ".join([str(value) for value in row]) + ".]" - for row in self.rows - ] - ) - + "]" - ) - - # MATRIX MANIPULATION - def add_row(self, row: list[int], position: int | None = None) -> None: - type_error = TypeError("Row must be a list containing all ints and/or floats") - if not isinstance(row, list): - raise type_error - for value in row: - if not isinstance(value, (int, float)): - raise type_error - if len(row) != self.num_columns: - raise ValueError( - "Row must be equal in length to the other rows in the matrix" - ) - if position is None: - self.rows.append(row) - else: - self.rows = self.rows[0:position] + [row] + self.rows[position:] - - def add_column(self, column: list[int], position: int | None = None) -> None: - type_error = TypeError( - "Column must be a list containing all ints and/or floats" - ) - if not isinstance(column, list): - raise type_error - for value in column: - if not isinstance(value, (int, float)): - raise type_error - if len(column) != self.num_rows: - raise ValueError( - "Column must be equal in length to the other columns in the matrix" - ) - if position is None: - self.rows = [self.rows[i] + [column[i]] for i in range(self.num_rows)] - else: - self.rows = [ - self.rows[i][0:position] + [column[i]] + self.rows[i][position:] - for i in range(self.num_rows) - ] - - # MATRIX OPERATIONS - def __eq__(self, other: object) -> bool: - if not isinstance(other, Matrix): - return NotImplemented - return self.rows == other.rows - - def __ne__(self, other: object) -> bool: - return not self == other - - def __neg__(self) -> Matrix: - return self * -1 - - def __add__(self, other: Matrix) -> Matrix: - if self.order != other.order: - raise ValueError("Addition requires matrices of the same order") - return Matrix( - [ - [self.rows[i][j] + other.rows[i][j] for j in range(self.num_columns)] - for i in range(self.num_rows) - ] - ) - - def __sub__(self, other: Matrix) -> Matrix: - if self.order != other.order: - raise ValueError("Subtraction requires matrices of the same order") - return Matrix( - [ - [self.rows[i][j] - other.rows[i][j] for j in range(self.num_columns)] - for i in range(self.num_rows) - ] - ) - - def __mul__(self, other: Matrix | int | float) -> Matrix: - if isinstance(other, (int, float)): - return Matrix( - [[int(element * other) for element in row] for row in self.rows] - ) - elif isinstance(other, Matrix): - if self.num_columns != other.num_rows: - raise ValueError( - "The number of columns in the first matrix must " - "be equal to the number of rows in the second" - ) - return Matrix( - [ - [Matrix.dot_product(row, column) for column in other.columns()] - for row in self.rows - ] - ) - else: - raise TypeError( - "A Matrix can only be multiplied by an int, float, or another matrix" - ) - - def __pow__(self, other: int) -> Matrix: - if not isinstance(other, int): - raise TypeError("A Matrix can only be raised to the power of an int") - if not self.is_square: - raise ValueError("Only square matrices can be raised to a power") - if other == 0: - return self.identity() - if other < 0: - if self.is_invertable: - return self.inverse() ** (-other) - raise ValueError( - "Only invertable matrices can be raised to a negative power" - ) - result = self - for _ in range(other - 1): - result *= self - return result - - @classmethod - def dot_product(cls, row: list[int], column: list[int]) -> int: - return sum(row[i] * column[i] for i in range(len(row))) - - -if __name__ == "__main__": - import doctest - - doctest.testmod() +# An OOP approach to representing and manipulating matrices + +from __future__ import annotations + + +class Matrix: + """ + Matrix object generated from a 2D array where each element is an array representing + a row. + Rows can contain type int or float. + Common operations and information available. + >>> rows = [ + ... [1, 2, 3], + ... [4, 5, 6], + ... [7, 8, 9] + ... ] + >>> matrix = Matrix(rows) + >>> print(matrix) + [[1. 2. 3.] + [4. 5. 6.] + [7. 8. 9.]] + + Matrix rows and columns are available as 2D arrays + >>> matrix.rows + [[1, 2, 3], [4, 5, 6], [7, 8, 9]] + >>> matrix.columns() + [[1, 4, 7], [2, 5, 8], [3, 6, 9]] + + Order is returned as a tuple + >>> matrix.order + (3, 3) + + Squareness and invertability are represented as bool + >>> matrix.is_square + True + >>> matrix.is_invertable() + False + + Identity, Minors, Cofactors and Adjugate are returned as Matrices. Inverse can be + a Matrix or Nonetype + >>> print(matrix.identity()) + [[1. 0. 0.] + [0. 1. 0.] + [0. 0. 1.]] + >>> print(matrix.minors()) + [[-3. -6. -3.] + [-6. -12. -6.] + [-3. -6. -3.]] + >>> print(matrix.cofactors()) + [[-3. 6. -3.] + [6. -12. 6.] + [-3. 6. -3.]] + >>> # won't be apparent due to the nature of the cofactor matrix + >>> print(matrix.adjugate()) + [[-3. 6. -3.] + [6. -12. 6.] + [-3. 6. -3.]] + >>> matrix.inverse() + Traceback (most recent call last): + ... + TypeError: Only matrices with a non-zero determinant have an inverse + + Determinant is an int, float, or Nonetype + >>> matrix.determinant() + 0 + + Negation, scalar multiplication, addition, subtraction, multiplication and + exponentiation are available and all return a Matrix + >>> print(-matrix) + [[-1. -2. -3.] + [-4. -5. -6.] + [-7. -8. -9.]] + >>> matrix2 = matrix * 3 + >>> print(matrix2) + [[3. 6. 9.] + [12. 15. 18.] + [21. 24. 27.]] + >>> print(matrix + matrix2) + [[4. 8. 12.] + [16. 20. 24.] + [28. 32. 36.]] + >>> print(matrix - matrix2) + [[-2. -4. -6.] + [-8. -10. -12.] + [-14. -16. -18.]] + >>> print(matrix ** 3) + [[468. 576. 684.] + [1062. 1305. 1548.] + [1656. 2034. 2412.]] + + Matrices can also be modified + >>> matrix.add_row([10, 11, 12]) + >>> print(matrix) + [[1. 2. 3.] + [4. 5. 6.] + [7. 8. 9.] + [10. 11. 12.]] + >>> matrix2.add_column([8, 16, 32]) + >>> print(matrix2) + [[3. 6. 9. 8.] + [12. 15. 18. 16.] + [21. 24. 27. 32.]] + >>> print(matrix * matrix2) + [[90. 108. 126. 136.] + [198. 243. 288. 304.] + [306. 378. 450. 472.] + [414. 513. 612. 640.]] + """ + + def __init__(self, rows: list[list[int]]): + error = TypeError( + "Matrices must be formed from a list of zero or more lists containing at " + "least one and the same number of values, each of which must be of type " + "int or float." + ) + if len(rows) != 0: + cols = len(rows[0]) + if cols == 0: + raise error + for row in rows: + if len(row) != cols: + raise error + for value in row: + if not isinstance(value, (int, float)): + raise error + self.rows = rows + else: + self.rows = [] + + # MATRIX INFORMATION + def columns(self) -> list[list[int]]: + return [[row[i] for row in self.rows] for i in range(len(self.rows[0]))] + + @property + def num_rows(self) -> int: + return len(self.rows) + + @property + def num_columns(self) -> int: + return len(self.rows[0]) + + @property + def order(self) -> tuple[int, int]: + return (self.num_rows, self.num_columns) + + @property + def is_square(self) -> bool: + return self.order[0] == self.order[1] + + def identity(self) -> Matrix: + values = [ + [0 if column_num != row_num else 1 for column_num in range(self.num_rows)] + for row_num in range(self.num_rows) + ] + return Matrix(values) + + def determinant(self) -> int: + if not self.is_square: + return 0 + if self.order == (0, 0): + return 1 + if self.order == (1, 1): + return int(self.rows[0][0]) + if self.order == (2, 2): + return int( + (self.rows[0][0] * self.rows[1][1]) + - (self.rows[0][1] * self.rows[1][0]) + ) + else: + return sum( + self.rows[0][column] * self.cofactors().rows[0][column] + for column in range(self.num_columns) + ) + + def is_invertable(self) -> bool: + return bool(self.determinant()) + + def get_minor(self, row: int, column: int) -> int: + values = [ + [ + self.rows[other_row][other_column] + for other_column in range(self.num_columns) + if other_column != column + ] + for other_row in range(self.num_rows) + if other_row != row + ] + return Matrix(values).determinant() + + def get_cofactor(self, row: int, column: int) -> int: + if (row + column) % 2 == 0: + return self.get_minor(row, column) + return -1 * self.get_minor(row, column) + + def minors(self) -> Matrix: + return Matrix( + [ + [self.get_minor(row, column) for column in range(self.num_columns)] + for row in range(self.num_rows) + ] + ) + + def cofactors(self) -> Matrix: + return Matrix( + [ + [ + self.minors().rows[row][column] + if (row + column) % 2 == 0 + else self.minors().rows[row][column] * -1 + for column in range(self.minors().num_columns) + ] + for row in range(self.minors().num_rows) + ] + ) + + def adjugate(self) -> Matrix: + values = [ + [self.cofactors().rows[column][row] for column in range(self.num_columns)] + for row in range(self.num_rows) + ] + return Matrix(values) + + def inverse(self) -> Matrix: + determinant = self.determinant() + if not determinant: + raise TypeError("Only matrices with a non-zero determinant have an inverse") + return self.adjugate() * (1 / determinant) + + def __repr__(self) -> str: + return str(self.rows) + + def __str__(self) -> str: + if self.num_rows == 0: + return "[]" + if self.num_rows == 1: + return "[[" + ". ".join(str(self.rows[0])) + "]]" + return ( + "[" + + "\n ".join( + [ + "[" + ". ".join([str(value) for value in row]) + ".]" + for row in self.rows + ] + ) + + "]" + ) + + # MATRIX MANIPULATION + def add_row(self, row: list[int], position: int | None = None) -> None: + type_error = TypeError("Row must be a list containing all ints and/or floats") + if not isinstance(row, list): + raise type_error + for value in row: + if not isinstance(value, (int, float)): + raise type_error + if len(row) != self.num_columns: + raise ValueError( + "Row must be equal in length to the other rows in the matrix" + ) + if position is None: + self.rows.append(row) + else: + self.rows = self.rows[0:position] + [row] + self.rows[position:] + + def add_column(self, column: list[int], position: int | None = None) -> None: + type_error = TypeError( + "Column must be a list containing all ints and/or floats" + ) + if not isinstance(column, list): + raise type_error + for value in column: + if not isinstance(value, (int, float)): + raise type_error + if len(column) != self.num_rows: + raise ValueError( + "Column must be equal in length to the other columns in the matrix" + ) + if position is None: + self.rows = [self.rows[i] + [column[i]] for i in range(self.num_rows)] + else: + self.rows = [ + self.rows[i][0:position] + [column[i]] + self.rows[i][position:] + for i in range(self.num_rows) + ] + + # MATRIX OPERATIONS + def __eq__(self, other: object) -> bool: + if not isinstance(other, Matrix): + return NotImplemented + return self.rows == other.rows + + def __ne__(self, other: object) -> bool: + return not self == other + + def __neg__(self) -> Matrix: + return self * -1 + + def __add__(self, other: Matrix) -> Matrix: + if self.order != other.order: + raise ValueError("Addition requires matrices of the same order") + return Matrix( + [ + [self.rows[i][j] + other.rows[i][j] for j in range(self.num_columns)] + for i in range(self.num_rows) + ] + ) + + def __sub__(self, other: Matrix) -> Matrix: + if self.order != other.order: + raise ValueError("Subtraction requires matrices of the same order") + return Matrix( + [ + [self.rows[i][j] - other.rows[i][j] for j in range(self.num_columns)] + for i in range(self.num_rows) + ] + ) + + def __mul__(self, other: Matrix | int | float) -> Matrix: + if isinstance(other, (int, float)): + return Matrix( + [[int(element * other) for element in row] for row in self.rows] + ) + elif isinstance(other, Matrix): + if self.num_columns != other.num_rows: + raise ValueError( + "The number of columns in the first matrix must " + "be equal to the number of rows in the second" + ) + return Matrix( + [ + [Matrix.dot_product(row, column) for column in other.columns()] + for row in self.rows + ] + ) + else: + raise TypeError( + "A Matrix can only be multiplied by an int, float, or another matrix" + ) + + def __pow__(self, other: int) -> Matrix: + if not isinstance(other, int): + raise TypeError("A Matrix can only be raised to the power of an int") + if not self.is_square: + raise ValueError("Only square matrices can be raised to a power") + if other == 0: + return self.identity() + if other < 0: + if self.is_invertable(): + return self.inverse() ** (-other) + raise ValueError( + "Only invertable matrices can be raised to a negative power" + ) + result = self + for _ in range(other - 1): + result *= self + return result + + @classmethod + def dot_product(cls, row: list[int], column: list[int]) -> int: + return sum(row[i] * column[i] for i in range(len(row))) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 0684ccdd69c62d5dc816bdc488bc079d06b9685a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 15 Nov 2022 18:34:17 +0100 Subject: [PATCH 551/726] [pre-commit.ci] pre-commit autoupdate (#7983) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/asottile/pyupgrade: v3.2.0 → v3.2.2](https://github.com/asottile/pyupgrade/compare/v3.2.0...v3.2.2) - [github.com/pre-commit/mirrors-mypy: v0.982 → v0.990](https://github.com/pre-commit/mirrors-mypy/compare/v0.982...v0.990) * updating DIRECTORY.md * Update .pre-commit-config.yaml * Downgrade to mypy v0.991 --> v0.990 * mpyp v0.991 * Update DIRECTORY.md Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss --- .pre-commit-config.yaml | 6 +++--- DIRECTORY.md | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a0ea03b9b..324a021ee 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,11 +27,11 @@ repos: - --profile=black - repo: https://github.com/asottile/pyupgrade - rev: v3.2.0 + rev: v3.2.2 hooks: - id: pyupgrade args: - - --py310-plus + - --py311-plus - repo: https://github.com/PyCQA/flake8 rev: 5.0.4 @@ -52,7 +52,7 @@ repos: *flake8-plugins - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.982 + rev: v0.991 hooks: - id: mypy args: diff --git a/DIRECTORY.md b/DIRECTORY.md index 74243cd06..e2fffec57 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -509,6 +509,7 @@ * [Area](maths/area.py) * [Area Under Curve](maths/area_under_curve.py) * [Armstrong Numbers](maths/armstrong_numbers.py) + * [Automorphic Number](maths/automorphic_number.py) * [Average Absolute Deviation](maths/average_absolute_deviation.py) * [Average Mean](maths/average_mean.py) * [Average Median](maths/average_median.py) @@ -603,6 +604,7 @@ * [Prime Sieve Eratosthenes](maths/prime_sieve_eratosthenes.py) * [Primelib](maths/primelib.py) * [Print Multiplication Table](maths/print_multiplication_table.py) + * [Pronic Number](maths/pronic_number.py) * [Proth Number](maths/proth_number.py) * [Pythagoras](maths/pythagoras.py) * [Qr Decomposition](maths/qr_decomposition.py) @@ -638,6 +640,7 @@ * [Test Prime Check](maths/test_prime_check.py) * [Trapezoidal Rule](maths/trapezoidal_rule.py) * [Triplet Sum](maths/triplet_sum.py) + * [Twin Prime](maths/twin_prime.py) * [Two Pointer](maths/two_pointer.py) * [Two Sum](maths/two_sum.py) * [Ugly Numbers](maths/ugly_numbers.py) From b33ea81a7437eaf7d048d92a9b75330c9d9e165e Mon Sep 17 00:00:00 2001 From: Akshay Dubey <38462415+itsAkshayDubey@users.noreply.github.com> Date: Fri, 18 Nov 2022 13:48:47 +0530 Subject: [PATCH 552/726] algorithm: Add juggler sequence (#7985) * feat: Add juggler sequence * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * refactor: Remove temp variable * refactor: Change error type for negative numbers * refactor: Remove # doctest: +NORMALIZE_WHITESPACE * refactor: Remove int typecasting * test: Add unit tests for n=10 and n=25 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/juggler_sequence.py | 61 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 maths/juggler_sequence.py diff --git a/maths/juggler_sequence.py b/maths/juggler_sequence.py new file mode 100644 index 000000000..9daba8bc0 --- /dev/null +++ b/maths/juggler_sequence.py @@ -0,0 +1,61 @@ +""" +== Juggler Sequence == +Juggler sequence start with any positive integer n. The next term is +obtained as follows: + If n term is even, the next term is floor value of square root of n . + If n is odd, the next term is floor value of 3 time the square root of n. + +https://en.wikipedia.org/wiki/Juggler_sequence +""" + +# Author : Akshay Dubey (https://github.com/itsAkshayDubey) +import math + + +def juggler_sequence(number: int) -> list[int]: + """ + >>> juggler_sequence(0) + Traceback (most recent call last): + ... + ValueError: Input value of [number=0] must be a positive integer + >>> juggler_sequence(1) + [1] + >>> juggler_sequence(2) + [2, 1] + >>> juggler_sequence(3) + [3, 5, 11, 36, 6, 2, 1] + >>> juggler_sequence(5) + [5, 11, 36, 6, 2, 1] + >>> juggler_sequence(10) + [10, 3, 5, 11, 36, 6, 2, 1] + >>> juggler_sequence(25) + [25, 125, 1397, 52214, 228, 15, 58, 7, 18, 4, 2, 1] + >>> juggler_sequence(6.0) + Traceback (most recent call last): + ... + TypeError: Input value of [number=6.0] must be an integer + >>> juggler_sequence(-1) + Traceback (most recent call last): + ... + ValueError: Input value of [number=-1] must be a positive integer + """ + if not isinstance(number, int): + raise TypeError(f"Input value of [number={number}] must be an integer") + if number < 1: + raise ValueError(f"Input value of [number={number}] must be a positive integer") + sequence = [number] + while number != 1: + if number % 2 == 0: + number = math.floor(math.sqrt(number)) + else: + number = math.floor( + math.sqrt(number) * math.sqrt(number) * math.sqrt(number) + ) + sequence.append(number) + return sequence + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From f01a1af1df28ba53fc4727ea0bb703b5744100a7 Mon Sep 17 00:00:00 2001 From: Swayam <74960567+practice404@users.noreply.github.com> Date: Sun, 20 Nov 2022 16:25:58 +0530 Subject: [PATCH 553/726] Bi directional dijkstra (#7982) * Added Bi-Directional Dijkstra * Added Bi-Directional Dijkstra * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Added doctest and type hints * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Rename Bi_directional_Dijkstra.py to bi_directional_dijkstra.py * Update bi_directional_dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bi_directional_dijkstra.py * Update bi_directional_dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bi_directional_dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bi_directional_dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bi_directional_dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bi_directional_dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bi_directional_dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bi_directional_dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bi_directional_dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bi_directional_dijkstra.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- graphs/bi_directional_dijkstra.py | 130 ++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 graphs/bi_directional_dijkstra.py diff --git a/graphs/bi_directional_dijkstra.py b/graphs/bi_directional_dijkstra.py new file mode 100644 index 000000000..fc53e2f0d --- /dev/null +++ b/graphs/bi_directional_dijkstra.py @@ -0,0 +1,130 @@ +""" +Bi-directional Dijkstra's algorithm. + +A bi-directional approach is an efficient and +less time consuming optimization for Dijkstra's +searching algorithm + +Reference: shorturl.at/exHM7 +""" + +# Author: Swayam Singh (https://github.com/practice404) + + +from queue import PriorityQueue +from typing import Any + +import numpy as np + + +def bidirectional_dij( + source: str, destination: str, graph_forward: dict, graph_backward: dict +) -> int: + """ + Bi-directional Dijkstra's algorithm. + + Returns: + shortest_path_distance (int): length of the shortest path. + + Warnings: + If the destination is not reachable, function returns -1 + + >>> bidirectional_dij("E", "F", graph_fwd, graph_bwd) + 3 + """ + shortest_path_distance = -1 + + visited_forward = set() + visited_backward = set() + cst_fwd = {source: 0} + cst_bwd = {destination: 0} + parent_forward = {source: None} + parent_backward = {destination: None} + queue_forward: PriorityQueue[Any] = PriorityQueue() + queue_backward: PriorityQueue[Any] = PriorityQueue() + + shortest_distance = np.inf + + queue_forward.put((0, source)) + queue_backward.put((0, destination)) + + if source == destination: + return 0 + + while queue_forward and queue_backward: + while not queue_forward.empty(): + _, v_fwd = queue_forward.get() + + if v_fwd not in visited_forward: + break + else: + break + visited_forward.add(v_fwd) + + while not queue_backward.empty(): + _, v_bwd = queue_backward.get() + + if v_bwd not in visited_backward: + break + else: + break + visited_backward.add(v_bwd) + + # forward pass and relaxation + for nxt_fwd, d_forward in graph_forward[v_fwd]: + if nxt_fwd in visited_forward: + continue + old_cost_f = cst_fwd.get(nxt_fwd, np.inf) + new_cost_f = cst_fwd[v_fwd] + d_forward + if new_cost_f < old_cost_f: + queue_forward.put((new_cost_f, nxt_fwd)) + cst_fwd[nxt_fwd] = new_cost_f + parent_forward[nxt_fwd] = v_fwd + if nxt_fwd in visited_backward: + if cst_fwd[v_fwd] + d_forward + cst_bwd[nxt_fwd] < shortest_distance: + shortest_distance = cst_fwd[v_fwd] + d_forward + cst_bwd[nxt_fwd] + + # backward pass and relaxation + for nxt_bwd, d_backward in graph_backward[v_bwd]: + if nxt_bwd in visited_backward: + continue + old_cost_b = cst_bwd.get(nxt_bwd, np.inf) + new_cost_b = cst_bwd[v_bwd] + d_backward + if new_cost_b < old_cost_b: + queue_backward.put((new_cost_b, nxt_bwd)) + cst_bwd[nxt_bwd] = new_cost_b + parent_backward[nxt_bwd] = v_bwd + + if nxt_bwd in visited_forward: + if cst_bwd[v_bwd] + d_backward + cst_fwd[nxt_bwd] < shortest_distance: + shortest_distance = cst_bwd[v_bwd] + d_backward + cst_fwd[nxt_bwd] + + if cst_fwd[v_fwd] + cst_bwd[v_bwd] >= shortest_distance: + break + + if shortest_distance != np.inf: + shortest_path_distance = shortest_distance + return shortest_path_distance + + +graph_fwd = { + "B": [["C", 1]], + "C": [["D", 1]], + "D": [["F", 1]], + "E": [["B", 1], ["G", 2]], + "F": [], + "G": [["F", 1]], +} +graph_bwd = { + "B": [["E", 1]], + "C": [["B", 1]], + "D": [["C", 1]], + "F": [["D", 1], ["G", 1]], + "E": [[None, np.inf]], + "G": [["E", 2]], +} + +if __name__ == "__main__": + import doctest + + doctest.testmod() From a25c53e8b0cc73ff718ec406ac04cca0c2ddbb02 Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Sun, 20 Nov 2022 14:59:25 +0400 Subject: [PATCH 554/726] Fix argument validation for count_1s_brian_kernighan_method (#7994) * Fix argument validation for count_1s_brian_kernighan_method * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 1 + .../count_1s_brian_kernighan_method.py | 15 +++++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index e2fffec57..83da4b76a 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -571,6 +571,7 @@ * [Largest Subarray Sum](maths/largest_subarray_sum.py) * [Least Common Multiple](maths/least_common_multiple.py) * [Line Length](maths/line_length.py) + * [Liouville Lambda](maths/liouville_lambda.py) * [Lucas Lehmer Primality Test](maths/lucas_lehmer_primality_test.py) * [Lucas Series](maths/lucas_series.py) * [Maclaurin Series](maths/maclaurin_series.py) diff --git a/bit_manipulation/count_1s_brian_kernighan_method.py b/bit_manipulation/count_1s_brian_kernighan_method.py index e6d6d6534..2ed81b09d 100644 --- a/bit_manipulation/count_1s_brian_kernighan_method.py +++ b/bit_manipulation/count_1s_brian_kernighan_method.py @@ -17,16 +17,19 @@ def get_1s_count(number: int) -> int: >>> get_1s_count(-1) Traceback (most recent call last): ... - ValueError: the value of input must be positive + ValueError: Input must be a non-negative integer >>> get_1s_count(0.8) Traceback (most recent call last): ... - TypeError: Input value must be an 'int' type + ValueError: Input must be a non-negative integer + >>> get_1s_count("25") + Traceback (most recent call last): + ... + ValueError: Input must be a non-negative integer """ - if number < 0: - raise ValueError("the value of input must be positive") - elif isinstance(number, float): - raise TypeError("Input value must be an 'int' type") + if not isinstance(number, int) or number < 0: + raise ValueError("Input must be a non-negative integer") + count = 0 while number: # This way we arrive at next set bit (next 1) instead of looping From f32d611689dc72bda67f1c4636ab1599c60d27a4 Mon Sep 17 00:00:00 2001 From: Mark Mayo Date: Mon, 21 Nov 2022 00:00:27 +1300 Subject: [PATCH 555/726] clean of unnecessary checks, imports, calls (#7993) --- backtracking/rat_in_maze.py | 4 ++-- boolean_algebra/not_gate.py | 2 +- cellular_automata/nagel_schrekenberg.py | 3 +-- ciphers/mixed_keyword_cypher.py | 4 ++-- compression/huffman.py | 2 +- data_structures/heap/min_heap.py | 2 +- .../test_digital_image_processing.py | 2 +- dynamic_programming/fizz_buzz.py | 5 ++--- dynamic_programming/max_sub_array.py | 3 +-- graphs/directed_and_undirected_(weighted)_graph.py | 8 ++++---- graphs/multi_heuristic_astar.py | 3 ++- linear_algebra/src/lib.py | 2 +- machine_learning/sequential_minimum_optimization.py | 10 ++-------- maths/find_min.py | 3 +-- maths/kadanes.py | 6 ++---- maths/largest_subarray_sum.py | 6 ++---- maths/series/geometric_series.py | 2 +- networking_flow/ford_fulkerson.py | 2 +- networking_flow/minimum_cut.py | 2 +- other/password.py | 10 +++------- project_euler/problem_025/sol1.py | 2 +- project_euler/problem_036/sol1.py | 2 +- quantum/q_fourier_transform.py | 4 ++-- quantum/q_full_adder.py | 6 +++++- quantum/superdense_coding.py | 2 +- sorts/msd_radix_sort.py | 2 +- strings/aho_corasick.py | 2 +- 27 files changed, 44 insertions(+), 57 deletions(-) diff --git a/backtracking/rat_in_maze.py b/backtracking/rat_in_maze.py index 2860880db..7bde886dd 100644 --- a/backtracking/rat_in_maze.py +++ b/backtracking/rat_in_maze.py @@ -88,12 +88,12 @@ def run_maze(maze: list[list[int]], i: int, j: int, solutions: list[list[int]]) solutions[i][j] = 1 return True - lower_flag = (not (i < 0)) and (not (j < 0)) # Check lower bounds + lower_flag = (not i < 0) and (not j < 0) # Check lower bounds upper_flag = (i < size) and (j < size) # Check upper bounds if lower_flag and upper_flag: # check for already visited and block points. - block_flag = (not (solutions[i][j])) and (not (maze[i][j])) + block_flag = (not solutions[i][j]) and (not maze[i][j]) if block_flag: # check visited solutions[i][j] = 1 diff --git a/boolean_algebra/not_gate.py b/boolean_algebra/not_gate.py index b41da602d..eb85e9e44 100644 --- a/boolean_algebra/not_gate.py +++ b/boolean_algebra/not_gate.py @@ -34,4 +34,4 @@ def test_not_gate() -> None: if __name__ == "__main__": print(not_gate(0)) - print(not_gate(1)) + print(not_gate(1)) diff --git a/cellular_automata/nagel_schrekenberg.py b/cellular_automata/nagel_schrekenberg.py index be44761ec..3fd6afca0 100644 --- a/cellular_automata/nagel_schrekenberg.py +++ b/cellular_automata/nagel_schrekenberg.py @@ -45,8 +45,7 @@ def construct_highway( highway = [[-1] * number_of_cells] # Create a highway without any car i = 0 - if initial_speed < 0: - initial_speed = 0 + initial_speed = max(initial_speed, 0) while i < number_of_cells: highway[0][i] = ( randint(0, max_speed) if random_speed else initial_speed diff --git a/ciphers/mixed_keyword_cypher.py b/ciphers/mixed_keyword_cypher.py index f55c9c428..806004faa 100644 --- a/ciphers/mixed_keyword_cypher.py +++ b/ciphers/mixed_keyword_cypher.py @@ -42,7 +42,7 @@ def mixed_keyword(key: str = "college", pt: str = "UNIVERSITY") -> str: s = [] for _ in range(len_temp): s.append(temp[k]) - if not (k < 25): + if k >= 25: break k += 1 modalpha.append(s) @@ -52,7 +52,7 @@ def mixed_keyword(key: str = "college", pt: str = "UNIVERSITY") -> str: k = 0 for j in range(len_temp): for m in modalpha: - if not (len(m) - 1 >= j): + if not len(m) - 1 >= j: break d[alpha[k]] = m[j] if not k < 25: diff --git a/compression/huffman.py b/compression/huffman.py index f619ed82c..b337ac3ec 100644 --- a/compression/huffman.py +++ b/compression/huffman.py @@ -56,7 +56,7 @@ def traverse_tree(root: Letter | TreeNode, bitstring: str) -> list[Letter]: Recursively traverse the Huffman Tree to set each Letter's bitstring dictionary, and return the list of Letters """ - if type(root) is Letter: + if isinstance(root, Letter): root.bitstring[root.letter] = bitstring return [root] treenode: TreeNode = root # type: ignore diff --git a/data_structures/heap/min_heap.py b/data_structures/heap/min_heap.py index 0403624f2..ecb187649 100644 --- a/data_structures/heap/min_heap.py +++ b/data_structures/heap/min_heap.py @@ -121,7 +121,7 @@ class MinHeap: self.sift_up(len(self.heap) - 1) def is_empty(self): - return True if len(self.heap) == 0 else False + return len(self.heap) == 0 def decrease_key(self, node, new_value): assert ( diff --git a/digital_image_processing/test_digital_image_processing.py b/digital_image_processing/test_digital_image_processing.py index fdcebfdad..c999464ce 100644 --- a/digital_image_processing/test_digital_image_processing.py +++ b/digital_image_processing/test_digital_image_processing.py @@ -10,7 +10,7 @@ from digital_image_processing import change_contrast as cc from digital_image_processing import convert_to_negative as cn from digital_image_processing import sepia as sp from digital_image_processing.dithering import burkes as bs -from digital_image_processing.edge_detection import canny as canny +from digital_image_processing.edge_detection import canny from digital_image_processing.filters import convolve as conv from digital_image_processing.filters import gaussian_filter as gg from digital_image_processing.filters import local_binary_pattern as lbp diff --git a/dynamic_programming/fizz_buzz.py b/dynamic_programming/fizz_buzz.py index dd1d21b10..e77ab3de7 100644 --- a/dynamic_programming/fizz_buzz.py +++ b/dynamic_programming/fizz_buzz.py @@ -33,10 +33,9 @@ def fizz_buzz(number: int, iterations: int) -> str: ... ValueError: iterations must be defined as integers """ - - if not type(iterations) == int: + if not isinstance(iterations, int): raise ValueError("iterations must be defined as integers") - if not type(number) == int or not number >= 1: + if not isinstance(number, int) or not number >= 1: raise ValueError( """starting number must be and integer and be more than 0""" diff --git a/dynamic_programming/max_sub_array.py b/dynamic_programming/max_sub_array.py index 42eca79a9..07717fba4 100644 --- a/dynamic_programming/max_sub_array.py +++ b/dynamic_programming/max_sub_array.py @@ -62,8 +62,7 @@ def max_sub_array(nums: list[int]) -> int: current = 0 for i in nums: current += i - if current < 0: - current = 0 + current = max(current, 0) best = max(best, current) return best diff --git a/graphs/directed_and_undirected_(weighted)_graph.py b/graphs/directed_and_undirected_(weighted)_graph.py index 43a72b89e..b29485031 100644 --- a/graphs/directed_and_undirected_(weighted)_graph.py +++ b/graphs/directed_and_undirected_(weighted)_graph.py @@ -167,7 +167,7 @@ class DirectedGraph: and not on_the_way_back ): len_stack = len(stack) - 1 - while True and len_stack >= 0: + while len_stack >= 0: if stack[len_stack] == node[1]: anticipating_nodes.add(node[1]) break @@ -220,7 +220,7 @@ class DirectedGraph: and not on_the_way_back ): len_stack_minus_one = len(stack) - 1 - while True and len_stack_minus_one >= 0: + while len_stack_minus_one >= 0: if stack[len_stack_minus_one] == node[1]: anticipating_nodes.add(node[1]) break @@ -392,7 +392,7 @@ class Graph: and not on_the_way_back ): len_stack = len(stack) - 1 - while True and len_stack >= 0: + while len_stack >= 0: if stack[len_stack] == node[1]: anticipating_nodes.add(node[1]) break @@ -445,7 +445,7 @@ class Graph: and not on_the_way_back ): len_stack_minus_one = len(stack) - 1 - while True and len_stack_minus_one >= 0: + while len_stack_minus_one >= 0: if stack[len_stack_minus_one] == node[1]: anticipating_nodes.add(node[1]) break diff --git a/graphs/multi_heuristic_astar.py b/graphs/multi_heuristic_astar.py index e16a98393..cd8e37b00 100644 --- a/graphs/multi_heuristic_astar.py +++ b/graphs/multi_heuristic_astar.py @@ -1,4 +1,5 @@ import heapq +import sys import numpy as np @@ -116,7 +117,7 @@ def do_something(back_pointer, goal, start): print(x, end=" ") x = back_pointer[x] print(x) - quit() + sys.exit() def valid(p: TPos): diff --git a/linear_algebra/src/lib.py b/linear_algebra/src/lib.py index 775e0244a..ac0398a31 100644 --- a/linear_algebra/src/lib.py +++ b/linear_algebra/src/lib.py @@ -129,7 +129,7 @@ class Vector: input: index (0-indexed) output: the i-th component of the vector. """ - if type(i) is int and -len(self.__components) <= i < len(self.__components): + if isinstance(i, int) and -len(self.__components) <= i < len(self.__components): return self.__components[i] else: raise Exception("index out of range") diff --git a/machine_learning/sequential_minimum_optimization.py b/machine_learning/sequential_minimum_optimization.py index 66535e806..3864f6421 100644 --- a/machine_learning/sequential_minimum_optimization.py +++ b/machine_learning/sequential_minimum_optimization.py @@ -388,16 +388,10 @@ class SmoSVM: return (data - self._min) / (self._max - self._min) def _is_unbound(self, index): - if 0.0 < self.alphas[index] < self._c: - return True - else: - return False + return bool(0.0 < self.alphas[index] < self._c) def _is_support(self, index): - if self.alphas[index] > 0: - return True - else: - return False + return bool(self.alphas[index] > 0) @property def unbound(self): diff --git a/maths/find_min.py b/maths/find_min.py index 228205ed7..2eac087c6 100644 --- a/maths/find_min.py +++ b/maths/find_min.py @@ -24,8 +24,7 @@ def find_min(nums: list[int | float]) -> int | float: raise ValueError("find_min() arg is an empty sequence") min_num = nums[0] for num in nums: - if min_num > num: - min_num = num + min_num = min(min_num, num) return min_num diff --git a/maths/kadanes.py b/maths/kadanes.py index b23409e2b..c2ea53a6c 100644 --- a/maths/kadanes.py +++ b/maths/kadanes.py @@ -49,10 +49,8 @@ def kadanes(arr: list) -> int: for i in arr: max_till_element += i - if max_sum <= max_till_element: - max_sum = max_till_element - if max_till_element < 0: - max_till_element = 0 + max_sum = max(max_sum, max_till_element) + max_till_element = max(max_till_element, 0) return max_sum diff --git a/maths/largest_subarray_sum.py b/maths/largest_subarray_sum.py index 0449e72e6..90f92c712 100644 --- a/maths/largest_subarray_sum.py +++ b/maths/largest_subarray_sum.py @@ -11,10 +11,8 @@ def max_sub_array_sum(a: list, size: int = 0): max_ending_here = 0 for i in range(0, size): max_ending_here = max_ending_here + a[i] - if max_so_far < max_ending_here: - max_so_far = max_ending_here - if max_ending_here < 0: - max_ending_here = 0 + max_so_far = max(max_so_far, max_ending_here) + max_ending_here = max(max_ending_here, 0) return max_so_far diff --git a/maths/series/geometric_series.py b/maths/series/geometric_series.py index a875ab89a..90c9fe77b 100644 --- a/maths/series/geometric_series.py +++ b/maths/series/geometric_series.py @@ -52,7 +52,7 @@ def geometric_series( power = 1 multiple = common_ratio_r for _ in range(int(nth_term)): - if series == []: + if not series: series.append(start_term_a) else: power += 1 diff --git a/networking_flow/ford_fulkerson.py b/networking_flow/ford_fulkerson.py index 370e38482..716ed508e 100644 --- a/networking_flow/ford_fulkerson.py +++ b/networking_flow/ford_fulkerson.py @@ -21,7 +21,7 @@ def bfs(graph, s, t, parent): visited[ind] = True parent[ind] = u - return True if visited[t] else False + return visited[t] def ford_fulkerson(graph, source, sink): diff --git a/networking_flow/minimum_cut.py b/networking_flow/minimum_cut.py index 33131315f..164b45f10 100644 --- a/networking_flow/minimum_cut.py +++ b/networking_flow/minimum_cut.py @@ -24,7 +24,7 @@ def bfs(graph, s, t, parent): visited[ind] = True parent[ind] = u - return True if visited[t] else False + return visited[t] def mincut(graph, source, sink): diff --git a/other/password.py b/other/password.py index f463c7564..9a6161af8 100644 --- a/other/password.py +++ b/other/password.py @@ -89,13 +89,9 @@ def is_strong_password(password: str, min_length: int = 8) -> bool: num = any(char in digits for char in password) spec_char = any(char in punctuation for char in password) - if upper and lower and num and spec_char: - return True - - else: - # Passwords should contain UPPERCASE, lowerase - # numbers, and special characters - return False + return upper and lower and num and spec_char + # Passwords should contain UPPERCASE, lowerase + # numbers, and special characters def main(): diff --git a/project_euler/problem_025/sol1.py b/project_euler/problem_025/sol1.py index c30a74a43..803464b5d 100644 --- a/project_euler/problem_025/sol1.py +++ b/project_euler/problem_025/sol1.py @@ -43,7 +43,7 @@ def fibonacci(n: int) -> int: 144 """ - if n == 1 or type(n) is not int: + if n == 1 or not isinstance(n, int): return 0 elif n == 2: return 1 diff --git a/project_euler/problem_036/sol1.py b/project_euler/problem_036/sol1.py index 425c41221..1d27356ec 100644 --- a/project_euler/problem_036/sol1.py +++ b/project_euler/problem_036/sol1.py @@ -32,7 +32,7 @@ def is_palindrome(n: int | str) -> bool: False """ n = str(n) - return True if n == n[::-1] else False + return n == n[::-1] def solution(n: int = 1000000): diff --git a/quantum/q_fourier_transform.py b/quantum/q_fourier_transform.py index d138dfb45..07a257579 100644 --- a/quantum/q_fourier_transform.py +++ b/quantum/q_fourier_transform.py @@ -55,9 +55,9 @@ def quantum_fourier_transform(number_of_qubits: int = 3) -> qiskit.result.counts ... ValueError: number of qubits must be exact integer. """ - if type(number_of_qubits) == str: + if isinstance(number_of_qubits, str): raise TypeError("number of qubits must be a integer.") - if not number_of_qubits > 0: + if number_of_qubits <= 0: raise ValueError("number of qubits must be > 0.") if math.floor(number_of_qubits) != number_of_qubits: raise ValueError("number of qubits must be exact integer.") diff --git a/quantum/q_full_adder.py b/quantum/q_full_adder.py index c6d03d170..66d931985 100644 --- a/quantum/q_full_adder.py +++ b/quantum/q_full_adder.py @@ -60,7 +60,11 @@ def quantum_full_adder( ... ValueError: inputs must be less or equal to 2. """ - if (type(input_1) == str) or (type(input_2) == str) or (type(carry_in) == str): + if ( + isinstance(input_1, str) + or isinstance(input_2, str) + or isinstance(carry_in, str) + ): raise TypeError("inputs must be integers.") if (input_1 < 0) or (input_2 < 0) or (carry_in < 0): diff --git a/quantum/superdense_coding.py b/quantum/superdense_coding.py index 10ebc2d35..1087312f9 100644 --- a/quantum/superdense_coding.py +++ b/quantum/superdense_coding.py @@ -53,7 +53,7 @@ def superdense_coding(bit_1: int = 1, bit_2: int = 1) -> qiskit.result.counts.Co ... ValueError: inputs must be less or equal to 1. """ - if (type(bit_1) == str) or (type(bit_2) == str): + if isinstance(bit_1, str) or isinstance(bit_2, str): raise TypeError("inputs must be integers.") if (bit_1 < 0) or (bit_2 < 0): raise ValueError("inputs must be positive.") diff --git a/sorts/msd_radix_sort.py b/sorts/msd_radix_sort.py index 84460e47b..74ce21762 100644 --- a/sorts/msd_radix_sort.py +++ b/sorts/msd_radix_sort.py @@ -133,7 +133,7 @@ def _msd_radix_sort_inplace( j = end_index - 1 while i <= j: changed = False - if not ((list_of_ints[i] >> bit_position) & 1): + if not (list_of_ints[i] >> bit_position) & 1: # found zero at the beginning i += 1 changed = True diff --git a/strings/aho_corasick.py b/strings/aho_corasick.py index 25ed649ce..e32a4ba64 100644 --- a/strings/aho_corasick.py +++ b/strings/aho_corasick.py @@ -84,7 +84,7 @@ class Automaton: else: current_state = next_state for key in self.adlist[current_state]["output"]: - if not (key in result): + if key not in result: result[key] = [] result[key].append(i - len(key) + 1) return result From 08c22457058207dc465b9ba9fd95659d33b3f1dd Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 29 Nov 2022 16:56:41 +0100 Subject: [PATCH 556/726] Upgrade to flake8 v6 (#8007) * Upgrade to flake8 v6 * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .flake8 | 6 ++++-- .pre-commit-config.yaml | 6 +++--- DIRECTORY.md | 2 ++ compression/huffman.py | 4 ++-- data_structures/binary_tree/non_recursive_segment_tree.py | 2 +- data_structures/binary_tree/segment_tree.py | 6 +++--- machine_learning/sequential_minimum_optimization.py | 2 +- project_euler/problem_107/sol1.py | 1 - 8 files changed, 16 insertions(+), 13 deletions(-) diff --git a/.flake8 b/.flake8 index 2f74f421d..b68ee8533 100644 --- a/.flake8 +++ b/.flake8 @@ -4,5 +4,7 @@ max-line-length = 88 max-complexity = 19 extend-ignore = # Formatting style for `black` - E203 # Whitespace before ':' - W503 # Line break occurred before a binary operator + # E203 is whitespace before ':' + E203, + # W503 is line break occurred before a binary operator + W503 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 324a021ee..74502b3ea 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.3.0 + rev: v4.4.0 hooks: - id: check-executables-have-shebangs - id: check-yaml @@ -34,13 +34,13 @@ repos: - --py311-plus - repo: https://github.com/PyCQA/flake8 - rev: 5.0.4 + rev: 6.0.0 hooks: - id: flake8 # See .flake8 for args additional_dependencies: &flake8-plugins - flake8-bugbear - flake8-builtins - - flake8-broken-line + # - flake8-broken-line - flake8-comprehensions - pep8-naming diff --git a/DIRECTORY.md b/DIRECTORY.md index 83da4b76a..b3b484f73 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -375,6 +375,7 @@ * [Articulation Points](graphs/articulation_points.py) * [Basic Graphs](graphs/basic_graphs.py) * [Bellman Ford](graphs/bellman_ford.py) + * [Bi Directional Dijkstra](graphs/bi_directional_dijkstra.py) * [Bidirectional A Star](graphs/bidirectional_a_star.py) * [Bidirectional Breadth First Search](graphs/bidirectional_breadth_first_search.py) * [Boruvka](graphs/boruvka.py) @@ -563,6 +564,7 @@ * [Is Ip V4 Address Valid](maths/is_ip_v4_address_valid.py) * [Is Square Free](maths/is_square_free.py) * [Jaccard Similarity](maths/jaccard_similarity.py) + * [Juggler Sequence](maths/juggler_sequence.py) * [Kadanes](maths/kadanes.py) * [Karatsuba](maths/karatsuba.py) * [Krishnamurthy Number](maths/krishnamurthy_number.py) diff --git a/compression/huffman.py b/compression/huffman.py index b337ac3ec..65e5c2f25 100644 --- a/compression/huffman.py +++ b/compression/huffman.py @@ -32,7 +32,7 @@ def parse_file(file_path: str) -> list[Letter]: if not c: break chars[c] = chars[c] + 1 if c in chars 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 x: x.freq) def build_tree(letters: list[Letter]) -> Letter | TreeNode: @@ -47,7 +47,7 @@ def build_tree(letters: list[Letter]) -> Letter | TreeNode: total_freq = left.freq + right.freq node = TreeNode(total_freq, left, right) response.append(node) - response.sort(key=lambda l: l.freq) + response.sort(key=lambda x: x.freq) return response[0] diff --git a/data_structures/binary_tree/non_recursive_segment_tree.py b/data_structures/binary_tree/non_recursive_segment_tree.py index 075ff6c91..04164e5cb 100644 --- a/data_structures/binary_tree/non_recursive_segment_tree.py +++ b/data_structures/binary_tree/non_recursive_segment_tree.py @@ -106,7 +106,7 @@ class SegmentTree(Generic[T]): l, r = l + self.N, r + self.N res: T | None = None - while l <= r: # noqa: E741 + while l <= r: if l % 2 == 1: res = self.st[l] if res is None else self.fn(res, self.st[l]) if r % 2 == 0: diff --git a/data_structures/binary_tree/segment_tree.py b/data_structures/binary_tree/segment_tree.py index 949a3ecdd..b05803869 100644 --- a/data_structures/binary_tree/segment_tree.py +++ b/data_structures/binary_tree/segment_tree.py @@ -16,7 +16,7 @@ class SegmentTree: return idx * 2 + 1 def build(self, idx, l, r): # noqa: E741 - if l == r: # noqa: E741 + if l == r: self.st[idx] = A[l] else: mid = (l + r) // 2 @@ -33,7 +33,7 @@ class SegmentTree: """ if r < a or l > b: return True - if l == r: # noqa: E741 + if l == r: self.st[idx] = val return True mid = (l + r) // 2 @@ -51,7 +51,7 @@ class SegmentTree: """ if r < a or l > b: return -math.inf - if l >= a and r <= b: # noqa: E741 + if l >= a and r <= b: return self.st[idx] mid = (l + r) // 2 q1 = self.query_recursive(self.left(idx), l, mid, a, b) diff --git a/machine_learning/sequential_minimum_optimization.py b/machine_learning/sequential_minimum_optimization.py index 3864f6421..f5185e1d9 100644 --- a/machine_learning/sequential_minimum_optimization.py +++ b/machine_learning/sequential_minimum_optimization.py @@ -314,7 +314,7 @@ class SmoSVM: l, h = max(0.0, a2 - a1), min(self._c, self._c + a2 - a1) else: l, h = max(0.0, a2 + a1 - self._c), min(self._c, a2 + a1) - if l == h: # noqa: E741 + if l == h: return None, None # calculate eta diff --git a/project_euler/problem_107/sol1.py b/project_euler/problem_107/sol1.py index b3f5685b9..4659eac24 100644 --- a/project_euler/problem_107/sol1.py +++ b/project_euler/problem_107/sol1.py @@ -99,7 +99,6 @@ 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] = {} data: list[str] edge1: int From 47bf3f58e04873ef609301b1e654f6ddcc02b0fa Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Tue, 29 Nov 2022 22:07:27 +0400 Subject: [PATCH 558/726] fix validation condition and add tests (#7997) * fix validation condition and add tests * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- bit_manipulation/index_of_rightmost_set_bit.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/bit_manipulation/index_of_rightmost_set_bit.py b/bit_manipulation/index_of_rightmost_set_bit.py index eb52ea4e6..c9c911660 100644 --- a/bit_manipulation/index_of_rightmost_set_bit.py +++ b/bit_manipulation/index_of_rightmost_set_bit.py @@ -19,9 +19,17 @@ def get_index_of_rightmost_set_bit(number: int) -> int: Traceback (most recent call last): ... ValueError: Input must be a non-negative integer + >>> get_index_of_rightmost_set_bit('test') + Traceback (most recent call last): + ... + ValueError: Input must be a non-negative integer + >>> get_index_of_rightmost_set_bit(1.25) + Traceback (most recent call last): + ... + ValueError: Input must be a non-negative integer """ - if number < 0 or not isinstance(number, int): + if not isinstance(number, int) or number < 0: raise ValueError("Input must be a non-negative integer") intermediate = number & ~(number - 1) From 6a86fe48671adb90504412acc2589c3ab1b18564 Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Tue, 29 Nov 2022 22:28:47 +0400 Subject: [PATCH 559/726] Add backtrack word search in matrix (#8005) * add backtracking word search * updating DIRECTORY.md * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * review notes fixes * additional fixes * add tests * small cleanup * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * small cleanup 2 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update backtracking/word_search.py Co-authored-by: Christian Clauss * Update backtracking/word_search.py Co-authored-by: Christian Clauss * Update backtracking/word_search.py Co-authored-by: Christian Clauss * Update backtracking/word_search.py Co-authored-by: Christian Clauss Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- DIRECTORY.md | 1 + backtracking/word_search.py | 160 ++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 backtracking/word_search.py diff --git a/DIRECTORY.md b/DIRECTORY.md index b3b484f73..51430a1e1 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -33,6 +33,7 @@ * [Rat In Maze](backtracking/rat_in_maze.py) * [Sudoku](backtracking/sudoku.py) * [Sum Of Subsets](backtracking/sum_of_subsets.py) + * [Word Search](backtracking/word_search.py) ## Bit Manipulation * [Binary And Operator](bit_manipulation/binary_and_operator.py) diff --git a/backtracking/word_search.py b/backtracking/word_search.py new file mode 100644 index 000000000..25d1436be --- /dev/null +++ b/backtracking/word_search.py @@ -0,0 +1,160 @@ +""" +Author : Alexander Pantyukhin +Date : November 24, 2022 + +Task: +Given an m x n grid of characters board and a string word, +return true if word exists in the grid. + +The word can be constructed from letters of sequentially adjacent cells, +where adjacent cells are horizontally or vertically neighboring. +The same letter cell may not be used more than once. + +Example: + +Matrix: +--------- +|A|B|C|E| +|S|F|C|S| +|A|D|E|E| +--------- + +Word: +"ABCCED" + +Result: +True + +Implementation notes: Use backtracking approach. +At each point, check all neighbors to try to find the next letter of the word. + +leetcode: https://leetcode.com/problems/word-search/ + +""" + + +def word_exists(board: list[list[str]], word: str) -> bool: + """ + >>> word_exists([["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], "ABCCED") + True + >>> word_exists([["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], "SEE") + True + >>> word_exists([["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], "ABCB") + False + >>> word_exists([["A"]], "A") + True + >>> word_exists([["A","A","A","A","A","A"], + ... ["A","A","A","A","A","A"], + ... ["A","A","A","A","A","A"], + ... ["A","A","A","A","A","A"], + ... ["A","A","A","A","A","B"], + ... ["A","A","A","A","B","A"]], + ... "AAAAAAAAAAAAABB") + False + >>> word_exists([["A"]], 123) + Traceback (most recent call last): + ... + ValueError: The word parameter should be a string of length greater than 0. + >>> word_exists([["A"]], "") + Traceback (most recent call last): + ... + ValueError: The word parameter should be a string of length greater than 0. + >>> word_exists([[]], "AB") + Traceback (most recent call last): + ... + ValueError: The board should be a non empty matrix of single chars strings. + >>> word_exists([], "AB") + Traceback (most recent call last): + ... + ValueError: The board should be a non empty matrix of single chars strings. + >>> word_exists([["A"], [21]], "AB") + Traceback (most recent call last): + ... + ValueError: The board should be a non empty matrix of single chars strings. + """ + + # Validate board + board_error_message = ( + "The board should be a non empty matrix of single chars strings." + ) + if not isinstance(board, list) or len(board) == 0: + raise ValueError(board_error_message) + + for row in board: + if not isinstance(row, list) or len(row) == 0: + raise ValueError(board_error_message) + + for item in row: + if not isinstance(item, str) or len(item) != 1: + raise ValueError(board_error_message) + + # Validate word + if not isinstance(word, str) or len(word) == 0: + raise ValueError( + "The word parameter should be a string of length greater than 0." + ) + + traverts_directions = [(0, 1), (0, -1), (-1, 0), (1, 0)] + len_word = len(word) + len_board = len(board) + len_board_column = len(board[0]) + + # Returns the hash key of matrix indexes. + def get_point_key(row: int, column: int) -> int: + """ + >>> len_board=10 + >>> len_board_column=20 + >>> get_point_key(0, 0) + 200 + """ + + return len_board * len_board_column * row + column + + # Return True if it's possible to search the word suffix + # starting from the word_index. + def exits_word( + row: int, column: int, word_index: int, visited_points_set: set[int] + ) -> bool: + """ + >>> board=[["A"]] + >>> word="B" + >>> exits_word(0, 0, 0, set()) + False + """ + + if board[row][column] != word[word_index]: + return False + + if word_index == len_word - 1: + return True + + for direction in traverts_directions: + next_i = row + direction[0] + next_j = column + direction[1] + if not (0 <= next_i < len_board and 0 <= next_j < len_board_column): + continue + + key = get_point_key(next_i, next_j) + if key in visited_points_set: + continue + + visited_points_set.add(key) + if exits_word(next_i, next_j, word_index + 1, visited_points_set): + return True + + visited_points_set.remove(key) + + return False + + for i in range(len_board): + for j in range(len_board_column): + if exits_word(i, j, 0, {get_point_key(i, j)}): + return True + + return False + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 5654c6242ed5974fa8f2aa89d9689efa012bdafc Mon Sep 17 00:00:00 2001 From: Akshay Dubey <38462415+itsAkshayDubey@users.noreply.github.com> Date: Tue, 29 Nov 2022 23:59:21 +0530 Subject: [PATCH 560/726] algorithm: Hexagonal number (#8003) * feat: Add hexagonal number * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/hexagonal_number.py | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 maths/hexagonal_number.py diff --git a/maths/hexagonal_number.py b/maths/hexagonal_number.py new file mode 100644 index 000000000..28735c638 --- /dev/null +++ b/maths/hexagonal_number.py @@ -0,0 +1,48 @@ +""" +== Hexagonal Number == +The nth hexagonal number hn is the number of distinct dots +in a pattern of dots consisting of the outlines of regular +hexagons with sides up to n dots, when the hexagons are +overlaid so that they share one vertex. + +https://en.wikipedia.org/wiki/Hexagonal_number +""" + +# Author : Akshay Dubey (https://github.com/itsAkshayDubey) + + +def hexagonal(number: int) -> int: + """ + :param number: nth hexagonal number to calculate + :return: the nth hexagonal number + Note: A hexagonal number is only defined for positive integers + >>> hexagonal(4) + 28 + >>> hexagonal(11) + 231 + >>> hexagonal(22) + 946 + >>> hexagonal(0) + Traceback (most recent call last): + ... + ValueError: Input must be a positive integer + >>> hexagonal(-1) + Traceback (most recent call last): + ... + ValueError: Input must be a positive integer + >>> hexagonal(11.0) + Traceback (most recent call last): + ... + TypeError: Input value of [number=11.0] must be an integer + """ + if not isinstance(number, int): + raise TypeError(f"Input value of [number={number}] must be an integer") + if number < 1: + raise ValueError("Input must be a positive integer") + return number * (2 * number - 1) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From d141fa8838369fafb3b28a8dd825ec1b20d34e03 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 5 Dec 2022 21:34:24 +0100 Subject: [PATCH 561/726] [pre-commit.ci] pre-commit autoupdate (#8017) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/asottile/pyupgrade: v3.2.2 → v3.3.0](https://github.com/asottile/pyupgrade/compare/v3.2.2...v3.3.0) * updating DIRECTORY.md Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- DIRECTORY.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 74502b3ea..3d83499f0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,7 +27,7 @@ repos: - --profile=black - repo: https://github.com/asottile/pyupgrade - rev: v3.2.2 + rev: v3.3.0 hooks: - id: pyupgrade args: diff --git a/DIRECTORY.md b/DIRECTORY.md index 51430a1e1..382ff3a6f 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -561,6 +561,7 @@ * [Greedy Coin Change](maths/greedy_coin_change.py) * [Hamming Numbers](maths/hamming_numbers.py) * [Hardy Ramanujanalgo](maths/hardy_ramanujanalgo.py) + * [Hexagonal Number](maths/hexagonal_number.py) * [Integration By Simpson Approx](maths/integration_by_simpson_approx.py) * [Is Ip V4 Address Valid](maths/is_ip_v4_address_valid.py) * [Is Square Free](maths/is_square_free.py) From b25915adf91cc39c98c597fce1eef9422f4e7d0d Mon Sep 17 00:00:00 2001 From: Aaryan Raj <97806283+iaaryanraj@users.noreply.github.com> Date: Sun, 11 Dec 2022 12:34:04 +0530 Subject: [PATCH 562/726] Add algorithm to convert decimal number to its simplest fraction form (#8001) * Added algorithm to convert decimal number to its simplest fraction form * Apply suggested changes --- maths/decimal_to_fraction.py | 48 ++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 maths/decimal_to_fraction.py diff --git a/maths/decimal_to_fraction.py b/maths/decimal_to_fraction.py new file mode 100644 index 000000000..9462bafe0 --- /dev/null +++ b/maths/decimal_to_fraction.py @@ -0,0 +1,48 @@ +def decimal_to_fraction(decimal: int | float | str) -> tuple[int, int]: + """ + Return a decimal number in its simplest fraction form + >>> decimal_to_fraction(2) + (2, 1) + >>> decimal_to_fraction(89.) + (89, 1) + >>> decimal_to_fraction("67") + (67, 1) + >>> decimal_to_fraction("45.0") + (45, 1) + >>> decimal_to_fraction(1.5) + (3, 2) + >>> decimal_to_fraction("6.25") + (25, 4) + >>> decimal_to_fraction("78td") + Traceback (most recent call last): + ValueError: Please enter a valid number + """ + try: + decimal = float(decimal) + except ValueError: + raise ValueError("Please enter a valid number") + fractional_part = decimal - int(decimal) + if fractional_part == 0: + return int(decimal), 1 + else: + number_of_frac_digits = len(str(decimal).split(".")[1]) + numerator = int(decimal * (10**number_of_frac_digits)) + denominator = 10**number_of_frac_digits + divisor, dividend = denominator, numerator + while True: + remainder = dividend % divisor + if remainder == 0: + break + dividend, divisor = divisor, remainder + numerator, denominator = numerator / divisor, denominator / divisor + return int(numerator), int(denominator) + + +if __name__ == "__main__": + print(f"{decimal_to_fraction(2) = }") + print(f"{decimal_to_fraction(89.0) = }") + print(f"{decimal_to_fraction('67') = }") + print(f"{decimal_to_fraction('45.0') = }") + print(f"{decimal_to_fraction(1.5) = }") + print(f"{decimal_to_fraction('6.25') = }") + print(f"{decimal_to_fraction('78td') = }") From 40f165b789e9a2475415768db5acadf63e021e46 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 12 Dec 2022 21:29:50 +0100 Subject: [PATCH 563/726] [pre-commit.ci] pre-commit autoupdate (#8026) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/psf/black: 22.10.0 → 22.12.0](https://github.com/psf/black/compare/22.10.0...22.12.0) - [github.com/asottile/pyupgrade: v3.3.0 → v3.3.1](https://github.com/asottile/pyupgrade/compare/v3.3.0...v3.3.1) * updating DIRECTORY.md Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- DIRECTORY.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3d83499f0..7cf4bedd7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: - id: auto-walrus - repo: https://github.com/psf/black - rev: 22.10.0 + rev: 22.12.0 hooks: - id: black @@ -27,7 +27,7 @@ repos: - --profile=black - repo: https://github.com/asottile/pyupgrade - rev: v3.3.0 + rev: v3.3.1 hooks: - id: pyupgrade args: diff --git a/DIRECTORY.md b/DIRECTORY.md index 382ff3a6f..0624eda2c 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -533,6 +533,7 @@ * [Collatz Sequence](maths/collatz_sequence.py) * [Combinations](maths/combinations.py) * [Decimal Isolate](maths/decimal_isolate.py) + * [Decimal To Fraction](maths/decimal_to_fraction.py) * [Dodecahedron](maths/dodecahedron.py) * [Double Factorial Iterative](maths/double_factorial_iterative.py) * [Double Factorial Recursive](maths/double_factorial_recursive.py) From af8d52092232e1104154b733000716036e668444 Mon Sep 17 00:00:00 2001 From: Roberto Garcia <37519995+rga2@users.noreply.github.com> Date: Wed, 14 Dec 2022 22:10:09 -0600 Subject: [PATCH 564/726] Update is_even.py (#8028) --- bit_manipulation/is_even.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bit_manipulation/is_even.py b/bit_manipulation/is_even.py index b7b0841a1..ba036f35a 100644 --- a/bit_manipulation/is_even.py +++ b/bit_manipulation/is_even.py @@ -11,7 +11,7 @@ def is_even(number: int) -> bool: from the above examples we can observe that for all the odd integers there is always 1 set bit at the end also, 1 in binary can be represented as 001, 00001, or 0000001 - so for any odd integer n => n&1 is always equlas 1 else the integer is even + so for any odd integer n => n&1 is always equals 1 else the integer is even >>> is_even(1) False From 30277f8590a7bf636477fa4c4ad22cedf10588f5 Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Thu, 15 Dec 2022 08:11:32 +0400 Subject: [PATCH 565/726] add numbers different signs algorithm. (#8008) --- DIRECTORY.md | 1 + bit_manipulation/numbers_different_signs.py | 39 +++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 bit_manipulation/numbers_different_signs.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 0624eda2c..34ce88a4f 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -50,6 +50,7 @@ * [Index Of Rightmost Set Bit](bit_manipulation/index_of_rightmost_set_bit.py) * [Is Even](bit_manipulation/is_even.py) * [Is Power Of Two](bit_manipulation/is_power_of_two.py) + * [Numbers Different Signs](bit_manipulation/numbers_different_signs.py) * [Reverse Bits](bit_manipulation/reverse_bits.py) * [Single Bit Manipulation Operations](bit_manipulation/single_bit_manipulation_operations.py) diff --git a/bit_manipulation/numbers_different_signs.py b/bit_manipulation/numbers_different_signs.py new file mode 100644 index 000000000..cf8b6d86f --- /dev/null +++ b/bit_manipulation/numbers_different_signs.py @@ -0,0 +1,39 @@ +""" +Author : Alexander Pantyukhin +Date : November 30, 2022 + +Task: +Given two int numbers. Return True these numbers have opposite signs +or False otherwise. + +Implementation notes: Use bit manipulation. +Use XOR for two numbers. +""" + + +def different_signs(num1: int, num2: int) -> bool: + """ + Return True if numbers have opposite signs False otherwise. + + >>> different_signs(1, -1) + True + >>> different_signs(1, 1) + False + >>> different_signs(1000000000000000000000000000, -1000000000000000000000000000) + True + >>> different_signs(-1000000000000000000000000000, 1000000000000000000000000000) + True + >>> different_signs(50, 278) + False + >>> different_signs(0, 2) + False + >>> different_signs(2, 0) + False + """ + return num1 ^ num2 < 0 + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 3f8b2af14bd3b64b838098f9e1830c0fea926a1a Mon Sep 17 00:00:00 2001 From: Victor Rodrigues da Silva <63797831+VictorRS27@users.noreply.github.com> Date: Sun, 18 Dec 2022 19:26:39 -0300 Subject: [PATCH 566/726] Add autoclave cipher (#8029) * Add autoclave cipher * Update autoclave with the given suggestions * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixing errors * Another fixes * Update and rename autoclave.py to autokey.py * Rename gaussian_naive_bayes.py to gaussian_naive_bayes.py.broken.txt * Rename gradient_boosting_regressor.py to gradient_boosting_regressor.py.broken.txt * Rename random_forest_classifier.py to random_forest_classifier.py.broken.txt * Rename random_forest_regressor.py to random_forest_regressor.py.broken.txt * Rename equal_loudness_filter.py to equal_loudness_filter.py.broken.txt Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- ...py => equal_loudness_filter.py.broken.txt} | 0 ciphers/autokey.py | 131 ++++++++++++++++++ ....py => gaussian_naive_bayes.py.broken.txt} | 0 ...gradient_boosting_regressor.py.broken.txt} | 0 ...=> random_forest_classifier.py.broken.txt} | 0 ... => random_forest_regressor.py.broken.txt} | 0 6 files changed, 131 insertions(+) rename audio_filters/{equal_loudness_filter.py => equal_loudness_filter.py.broken.txt} (100%) create mode 100644 ciphers/autokey.py rename machine_learning/{gaussian_naive_bayes.py => gaussian_naive_bayes.py.broken.txt} (100%) rename machine_learning/{gradient_boosting_regressor.py => gradient_boosting_regressor.py.broken.txt} (100%) rename machine_learning/{random_forest_classifier.py => random_forest_classifier.py.broken.txt} (100%) rename machine_learning/{random_forest_regressor.py => random_forest_regressor.py.broken.txt} (100%) diff --git a/audio_filters/equal_loudness_filter.py b/audio_filters/equal_loudness_filter.py.broken.txt similarity index 100% rename from audio_filters/equal_loudness_filter.py rename to audio_filters/equal_loudness_filter.py.broken.txt diff --git a/ciphers/autokey.py b/ciphers/autokey.py new file mode 100644 index 000000000..8683e6d37 --- /dev/null +++ b/ciphers/autokey.py @@ -0,0 +1,131 @@ +""" +https://en.wikipedia.org/wiki/Autokey_cipher +An autokey cipher (also known as the autoclave cipher) is a cipher that +incorporates the message (the plaintext) into the key. +The key is generated from the message in some automated fashion, +sometimes by selecting certain letters from the text or, more commonly, +by adding a short primer key to the front of the message. +""" + + +def encrypt(plaintext: str, key: str) -> str: + """ + Encrypt a given plaintext (string) and key (string), returning the + encrypted ciphertext. + >>> encrypt("hello world", "coffee") + 'jsqqs avvwo' + >>> encrypt("coffee is good as python", "TheAlgorithms") + 'vvjfpk wj ohvp su ddylsv' + >>> encrypt("coffee is good as python", 2) + Traceback (most recent call last): + ... + TypeError: key must be a string + >>> encrypt("", "TheAlgorithms") + Traceback (most recent call last): + ... + ValueError: plaintext is empty + """ + if not isinstance(plaintext, str): + raise TypeError("plaintext must be a string") + if not isinstance(key, str): + raise TypeError("key must be a string") + + if not plaintext: + raise ValueError("plaintext is empty") + if not key: + raise ValueError("key is empty") + + key += plaintext + plaintext = plaintext.lower() + key = key.lower() + plaintext_iterator = 0 + key_iterator = 0 + ciphertext = "" + while plaintext_iterator < len(plaintext): + if ( + ord(plaintext[plaintext_iterator]) < 97 + or ord(plaintext[plaintext_iterator]) > 122 + ): + ciphertext += plaintext[plaintext_iterator] + plaintext_iterator += 1 + elif ord(key[key_iterator]) < 97 or ord(key[key_iterator]) > 122: + key_iterator += 1 + else: + ciphertext += chr( + ( + (ord(plaintext[plaintext_iterator]) - 97 + ord(key[key_iterator])) + - 97 + ) + % 26 + + 97 + ) + key_iterator += 1 + plaintext_iterator += 1 + return ciphertext + + +def decrypt(ciphertext: str, key: str) -> str: + """ + Decrypt a given ciphertext (string) and key (string), returning the decrypted + ciphertext. + >>> decrypt("jsqqs avvwo", "coffee") + 'hello world' + >>> decrypt("vvjfpk wj ohvp su ddylsv", "TheAlgorithms") + 'coffee is good as python' + >>> decrypt("vvjfpk wj ohvp su ddylsv", "") + Traceback (most recent call last): + ... + ValueError: key is empty + >>> decrypt(527.26, "TheAlgorithms") + Traceback (most recent call last): + ... + TypeError: ciphertext must be a string + """ + if not isinstance(ciphertext, str): + raise TypeError("ciphertext must be a string") + if not isinstance(key, str): + raise TypeError("key must be a string") + + if not ciphertext: + raise ValueError("ciphertext is empty") + if not key: + raise ValueError("key is empty") + + key = key.lower() + ciphertext_iterator = 0 + key_iterator = 0 + plaintext = "" + while ciphertext_iterator < len(ciphertext): + if ( + ord(ciphertext[ciphertext_iterator]) < 97 + or ord(ciphertext[ciphertext_iterator]) > 122 + ): + plaintext += ciphertext[ciphertext_iterator] + else: + plaintext += chr( + (ord(ciphertext[ciphertext_iterator]) - ord(key[key_iterator])) % 26 + + 97 + ) + key += chr( + (ord(ciphertext[ciphertext_iterator]) - ord(key[key_iterator])) % 26 + + 97 + ) + key_iterator += 1 + ciphertext_iterator += 1 + return plaintext + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + operation = int(input("Type 1 to encrypt or 2 to decrypt:")) + if operation == 1: + plaintext = input("Typeplaintext to be encrypted:\n") + key = input("Type the key:\n") + print(encrypt(plaintext, key)) + elif operation == 2: + ciphertext = input("Type the ciphertext to be decrypted:\n") + key = input("Type the key:\n") + print(decrypt(ciphertext, key)) + decrypt("jsqqs avvwo", "coffee") diff --git a/machine_learning/gaussian_naive_bayes.py b/machine_learning/gaussian_naive_bayes.py.broken.txt similarity index 100% rename from machine_learning/gaussian_naive_bayes.py rename to machine_learning/gaussian_naive_bayes.py.broken.txt diff --git a/machine_learning/gradient_boosting_regressor.py b/machine_learning/gradient_boosting_regressor.py.broken.txt similarity index 100% rename from machine_learning/gradient_boosting_regressor.py rename to machine_learning/gradient_boosting_regressor.py.broken.txt diff --git a/machine_learning/random_forest_classifier.py b/machine_learning/random_forest_classifier.py.broken.txt similarity index 100% rename from machine_learning/random_forest_classifier.py rename to machine_learning/random_forest_classifier.py.broken.txt diff --git a/machine_learning/random_forest_regressor.py b/machine_learning/random_forest_regressor.py.broken.txt similarity index 100% rename from machine_learning/random_forest_regressor.py rename to machine_learning/random_forest_regressor.py.broken.txt From d4c5b22424d05d3198dc2e5a49427e929b058ccf Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 19 Dec 2022 23:04:34 +0100 Subject: [PATCH 567/726] [pre-commit.ci] pre-commit autoupdate (#8037) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/MarcoGorelli/auto-walrus: v0.2.1 → v0.2.2](https://github.com/MarcoGorelli/auto-walrus/compare/v0.2.1...v0.2.2) - [github.com/PyCQA/isort: 5.10.1 → v5.11.3](https://github.com/PyCQA/isort/compare/5.10.1...v5.11.3) * updating DIRECTORY.md Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- DIRECTORY.md | 6 +----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7cf4bedd7..0f5fe20a8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,7 +10,7 @@ repos: - id: requirements-txt-fixer - repo: https://github.com/MarcoGorelli/auto-walrus - rev: v0.2.1 + rev: v0.2.2 hooks: - id: auto-walrus @@ -20,7 +20,7 @@ repos: - id: black - repo: https://github.com/PyCQA/isort - rev: 5.10.1 + rev: v5.11.3 hooks: - id: isort args: diff --git a/DIRECTORY.md b/DIRECTORY.md index 34ce88a4f..bec857a38 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -14,7 +14,6 @@ ## Audio Filters * [Butterworth Filter](audio_filters/butterworth_filter.py) - * [Equal Loudness Filter](audio_filters/equal_loudness_filter.py) * [Iir Filter](audio_filters/iir_filter.py) * [Show Response](audio_filters/show_response.py) @@ -79,6 +78,7 @@ * [A1Z26](ciphers/a1z26.py) * [Affine Cipher](ciphers/affine_cipher.py) * [Atbash](ciphers/atbash.py) + * [Autokey](ciphers/autokey.py) * [Baconian Cipher](ciphers/baconian_cipher.py) * [Base16](ciphers/base16.py) * [Base32](ciphers/base32.py) @@ -475,8 +475,6 @@ * [Decision Tree](machine_learning/decision_tree.py) * Forecasting * [Run](machine_learning/forecasting/run.py) - * [Gaussian Naive Bayes](machine_learning/gaussian_naive_bayes.py) - * [Gradient Boosting Regressor](machine_learning/gradient_boosting_regressor.py) * [Gradient Descent](machine_learning/gradient_descent.py) * [K Means Clust](machine_learning/k_means_clust.py) * [K Nearest Neighbours](machine_learning/k_nearest_neighbours.py) @@ -490,8 +488,6 @@ * [Lstm Prediction](machine_learning/lstm/lstm_prediction.py) * [Multilayer Perceptron Classifier](machine_learning/multilayer_perceptron_classifier.py) * [Polymonial Regression](machine_learning/polymonial_regression.py) - * [Random Forest Classifier](machine_learning/random_forest_classifier.py) - * [Random Forest Regressor](machine_learning/random_forest_regressor.py) * [Scoring Functions](machine_learning/scoring_functions.py) * [Self Organizing Map](machine_learning/self_organizing_map.py) * [Sequential Minimum Optimization](machine_learning/sequential_minimum_optimization.py) From 79ef431cec53020709268507b6515ff1e7e47680 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sat, 24 Dec 2022 17:57:28 +0300 Subject: [PATCH 568/726] Reduce the complexity of sorts/merge_insertion_sort.py (#7954) * Reduce the complexity of sorts/merge_insertion_sort.py * Add tests * Lower the --max-complexity threshold in the file .flake8 --- .flake8 | 2 +- sorts/merge_insertion_sort.py | 79 +++++++++++++++++++++-------------- 2 files changed, 48 insertions(+), 33 deletions(-) diff --git a/.flake8 b/.flake8 index b68ee8533..77ca7a328 100644 --- a/.flake8 +++ b/.flake8 @@ -1,7 +1,7 @@ [flake8] max-line-length = 88 # max-complexity should be 10 -max-complexity = 19 +max-complexity = 17 extend-ignore = # Formatting style for `black` # E203 is whitespace before ':' diff --git a/sorts/merge_insertion_sort.py b/sorts/merge_insertion_sort.py index ecaa53545..4a5bdea0a 100644 --- a/sorts/merge_insertion_sort.py +++ b/sorts/merge_insertion_sort.py @@ -14,6 +14,53 @@ python3 merge_insertion_sort.py from __future__ import annotations +def binary_search_insertion(sorted_list, item): + """ + >>> binary_search_insertion([1, 2, 7, 9, 10], 4) + [1, 2, 4, 7, 9, 10] + """ + left = 0 + right = len(sorted_list) - 1 + while left <= right: + middle = (left + right) // 2 + if left == right: + if sorted_list[middle] < item: + left = middle + 1 + break + elif sorted_list[middle] < item: + left = middle + 1 + else: + right = middle - 1 + sorted_list.insert(left, item) + return sorted_list + + +def merge(left, right): + """ + >>> merge([[1, 6], [9, 10]], [[2, 3], [4, 5], [7, 8]]) + [[1, 6], [2, 3], [4, 5], [7, 8], [9, 10]] + """ + result = [] + while left and right: + if left[0][0] < right[0][0]: + result.append(left.pop(0)) + else: + result.append(right.pop(0)) + return result + left + right + + +def sortlist_2d(list_2d): + """ + >>> sortlist_2d([[9, 10], [1, 6], [7, 8], [2, 3], [4, 5]]) + [[1, 6], [2, 3], [4, 5], [7, 8], [9, 10]] + """ + length = len(list_2d) + if length <= 1: + return list_2d + middle = length // 2 + return merge(sortlist_2d(list_2d[:middle]), sortlist_2d(list_2d[middle:])) + + def merge_insertion_sort(collection: list[int]) -> list[int]: """Pure implementation of merge-insertion sort algorithm in Python @@ -38,38 +85,6 @@ def merge_insertion_sort(collection: list[int]) -> list[int]: True """ - def binary_search_insertion(sorted_list, item): - left = 0 - right = len(sorted_list) - 1 - while left <= right: - middle = (left + right) // 2 - if left == right: - if sorted_list[middle] < item: - left = middle + 1 - break - elif sorted_list[middle] < item: - left = middle + 1 - else: - right = middle - 1 - sorted_list.insert(left, item) - return sorted_list - - def sortlist_2d(list_2d): - def merge(left, right): - result = [] - while left and right: - if left[0][0] < right[0][0]: - result.append(left.pop(0)) - else: - result.append(right.pop(0)) - return result + left + right - - length = len(list_2d) - if length <= 1: - return list_2d - middle = length // 2 - return merge(sortlist_2d(list_2d[:middle]), sortlist_2d(list_2d[middle:])) - if len(collection) <= 1: return collection From 27d56ba3932d2ca2951a45232790794b2b0838d8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 26 Dec 2022 22:02:50 +0100 Subject: [PATCH 569/726] [pre-commit.ci] pre-commit autoupdate (#8047) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/PyCQA/isort: v5.11.3 → 5.11.4](https://github.com/PyCQA/isort/compare/v5.11.3...5.11.4) * Update .flake8 Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .flake8 | 2 +- .pre-commit-config.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.flake8 b/.flake8 index 77ca7a328..b68ee8533 100644 --- a/.flake8 +++ b/.flake8 @@ -1,7 +1,7 @@ [flake8] max-line-length = 88 # max-complexity should be 10 -max-complexity = 17 +max-complexity = 19 extend-ignore = # Formatting style for `black` # E203 is whitespace before ':' diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0f5fe20a8..8eb6d297e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,7 +20,7 @@ repos: - id: black - repo: https://github.com/PyCQA/isort - rev: v5.11.3 + rev: 5.11.4 hooks: - id: isort args: From 90686e39b9fd3b599a8cd77810e0fdbb74eae064 Mon Sep 17 00:00:00 2001 From: Lucia Harcekova <119792460+LuciaHarcekova@users.noreply.github.com> Date: Wed, 28 Dec 2022 17:34:35 +0000 Subject: [PATCH 570/726] Add LZ77 compression algorithm (#8059) * - add "lz77_compressor" class with compress and decompress methods using LZ77 compression algorithm * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * - use "list" instead "List", formatting * - fix spelling * - add Python type hints * - add 'Token' class to represent triplet (offset, length, indicator) * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * - add test, hange type rom List to list * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * - remove extra import * - remove extra types in comments * - better test * - edit comments * - add return types * - add tests for __str__ and __repr__ * Update lz77.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- compression/lz77.py | 227 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 compression/lz77.py diff --git a/compression/lz77.py b/compression/lz77.py new file mode 100644 index 000000000..7c1a6f6a4 --- /dev/null +++ b/compression/lz77.py @@ -0,0 +1,227 @@ +""" +LZ77 compression algorithm +- lossless data compression published in papers by Abraham Lempel and Jacob Ziv in 1977 +- also known as LZ1 or sliding-window compression +- form the basis for many variations including LZW, LZSS, LZMA and others + +It uses a “sliding window” method. Within the sliding window we have: + - search buffer + - look ahead buffer +len(sliding_window) = len(search_buffer) + len(look_ahead_buffer) + +LZ77 manages a dictionary that uses triples composed of: + - Offset into search buffer, it's the distance between the start of a phrase and + the beginning of a file. + - Length of the match, it's the number of characters that make up a phrase. + - The indicator is represented by a character that is going to be encoded next. + +As a file is parsed, the dictionary is dynamically updated to reflect the compressed +data contents and size. + +Examples: +"cabracadabrarrarrad" <-> [(0, 0, 'c'), (0, 0, 'a'), (0, 0, 'b'), (0, 0, 'r'), + (3, 1, 'c'), (2, 1, 'd'), (7, 4, 'r'), (3, 5, 'd')] +"ababcbababaa" <-> [(0, 0, 'a'), (0, 0, 'b'), (2, 2, 'c'), (4, 3, 'a'), (2, 2, 'a')] +"aacaacabcabaaac" <-> [(0, 0, 'a'), (1, 1, 'c'), (3, 4, 'b'), (3, 3, 'a'), (1, 2, 'c')] + +Sources: +en.wikipedia.org/wiki/LZ77_and_LZ78 +""" + + +from dataclasses import dataclass + +__version__ = "0.1" +__author__ = "Lucia Harcekova" + + +@dataclass +class Token: + """ + Dataclass representing triplet called token consisting of length, offset + and indicator. This triplet is used during LZ77 compression. + """ + + offset: int + length: int + indicator: str + + def __repr__(self) -> str: + """ + >>> token = Token(1, 2, "c") + >>> repr(token) + '(1, 2, c)' + >>> str(token) + '(1, 2, c)' + """ + return f"({self.offset}, {self.length}, {self.indicator})" + + +class LZ77Compressor: + """ + Class containing compress and decompress methods using LZ77 compression algorithm. + """ + + def __init__(self, window_size: int = 13, lookahead_buffer_size: int = 6) -> None: + self.window_size = window_size + self.lookahead_buffer_size = lookahead_buffer_size + self.search_buffer_size = self.window_size - self.lookahead_buffer_size + + def compress(self, text: str) -> list[Token]: + """ + Compress the given string text using LZ77 compression algorithm. + + Args: + text: string to be compressed + + Returns: + output: the compressed text as a list of Tokens + + >>> lz77_compressor = LZ77Compressor() + >>> str(lz77_compressor.compress("ababcbababaa")) + '[(0, 0, a), (0, 0, b), (2, 2, c), (4, 3, a), (2, 2, a)]' + >>> str(lz77_compressor.compress("aacaacabcabaaac")) + '[(0, 0, a), (1, 1, c), (3, 4, b), (3, 3, a), (1, 2, c)]' + """ + + output = [] + search_buffer = "" + + # while there are still characters in text to compress + while text: + + # find the next encoding phrase + # - triplet with offset, length, indicator (the next encoding character) + token = self._find_encoding_token(text, search_buffer) + + # update the search buffer: + # - add new characters from text into it + # - check if size exceed the max search buffer size, if so, drop the + # oldest elements + search_buffer += text[: token.length + 1] + if len(search_buffer) > self.search_buffer_size: + search_buffer = search_buffer[-self.search_buffer_size :] + + # update the text + text = text[token.length + 1 :] + + # append the token to output + output.append(token) + + return output + + def decompress(self, tokens: list[Token]) -> str: + """ + Convert the list of tokens into an output string. + + Args: + tokens: list containing triplets (offset, length, char) + + Returns: + output: decompressed text + + Tests: + >>> lz77_compressor = LZ77Compressor() + >>> lz77_compressor.decompress([Token(0, 0, 'c'), Token(0, 0, 'a'), + ... Token(0, 0, 'b'), Token(0, 0, 'r'), Token(3, 1, 'c'), + ... Token(2, 1, 'd'), Token(7, 4, 'r'), Token(3, 5, 'd')]) + 'cabracadabrarrarrad' + >>> lz77_compressor.decompress([Token(0, 0, 'a'), Token(0, 0, 'b'), + ... Token(2, 2, 'c'), Token(4, 3, 'a'), Token(2, 2, 'a')]) + 'ababcbababaa' + >>> lz77_compressor.decompress([Token(0, 0, 'a'), Token(1, 1, 'c'), + ... Token(3, 4, 'b'), Token(3, 3, 'a'), Token(1, 2, 'c')]) + 'aacaacabcabaaac' + """ + + output = "" + + for token in tokens: + for _ in range(token.length): + output += output[-token.offset] + output += token.indicator + + return output + + def _find_encoding_token(self, text: str, search_buffer: str) -> Token: + """Finds the encoding token for the first character in the text. + + Tests: + >>> lz77_compressor = LZ77Compressor() + >>> lz77_compressor._find_encoding_token("abrarrarrad", "abracad").offset + 7 + >>> lz77_compressor._find_encoding_token("adabrarrarrad", "cabrac").length + 1 + >>> lz77_compressor._find_encoding_token("abc", "xyz").offset + 0 + >>> lz77_compressor._find_encoding_token("", "xyz").offset + Traceback (most recent call last): + ... + ValueError: We need some text to work with. + >>> lz77_compressor._find_encoding_token("abc", "").offset + 0 + """ + + if not text: + raise ValueError("We need some text to work with.") + + # Initialise result parameters to default values + length, offset = 0, 0 + + if not search_buffer: + return Token(offset, length, text[length]) + + for i, character in enumerate(search_buffer): + found_offset = len(search_buffer) - i + if character == text[0]: + found_length = self._match_length_from_index(text, search_buffer, 0, i) + # if the found length is bigger than the current or if it's equal, + # which means it's offset is smaller: update offset and length + if found_length >= length: + offset, length = found_offset, found_length + + return Token(offset, length, text[length]) + + def _match_length_from_index( + self, text: str, window: str, text_index: int, window_index: int + ) -> int: + """Calculate the longest possible match of text and window characters from + text_index in text and window_index in window. + + Args: + text: _description_ + window: sliding window + text_index: index of character in text + window_index: index of character in sliding window + + Returns: + The maximum match between text and window, from given indexes. + + Tests: + >>> lz77_compressor = LZ77Compressor(13, 6) + >>> lz77_compressor._match_length_from_index("rarrad", "adabrar", 0, 4) + 5 + >>> lz77_compressor._match_length_from_index("adabrarrarrad", + ... "cabrac", 0, 1) + 1 + """ + if not text or text[text_index] != window[window_index]: + return 0 + return 1 + self._match_length_from_index( + text, window + text[text_index], text_index + 1, window_index + 1 + ) + + +if __name__ == "__main__": + from doctest import testmod + + testmod() + # Initialize compressor class + lz77_compressor = LZ77Compressor(window_size=13, lookahead_buffer_size=6) + + # Example + TEXT = "cabracadabrarrarrad" + compressed_text = lz77_compressor.compress(TEXT) + print(lz77_compressor.compress("ababcbababaa")) + decompressed_text = lz77_compressor.decompress(compressed_text) + assert decompressed_text == TEXT, "The LZ77 algorithm returned the invalid result." From b72d0681ec8fd6c02ee10ba04bae3fe97ffaebc6 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Thu, 29 Dec 2022 09:06:26 -0800 Subject: [PATCH 571/726] Remove extra imports in gamma.py doctests (#8060) * Refactor bottom-up function to be class method * Add type hints * Update convolve function namespace * Remove depreciated np.float * updating DIRECTORY.md * updating DIRECTORY.md * updating DIRECTORY.md * updating DIRECTORY.md * Renamed function for consistency * updating DIRECTORY.md * Remove extra imports in gamma.py doctests Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> --- maths/gamma.py | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/maths/gamma.py b/maths/gamma.py index 69cd819ef..d5debc587 100644 --- a/maths/gamma.py +++ b/maths/gamma.py @@ -11,42 +11,27 @@ def gamma(num: float) -> float: used extension of the factorial function to complex numbers. The gamma function is defined for all complex numbers except the non-positive integers - - >>> gamma(-1) Traceback (most recent call last): ... ValueError: math domain error - - - >>> gamma(0) Traceback (most recent call last): ... ValueError: math domain error - - >>> gamma(9) 40320.0 - >>> from math import gamma as math_gamma >>> all(.99999999 < gamma(i) / math_gamma(i) <= 1.000000001 ... for i in range(1, 50)) True - - - >>> from math import gamma as math_gamma >>> gamma(-1)/math_gamma(-1) <= 1.000000001 Traceback (most recent call last): ... ValueError: math domain error - - - >>> from math import gamma as math_gamma >>> gamma(3.3) - math_gamma(3.3) <= 0.00000001 True """ - if num <= 0: raise ValueError("math domain error") From c6223c71d82c7ba57f3de9eed23963ec96de01bb Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Fri, 30 Dec 2022 09:47:40 +0400 Subject: [PATCH 572/726] add word_break dynamic approach up -> down. (#8039) * add word_break dynamic approach up -> down. * updating DIRECTORY.md * Update word_break.py fix review notes. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update word_break.py fix review notes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix review notes * add trie type * Update word_break.py add typing Any to trie. * Update dynamic_programming/word_break.py Co-authored-by: Caeden Perelli-Harris * Update dynamic_programming/word_break.py Co-authored-by: Christian Clauss * Update dynamic_programming/word_break.py Co-authored-by: Christian Clauss * Update dynamic_programming/word_break.py Co-authored-by: Christian Clauss * Update dynamic_programming/word_break.py Co-authored-by: Christian Clauss * fix review notes Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Caeden Perelli-Harris Co-authored-by: Christian Clauss --- DIRECTORY.md | 1 + dynamic_programming/word_break.py | 111 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 dynamic_programming/word_break.py diff --git a/DIRECTORY.md b/DIRECTORY.md index bec857a38..3437df12c 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -328,6 +328,7 @@ * [Subset Generation](dynamic_programming/subset_generation.py) * [Sum Of Subset](dynamic_programming/sum_of_subset.py) * [Viterbi](dynamic_programming/viterbi.py) + * [Word Break](dynamic_programming/word_break.py) ## Electronics * [Builtin Voltage](electronics/builtin_voltage.py) diff --git a/dynamic_programming/word_break.py b/dynamic_programming/word_break.py new file mode 100644 index 000000000..642ea0edf --- /dev/null +++ b/dynamic_programming/word_break.py @@ -0,0 +1,111 @@ +""" +Author : Alexander Pantyukhin +Date : December 12, 2022 + +Task: +Given a string and a list of words, return true if the string can be +segmented into a space-separated sequence of one or more words. + +Note that the same word may be reused +multiple times in the segmentation. + +Implementation notes: Trie + Dynamic programming up -> down. +The Trie will be used to store the words. It will be useful for scanning +available words for the current position in the string. + +Leetcode: +https://leetcode.com/problems/word-break/description/ + +Runtime: O(n * n) +Space: O(n) +""" + +from functools import lru_cache +from typing import Any + + +def word_break(string: str, words: list[str]) -> bool: + """ + Return True if numbers have opposite signs False otherwise. + + >>> word_break("applepenapple", ["apple","pen"]) + True + >>> word_break("catsandog", ["cats","dog","sand","and","cat"]) + False + >>> word_break("cars", ["car","ca","rs"]) + True + >>> word_break('abc', []) + False + >>> word_break(123, ['a']) + Traceback (most recent call last): + ... + ValueError: the string should be not empty string + >>> word_break('', ['a']) + Traceback (most recent call last): + ... + ValueError: the string should be not empty string + >>> word_break('abc', [123]) + Traceback (most recent call last): + ... + ValueError: the words should be a list of non-empty strings + >>> word_break('abc', ['']) + Traceback (most recent call last): + ... + ValueError: the words should be a list of non-empty strings + """ + + # Validation + if not isinstance(string, str) or len(string) == 0: + raise ValueError("the string should be not empty string") + + if not isinstance(words, list) or not all( + isinstance(item, str) and len(item) > 0 for item in words + ): + raise ValueError("the words should be a list of non-empty strings") + + # Build trie + trie: dict[str, Any] = {} + word_keeper_key = "WORD_KEEPER" + + for word in words: + trie_node = trie + for c in word: + if c not in trie_node: + trie_node[c] = {} + + trie_node = trie_node[c] + + trie_node[word_keeper_key] = True + + len_string = len(string) + + # Dynamic programming method + @lru_cache(maxsize=None) + def is_breakable(index: int) -> bool: + """ + >>> string = 'a' + >>> is_breakable(1) + True + """ + if index == len_string: + return True + + trie_node = trie + for i in range(index, len_string): + trie_node = trie_node.get(string[i], None) + + if trie_node is None: + return False + + if trie_node.get(word_keeper_key, False) and is_breakable(i + 1): + return True + + return False + + return is_breakable(0) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From d29afca93b278e7885f2395c1640aa90d109cc12 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Sun, 1 Jan 2023 05:30:14 -0800 Subject: [PATCH 573/726] Fix get_top_billioners.py file name typo (#8066) --- .../{get_top_billioners.py => get_top_billionaires.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename web_programming/{get_top_billioners.py => get_top_billionaires.py} (100%) diff --git a/web_programming/get_top_billioners.py b/web_programming/get_top_billionaires.py similarity index 100% rename from web_programming/get_top_billioners.py rename to web_programming/get_top_billionaires.py From 7c1d23d4485904634a6755d5978d406be534421d Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Sun, 1 Jan 2023 17:10:59 -0800 Subject: [PATCH 574/726] Change prime_sieve_eratosthenes.py to return list (#8062) --- maths/prime_sieve_eratosthenes.py | 35 +++++++++++++++++++------------ 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/maths/prime_sieve_eratosthenes.py b/maths/prime_sieve_eratosthenes.py index 3a3c55085..32eef9165 100644 --- a/maths/prime_sieve_eratosthenes.py +++ b/maths/prime_sieve_eratosthenes.py @@ -1,10 +1,10 @@ """ Sieve of Eratosthenes -Input : n =10 +Input: n = 10 Output: 2 3 5 7 -Input : n = 20 +Input: n = 20 Output: 2 3 5 7 11 13 17 19 you can read in detail about this at @@ -12,34 +12,43 @@ https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes """ -def prime_sieve_eratosthenes(num): +def prime_sieve_eratosthenes(num: int) -> list[int]: """ - print the prime numbers up to n + Print the prime numbers up to n >>> prime_sieve_eratosthenes(10) - 2,3,5,7, + [2, 3, 5, 7] >>> prime_sieve_eratosthenes(20) - 2,3,5,7,11,13,17,19, + [2, 3, 5, 7, 11, 13, 17, 19] + >>> prime_sieve_eratosthenes(2) + [2] + >>> prime_sieve_eratosthenes(1) + [] + >>> prime_sieve_eratosthenes(-1) + Traceback (most recent call last): + ... + ValueError: Input must be a positive integer """ - primes = [True for i in range(num + 1)] - p = 2 + if num <= 0: + raise ValueError("Input must be a positive integer") + primes = [True] * (num + 1) + + p = 2 while p * p <= num: if primes[p]: for i in range(p * p, num + 1, p): primes[i] = False p += 1 - for prime in range(2, num + 1): - if primes[prime]: - print(prime, end=",") + return [prime for prime in range(2, num + 1) if primes[prime]] if __name__ == "__main__": import doctest doctest.testmod() - num = int(input()) - prime_sieve_eratosthenes(num) + user_num = int(input("Enter a positive integer: ").strip()) + print(prime_sieve_eratosthenes(user_num)) From 725731c8d289f742bfde3f159a538a47d19c27dc Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Mon, 2 Jan 2023 05:07:39 -0800 Subject: [PATCH 575/726] Refactor `local_weighted_learning.py` to use `np.array` (#8069) * updating DIRECTORY.md * Format local_weighted_learning.py doctests for clarity * Refactor local_weighted_learning.py to use np.array instead of np.mat The np.matrix class is planned to be eventually depreciated in favor of np.array, and current use of the class raises warnings in pytest * Update local_weighted_learning.py documentation Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 3 +- .../local_weighted_learning.py | 116 ++++++++++-------- 2 files changed, 68 insertions(+), 51 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 3437df12c..5ce9dca74 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -123,6 +123,7 @@ * [Huffman](compression/huffman.py) * [Lempel Ziv](compression/lempel_ziv.py) * [Lempel Ziv Decompress](compression/lempel_ziv_decompress.py) + * [Lz77](compression/lz77.py) * [Peak Signal To Noise Ratio](compression/peak_signal_to_noise_ratio.py) * [Run Length Encoding](compression/run_length_encoding.py) @@ -1162,7 +1163,7 @@ * [Get Amazon Product Data](web_programming/get_amazon_product_data.py) * [Get Imdb Top 250 Movies Csv](web_programming/get_imdb_top_250_movies_csv.py) * [Get Imdbtop](web_programming/get_imdbtop.py) - * [Get Top Billioners](web_programming/get_top_billioners.py) + * [Get Top Billionaires](web_programming/get_top_billionaires.py) * [Get Top Hn Posts](web_programming/get_top_hn_posts.py) * [Get User Tweets](web_programming/get_user_tweets.py) * [Giphy](web_programming/giphy.py) diff --git a/machine_learning/local_weighted_learning/local_weighted_learning.py b/machine_learning/local_weighted_learning/local_weighted_learning.py index df03fe0a1..6260e9ac6 100644 --- a/machine_learning/local_weighted_learning/local_weighted_learning.py +++ b/machine_learning/local_weighted_learning/local_weighted_learning.py @@ -1,76 +1,86 @@ -# Required imports to run this file import matplotlib.pyplot as plt import numpy as np -# weighted matrix -def weighted_matrix(point: np.mat, training_data_x: np.mat, bandwidth: float) -> np.mat: +def weighted_matrix( + point: np.array, training_data_x: np.array, bandwidth: float +) -> np.array: """ - Calculate the weight for every point in the - data set. It takes training_point , query_point, and tau - Here Tau is not a fixed value it can be varied depends on output. - tau --> bandwidth - xmat -->Training data - point --> the x where we want to make predictions - >>> weighted_matrix(np.array([1., 1.]),np.mat([[16.99, 10.34], [21.01,23.68], - ... [24.59,25.69]]), 0.6) - matrix([[1.43807972e-207, 0.00000000e+000, 0.00000000e+000], - [0.00000000e+000, 0.00000000e+000, 0.00000000e+000], - [0.00000000e+000, 0.00000000e+000, 0.00000000e+000]]) + Calculate the weight for every point in the data set. + point --> the x value at which we want to make predictions + >>> weighted_matrix( + ... np.array([1., 1.]), + ... np.array([[16.99, 10.34], [21.01,23.68], [24.59,25.69]]), + ... 0.6 + ... ) + array([[1.43807972e-207, 0.00000000e+000, 0.00000000e+000], + [0.00000000e+000, 0.00000000e+000, 0.00000000e+000], + [0.00000000e+000, 0.00000000e+000, 0.00000000e+000]]) """ - # m is the number of training samples - m, n = np.shape(training_data_x) - # Initializing weights as identity matrix - weights = np.mat(np.eye(m)) + m, _ = np.shape(training_data_x) # m is the number of training samples + weights = np.eye(m) # Initializing weights as identity matrix + # calculating weights for all training examples [x(i)'s] for j in range(m): diff = point - training_data_x[j] - weights[j, j] = np.exp(diff * diff.T / (-2.0 * bandwidth**2)) + weights[j, j] = np.exp(diff @ diff.T / (-2.0 * bandwidth**2)) return weights def local_weight( - point: np.mat, training_data_x: np.mat, training_data_y: np.mat, bandwidth: float -) -> np.mat: + point: np.array, + training_data_x: np.array, + training_data_y: np.array, + bandwidth: float, +) -> np.array: """ Calculate the local weights using the weight_matrix function on training data. Return the weighted matrix. - >>> local_weight(np.array([1., 1.]),np.mat([[16.99, 10.34], [21.01,23.68], - ... [24.59,25.69]]),np.mat([[1.01, 1.66, 3.5]]), 0.6) - matrix([[0.00873174], - [0.08272556]]) + >>> local_weight( + ... np.array([1., 1.]), + ... np.array([[16.99, 10.34], [21.01,23.68], [24.59,25.69]]), + ... np.array([[1.01, 1.66, 3.5]]), + ... 0.6 + ... ) + array([[0.00873174], + [0.08272556]]) """ weight = weighted_matrix(point, training_data_x, bandwidth) - w = (training_data_x.T * (weight * training_data_x)).I * ( - training_data_x.T * weight * training_data_y.T + w = np.linalg.inv(training_data_x.T @ (weight @ training_data_x)) @ ( + training_data_x.T @ weight @ training_data_y.T ) return w def local_weight_regression( - training_data_x: np.mat, training_data_y: np.mat, bandwidth: float -) -> np.mat: + training_data_x: np.array, training_data_y: np.array, bandwidth: float +) -> np.array: """ - Calculate predictions for each data point on axis. - >>> local_weight_regression(np.mat([[16.99, 10.34], [21.01,23.68], - ... [24.59,25.69]]),np.mat([[1.01, 1.66, 3.5]]), 0.6) + Calculate predictions for each data point on axis + >>> local_weight_regression( + ... np.array([[16.99, 10.34], [21.01, 23.68], [24.59, 25.69]]), + ... np.array([[1.01, 1.66, 3.5]]), + ... 0.6 + ... ) array([1.07173261, 1.65970737, 3.50160179]) """ - m, n = np.shape(training_data_x) + m, _ = np.shape(training_data_x) ypred = np.zeros(m) for i, item in enumerate(training_data_x): - ypred[i] = item * local_weight( + ypred[i] = item @ local_weight( item, training_data_x, training_data_y, bandwidth ) return ypred -def load_data(dataset_name: str, cola_name: str, colb_name: str) -> np.mat: +def load_data( + dataset_name: str, cola_name: str, colb_name: str +) -> tuple[np.array, np.array, np.array, np.array]: """ - Function used for loading data from the seaborn splitting into x and y points + Load data from seaborn and split it into x and y points """ import seaborn as sns @@ -78,23 +88,25 @@ def load_data(dataset_name: str, cola_name: str, colb_name: str) -> np.mat: col_a = np.array(data[cola_name]) # total_bill col_b = np.array(data[colb_name]) # tip - mcol_a = np.mat(col_a) - mcol_b = np.mat(col_b) + mcol_a = col_a.copy() + mcol_b = col_b.copy() - m = np.shape(mcol_b)[1] - one = np.ones((1, m), dtype=int) + one = np.ones(np.shape(mcol_b)[0], dtype=int) - # horizontal stacking - training_data_x = np.hstack((one.T, mcol_a.T)) + # pairing elements of one and mcol_a + training_data_x = np.column_stack((one, mcol_a)) return training_data_x, mcol_b, col_a, col_b -def get_preds(training_data_x: np.mat, mcol_b: np.mat, tau: float) -> np.ndarray: +def get_preds(training_data_x: np.array, mcol_b: np.array, tau: float) -> np.array: """ Get predictions with minimum error for each training data - >>> get_preds(np.mat([[16.99, 10.34], [21.01,23.68], - ... [24.59,25.69]]),np.mat([[1.01, 1.66, 3.5]]), 0.6) + >>> get_preds( + ... np.array([[16.99, 10.34], [21.01, 23.68], [24.59, 25.69]]), + ... np.array([[1.01, 1.66, 3.5]]), + ... 0.6 + ... ) array([1.07173261, 1.65970737, 3.50160179]) """ ypred = local_weight_regression(training_data_x, mcol_b, tau) @@ -102,15 +114,15 @@ def get_preds(training_data_x: np.mat, mcol_b: np.mat, tau: float) -> np.ndarray def plot_preds( - training_data_x: np.mat, - predictions: np.ndarray, - col_x: np.ndarray, - col_y: np.ndarray, + training_data_x: np.array, + predictions: np.array, + col_x: np.array, + col_y: np.array, cola_name: str, colb_name: str, ) -> plt.plot: """ - This function used to plot predictions and display the graph + Plot predictions and display the graph """ xsort = training_data_x.copy() xsort.sort(axis=0) @@ -128,6 +140,10 @@ def plot_preds( if __name__ == "__main__": + import doctest + + doctest.testmod() + training_data_x, mcol_b, col_a, col_b = load_data("tips", "total_bill", "tip") predictions = get_preds(training_data_x, mcol_b, 0.5) plot_preds(training_data_x, predictions, col_a, col_b, "total_bill", "tip") From 9f041e9cc82dab21401359d4cfa1b966fc30ddc4 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Mon, 2 Jan 2023 05:15:14 -0800 Subject: [PATCH 576/726] Refactor `sierpinski_triangle.py` (#8068) * updating DIRECTORY.md * Update sierpinski_triangle.py header doc * Remove unused PROGNAME var in sierpinski_triangle.py The PROGNAME var was used to print an image description in the reference code that this implementation was taken from, but it's entirely unused here * Refactor triangle() function to not use list of vertices Since the number of vertices is always fixed at 3, there's no need to pass in the vertices as a list, and it's clearer to give the vertices distinct names rather than index them from the list * Refactor sierpinski_triangle.py to use tuples Tuples make more sense than lists for storing coordinate pairs * Flip if-statement condition in sierpinski_triangle.py to avoid nesting * Add type hints to sierpinski_triangle.py * Add doctests to sierpinski_triangle.py * Fix return types in doctests * Update fractals/sierpinski_triangle.py Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss --- fractals/sierpinski_triangle.py | 110 +++++++++++++++++--------------- 1 file changed, 59 insertions(+), 51 deletions(-) diff --git a/fractals/sierpinski_triangle.py b/fractals/sierpinski_triangle.py index 084f6661f..c28ec00b2 100644 --- a/fractals/sierpinski_triangle.py +++ b/fractals/sierpinski_triangle.py @@ -1,76 +1,84 @@ -#!/usr/bin/python +""" +Author Anurag Kumar | anuragkumarak95@gmail.com | git/anuragkumarak95 -"""Author Anurag Kumar | anuragkumarak95@gmail.com | git/anuragkumarak95 +Simple example of fractal generation using recursion. -Simple example of Fractal generation using recursive function. +What is the Sierpiński Triangle? + The Sierpiński triangle (sometimes spelled Sierpinski), also called the +Sierpiński gasket or Sierpiński sieve, is a fractal attractive fixed set with +the overall shape of an equilateral triangle, subdivided recursively into +smaller equilateral triangles. Originally constructed as a curve, this is one of +the basic examples of self-similar sets—that is, it is a mathematically +generated pattern that is reproducible at any magnification or reduction. It is +named after the Polish mathematician Wacław Sierpiński, but appeared as a +decorative pattern many centuries before the work of Sierpiński. -What is Sierpinski Triangle? ->>The Sierpinski triangle (also with the original orthography Sierpinski), also called -the Sierpinski gasket or the Sierpinski Sieve, is a fractal and attractive fixed set -with the overall shape of an equilateral triangle, subdivided recursively into smaller -equilateral triangles. Originally constructed as a curve, this is one of the basic -examples of self-similar sets, i.e., it is a mathematically generated pattern that can -be reproducible at any magnification or reduction. It is named after the Polish -mathematician Wacław Sierpinski, but appeared as a decorative pattern many centuries -prior to the work of Sierpinski. -Requirements(pip): - - turtle - -Python: - - 2.6 - -Usage: - - $python sierpinski_triangle.py - -Credits: This code was written by editing the code from -https://www.riannetrujillo.com/blog/python-fractal/ +Usage: python sierpinski_triangle.py +Credits: + The above description is taken from + https://en.wikipedia.org/wiki/Sierpi%C5%84ski_triangle + This code was written by editing the code from + https://www.riannetrujillo.com/blog/python-fractal/ """ import sys import turtle -PROGNAME = "Sierpinski Triangle" -points = [[-175, -125], [0, 175], [175, -125]] # size of triangle +def get_mid(p1: tuple[float, float], p2: tuple[float, float]) -> tuple[float, float]: + """ + Find the midpoint of two points + + >>> get_mid((0, 0), (2, 2)) + (1.0, 1.0) + >>> get_mid((-3, -3), (3, 3)) + (0.0, 0.0) + >>> get_mid((1, 0), (3, 2)) + (2.0, 1.0) + >>> get_mid((0, 0), (1, 1)) + (0.5, 0.5) + >>> get_mid((0, 0), (0, 0)) + (0.0, 0.0) + """ + return (p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2 -def get_mid(p1, p2): - return ((p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2) # find midpoint - - -def triangle(points, depth): - +def triangle( + vertex1: tuple[float, float], + vertex2: tuple[float, float], + vertex3: tuple[float, float], + depth: int, +) -> None: + """ + Recursively draw the Sierpinski triangle given the vertices of the triangle + and the recursion depth + """ my_pen.up() - my_pen.goto(points[0][0], points[0][1]) + my_pen.goto(vertex1[0], vertex1[1]) my_pen.down() - my_pen.goto(points[1][0], points[1][1]) - my_pen.goto(points[2][0], points[2][1]) - my_pen.goto(points[0][0], points[0][1]) + my_pen.goto(vertex2[0], vertex2[1]) + my_pen.goto(vertex3[0], vertex3[1]) + my_pen.goto(vertex1[0], vertex1[1]) - if depth > 0: - triangle( - [points[0], get_mid(points[0], points[1]), get_mid(points[0], points[2])], - depth - 1, - ) - triangle( - [points[1], get_mid(points[0], points[1]), get_mid(points[1], points[2])], - depth - 1, - ) - triangle( - [points[2], get_mid(points[2], points[1]), get_mid(points[0], points[2])], - depth - 1, - ) + if depth == 0: + return + + triangle(vertex1, get_mid(vertex1, vertex2), get_mid(vertex1, vertex3), depth - 1) + triangle(vertex2, get_mid(vertex1, vertex2), get_mid(vertex2, vertex3), depth - 1) + triangle(vertex3, get_mid(vertex3, vertex2), get_mid(vertex1, vertex3), depth - 1) if __name__ == "__main__": if len(sys.argv) != 2: raise ValueError( - "right format for using this script: " - "$python fractals.py " + "Correct format for using this script: " + "python fractals.py " ) my_pen = turtle.Turtle() my_pen.ht() my_pen.speed(5) my_pen.pencolor("red") - triangle(points, int(sys.argv[1])) + + vertices = [(-175, -125), (0, 175), (175, -125)] # vertices of triangle + triangle(vertices[0], vertices[1], vertices[2], int(sys.argv[1])) From 32a1ff9359b4de80b94ef26c55a5b24204d35382 Mon Sep 17 00:00:00 2001 From: Abhishek Mulik Date: Wed, 4 Jan 2023 06:17:15 +0530 Subject: [PATCH 577/726] Update is_palindrome.py (#8022) --- strings/is_palindrome.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/strings/is_palindrome.py b/strings/is_palindrome.py index 5758af0ce..9bf2abd98 100644 --- a/strings/is_palindrome.py +++ b/strings/is_palindrome.py @@ -16,7 +16,24 @@ def is_palindrome(s: str) -> bool: # Since punctuation, capitalization, and spaces are often ignored while checking # palindromes, we first remove them from our string. s = "".join(character for character in s.lower() if character.isalnum()) - return s == s[::-1] + # return s == s[::-1] the slicing method + # uses extra spaces we can + # better with iteration method. + + end = len(s) // 2 + n = len(s) + + # We need to traverse till half of the length of string + # as we can get access of the i'th last element from + # i'th index. + # eg: [0,1,2,3,4,5] => 4th index can be accessed + # with the help of 1st index (i==n-i-1) + # where n is length of string + + for i in range(end): + if s[i] != s[n - i - 1]: + return False + return True if __name__ == "__main__": From 4939e8463fc34c936a309d513cfe8153343cb9d5 Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Sat, 7 Jan 2023 16:56:39 +0000 Subject: [PATCH 578/726] Create cached fibonacci algorithm (#8084) * feat: Add `fib_recursive_cached` func * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * doc: Show difference in time when caching algorithm Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/fibonacci.py | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/maths/fibonacci.py b/maths/fibonacci.py index e0da66ee5..d58c9fc68 100644 --- a/maths/fibonacci.py +++ b/maths/fibonacci.py @@ -16,6 +16,7 @@ fib_memoization runtime: 0.0107 ms fib_binet runtime: 0.0174 ms """ +from functools import lru_cache from math import sqrt from time import time @@ -92,6 +93,39 @@ def fib_recursive(n: int) -> list[int]: return [fib_recursive_term(i) for i in range(n + 1)] +def fib_recursive_cached(n: int) -> list[int]: + """ + Calculates the first n (0-indexed) Fibonacci numbers using recursion + >>> fib_iterative(0) + [0] + >>> fib_iterative(1) + [0, 1] + >>> fib_iterative(5) + [0, 1, 1, 2, 3, 5] + >>> fib_iterative(10) + [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55] + >>> fib_iterative(-1) + Traceback (most recent call last): + ... + Exception: n is negative + """ + + @lru_cache(maxsize=None) + def fib_recursive_term(i: int) -> int: + """ + Calculates the i-th (0-indexed) Fibonacci number using recursion + """ + if i < 0: + raise Exception("n is negative") + if i < 2: + return i + return fib_recursive_term(i - 1) + fib_recursive_term(i - 2) + + if n < 0: + raise Exception("n is negative") + return [fib_recursive_term(i) for i in range(n + 1)] + + def fib_memoization(n: int) -> list[int]: """ Calculates the first n (0-indexed) Fibonacci numbers using memoization @@ -163,8 +197,9 @@ def fib_binet(n: int) -> list[int]: if __name__ == "__main__": - num = 20 + num = 30 time_func(fib_iterative, num) - time_func(fib_recursive, num) + time_func(fib_recursive, num) # Around 3s runtime + time_func(fib_recursive_cached, num) # Around 0ms runtime time_func(fib_memoization, num) time_func(fib_binet, num) From 1a27258bd6c3a35a403629b4ea7fc0228bcc892d Mon Sep 17 00:00:00 2001 From: MohammadReza Balakhaniyan <51448587+balakhaniyan@users.noreply.github.com> Date: Wed, 11 Jan 2023 02:17:02 +0330 Subject: [PATCH 579/726] gcd_of_n_numbers (#8057) * add maths/Gcd of N Numbers * add maths/Gcd of N Numbers * add maths/Gcd of N Numbers * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add maths/Gcd of N Numbers * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add maths/Gcd of N Numbers * add maths/Gcd of N Numbers * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add maths/Gcd of N Numbers * add maths/Gcd of N Numbers * more pythonic * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * more pythonic * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * merged * merged * more readable * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/gcd_of_n_numbers.py | 109 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 maths/gcd_of_n_numbers.py diff --git a/maths/gcd_of_n_numbers.py b/maths/gcd_of_n_numbers.py new file mode 100644 index 000000000..63236c236 --- /dev/null +++ b/maths/gcd_of_n_numbers.py @@ -0,0 +1,109 @@ +""" +Gcd of N Numbers +Reference: https://en.wikipedia.org/wiki/Greatest_common_divisor +""" + +from collections import Counter + + +def get_factors( + number: int, factors: Counter | None = None, factor: int = 2 +) -> Counter: + """ + this is a recursive function for get all factors of number + >>> get_factors(45) + Counter({3: 2, 5: 1}) + >>> get_factors(2520) + Counter({2: 3, 3: 2, 5: 1, 7: 1}) + >>> get_factors(23) + Counter({23: 1}) + >>> get_factors(0) + Traceback (most recent call last): + ... + TypeError: number must be integer and greater than zero + >>> get_factors(-1) + Traceback (most recent call last): + ... + TypeError: number must be integer and greater than zero + >>> get_factors(1.5) + Traceback (most recent call last): + ... + TypeError: number must be integer and greater than zero + + factor can be all numbers from 2 to number that we check if number % factor == 0 + if it is equal to zero, we check again with number // factor + else we increase factor by one + """ + + match number: + case int(number) if number == 1: + return Counter({1: 1}) + case int(num) if number > 0: + number = num + case _: + raise TypeError("number must be integer and greater than zero") + + factors = factors or Counter() + + if number == factor: # break condition + # all numbers are factors of itself + factors[factor] += 1 + return factors + + if number % factor > 0: + # if it is greater than zero + # so it is not a factor of number and we check next number + return get_factors(number, factors, factor + 1) + + factors[factor] += 1 + # else we update factors (that is Counter(dict-like) type) and check again + return get_factors(number // factor, factors, factor) + + +def get_greatest_common_divisor(*numbers: int) -> int: + """ + get gcd of n numbers: + >>> get_greatest_common_divisor(18, 45) + 9 + >>> get_greatest_common_divisor(23, 37) + 1 + >>> get_greatest_common_divisor(2520, 8350) + 10 + >>> get_greatest_common_divisor(-10, 20) + Traceback (most recent call last): + ... + Exception: numbers must be integer and greater than zero + >>> get_greatest_common_divisor(1.5, 2) + Traceback (most recent call last): + ... + Exception: numbers must be integer and greater than zero + >>> get_greatest_common_divisor(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + 1 + >>> get_greatest_common_divisor("1", 2, 3, 4, 5, 6, 7, 8, 9, 10) + Traceback (most recent call last): + ... + Exception: numbers must be integer and greater than zero + """ + + # we just need factors, not numbers itself + try: + same_factors, *factors = map(get_factors, numbers) + except TypeError as e: + raise Exception("numbers must be integer and greater than zero") from e + + for factor in factors: + same_factors &= factor + # get common factor between all + # `&` return common elements with smaller value (for Counter type) + + # now, same_factors is something like {2: 2, 3: 4} that means 2 * 2 * 3 * 3 * 3 * 3 + mult = 1 + # power each factor and multiply + # for {2: 2, 3: 4}, it is [4, 81] and then 324 + for m in [factor**power for factor, power in same_factors.items()]: + mult *= m + return mult + + +if __name__ == "__main__": + print(get_greatest_common_divisor(18, 45)) # 9 From c00af459fe0a18ae6adca2aec5ca8c7ff64864c8 Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Thu, 26 Jan 2023 07:12:11 +0000 Subject: [PATCH 580/726] feat: Concatenate both factorial implementations (#8099) * feat: Concatenate both factorial implementations * fix: Rename factorial recursive method --- .../{factorial_iterative.py => factorial.py} | 24 ++++++++++++++++ maths/factorial_recursive.py | 28 ------------------- 2 files changed, 24 insertions(+), 28 deletions(-) rename maths/{factorial_iterative.py => factorial.py} (58%) delete mode 100644 maths/factorial_recursive.py diff --git a/maths/factorial_iterative.py b/maths/factorial.py similarity index 58% rename from maths/factorial_iterative.py rename to maths/factorial.py index c6cf7de57..bbf0efc01 100644 --- a/maths/factorial_iterative.py +++ b/maths/factorial.py @@ -34,6 +34,30 @@ def factorial(number: int) -> int: return value +def factorial_recursive(n: int) -> int: + """ + Calculate the factorial of a positive integer + https://en.wikipedia.org/wiki/Factorial + + >>> import math + >>> all(factorial(i) == math.factorial(i) for i in range(20)) + True + >>> factorial(0.1) + Traceback (most recent call last): + ... + ValueError: factorial() only accepts integral values + >>> factorial(-1) + Traceback (most recent call last): + ... + ValueError: factorial() not defined for negative values + """ + if not isinstance(n, int): + raise ValueError("factorial() only accepts integral values") + if n < 0: + raise ValueError("factorial() not defined for negative values") + return 1 if n == 0 or n == 1 else n * factorial(n - 1) + + if __name__ == "__main__": import doctest diff --git a/maths/factorial_recursive.py b/maths/factorial_recursive.py deleted file mode 100644 index 137112738..000000000 --- a/maths/factorial_recursive.py +++ /dev/null @@ -1,28 +0,0 @@ -def factorial(n: int) -> int: - """ - Calculate the factorial of a positive integer - https://en.wikipedia.org/wiki/Factorial - - >>> import math - >>> all(factorial(i) == math.factorial(i) for i in range(20)) - True - >>> factorial(0.1) - Traceback (most recent call last): - ... - ValueError: factorial() only accepts integral values - >>> factorial(-1) - Traceback (most recent call last): - ... - ValueError: factorial() not defined for negative values - """ - if not isinstance(n, int): - raise ValueError("factorial() only accepts integral values") - if n < 0: - raise ValueError("factorial() not defined for negative values") - return 1 if n == 0 or n == 1 else n * factorial(n - 1) - - -if __name__ == "__main__": - import doctest - - doctest.testmod() From 57c12fab2822df33b8da5a1fd9b95f2f7d64f130 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Thu, 26 Jan 2023 02:13:03 -0500 Subject: [PATCH 581/726] Fix `mypy` errors in `lorentz_transformation_four_vector.py` (#8075) * updating DIRECTORY.md * Fix mypy errors in lorentz_transformation_four_vector.py * Remove unused symbol vars * Add function documentation and rewrite algorithm explanation Previous explanation was misleading, as the code only calculates Lorentz transformations for movement in the x direction (0 velocity in the y and z directions) and not movement in any direction * updating DIRECTORY.md * Update error message for speed Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 1 + physics/lorentz_transformation_four_vector.py | 138 ++++++++---------- 2 files changed, 62 insertions(+), 77 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 5ce9dca74..31e86ea59 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -557,6 +557,7 @@ * [Gamma Recursive](maths/gamma_recursive.py) * [Gaussian](maths/gaussian.py) * [Gaussian Error Linear Unit](maths/gaussian_error_linear_unit.py) + * [Gcd Of N Numbers](maths/gcd_of_n_numbers.py) * [Greatest Common Divisor](maths/greatest_common_divisor.py) * [Greedy Coin Change](maths/greedy_coin_change.py) * [Hamming Numbers](maths/hamming_numbers.py) diff --git a/physics/lorentz_transformation_four_vector.py b/physics/lorentz_transformation_four_vector.py index f58b40e59..64be97245 100644 --- a/physics/lorentz_transformation_four_vector.py +++ b/physics/lorentz_transformation_four_vector.py @@ -1,39 +1,33 @@ """ -Lorentz transformation describes the transition from a reference frame P -to another reference frame P', each of which is moving in a direction with -respect to the other. The Lorentz transformation implemented in this code -is the relativistic version using a four vector described by Minkowsky Space: -x0 = ct, x1 = x, x2 = y, and x3 = z +Lorentz transformations describe the transition between two inertial reference +frames F and F', each of which is moving in some direction with respect to the +other. This code only calculates Lorentz transformations for movement in the x +direction with no spacial rotation (i.e., a Lorentz boost in the x direction). +The Lorentz transformations are calculated here as linear transformations of +four-vectors [ct, x, y, z] described by Minkowski space. Note that t (time) is +multiplied by c (the speed of light) in the first entry of each four-vector. -NOTE: Please note that x0 is c (speed of light) times t (time). +Thus, if X = [ct; x; y; z] and X' = [ct'; x'; y'; z'] are the four-vectors for +two inertial reference frames and X' moves in the x direction with velocity v +with respect to X, then the Lorentz transformation from X to X' is X' = BX, +where -So, the Lorentz transformation using a four vector is defined as: + | γ -γβ 0 0| +B = |-γβ γ 0 0| + | 0 0 1 0| + | 0 0 0 1| -|ct'| | γ -γβ 0 0| |ct| -|x' | = |-γβ γ 0 0| *|x | -|y' | | 0 0 1 0| |y | -|z' | | 0 0 0 1| |z | - -Where: - 1 -γ = --------------- - ----------- - / v^2 | - /(1 - --- - -/ c^2 - - v -β = ----- - c +is the matrix describing the Lorentz boost between X and X', +γ = 1 / √(1 - v²/c²) is the Lorentz factor, and β = v/c is the velocity as +a fraction of c. Reference: https://en.wikipedia.org/wiki/Lorentz_transformation """ -from __future__ import annotations from math import sqrt -import numpy as np # type: ignore -from sympy import symbols # type: ignore +import numpy as np +from sympy import symbols # Coefficient # Speed of light (m/s) @@ -41,79 +35,77 @@ c = 299792458 # Symbols ct, x, y, z = symbols("ct x y z") -ct_p, x_p, y_p, z_p = symbols("ct' x' y' z'") # Vehicle's speed divided by speed of light (no units) def beta(velocity: float) -> float: """ + Calculates β = v/c, the given velocity as a fraction of c >>> beta(c) 1.0 - >>> beta(199792458) 0.666435904801848 - >>> beta(1e5) 0.00033356409519815205 - >>> beta(0.2) Traceback (most recent call last): ... - ValueError: Speed must be greater than 1! + ValueError: Speed must be greater than or equal to 1! """ if velocity > c: - raise ValueError("Speed must not exceed Light Speed 299,792,458 [m/s]!") - - # Usually the speed u should be much higher than 1 (c order of magnitude) + raise ValueError("Speed must not exceed light speed 299,792,458 [m/s]!") elif velocity < 1: - raise ValueError("Speed must be greater than 1!") + # Usually the speed should be much higher than 1 (c order of magnitude) + raise ValueError("Speed must be greater than or equal to 1!") + return velocity / c def gamma(velocity: float) -> float: """ + Calculate the Lorentz factor γ = 1 / √(1 - v²/c²) for a given velocity >>> gamma(4) 1.0000000000000002 - >>> gamma(1e5) 1.0000000556325075 - >>> gamma(3e7) 1.005044845777813 - >>> gamma(2.8e8) 2.7985595722318277 - >>> gamma(299792451) 4627.49902669495 - >>> gamma(0.3) Traceback (most recent call last): ... - ValueError: Speed must be greater than 1! - - >>> gamma(2*c) + ValueError: Speed must be greater than or equal to 1! + >>> gamma(2 * c) Traceback (most recent call last): ... - ValueError: Speed must not exceed Light Speed 299,792,458 [m/s]! + ValueError: Speed must not exceed light speed 299,792,458 [m/s]! """ - return 1 / (sqrt(1 - beta(velocity) ** 2)) + return 1 / sqrt(1 - beta(velocity) ** 2) -def transformation_matrix(velocity: float) -> np.array: +def transformation_matrix(velocity: float) -> np.ndarray: """ + Calculate the Lorentz transformation matrix for movement in the x direction: + + | γ -γβ 0 0| + |-γβ γ 0 0| + | 0 0 1 0| + | 0 0 0 1| + + where γ is the Lorentz factor and β is the velocity as a fraction of c >>> transformation_matrix(29979245) array([[ 1.00503781, -0.10050378, 0. , 0. ], [-0.10050378, 1.00503781, 0. , 0. ], [ 0. , 0. , 1. , 0. ], [ 0. , 0. , 0. , 1. ]]) - >>> transformation_matrix(19979245.2) array([[ 1.00222811, -0.06679208, 0. , 0. ], [-0.06679208, 1.00222811, 0. , 0. ], [ 0. , 0. , 1. , 0. ], [ 0. , 0. , 0. , 1. ]]) - >>> transformation_matrix(1) array([[ 1.00000000e+00, -3.33564095e-09, 0.00000000e+00, 0.00000000e+00], @@ -123,16 +115,14 @@ def transformation_matrix(velocity: float) -> np.array: 0.00000000e+00], [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]]) - >>> transformation_matrix(0) Traceback (most recent call last): ... - ValueError: Speed must be greater than 1! - + ValueError: Speed must be greater than or equal to 1! >>> transformation_matrix(c * 1.5) Traceback (most recent call last): ... - ValueError: Speed must not exceed Light Speed 299,792,458 [m/s]! + ValueError: Speed must not exceed light speed 299,792,458 [m/s]! """ return np.array( [ @@ -144,44 +134,39 @@ def transformation_matrix(velocity: float) -> np.array: ) -def transform( - velocity: float, event: np.array = np.zeros(4), symbolic: bool = True # noqa: B008 -) -> np.array: +def transform(velocity: float, event: np.ndarray | None = None) -> np.ndarray: """ - >>> transform(29979245,np.array([1,2,3,4]), False) - array([ 3.01302757e+08, -3.01302729e+07, 3.00000000e+00, 4.00000000e+00]) + Calculate a Lorentz transformation for movement in the x direction given a + velocity and a four-vector for an inertial reference frame + If no four-vector is given, then calculate the transformation symbolically + with variables + >>> transform(29979245, np.array([1, 2, 3, 4])) + array([ 3.01302757e+08, -3.01302729e+07, 3.00000000e+00, 4.00000000e+00]) >>> transform(29979245) array([1.00503781498831*ct - 0.100503778816875*x, -0.100503778816875*ct + 1.00503781498831*x, 1.0*y, 1.0*z], dtype=object) - >>> transform(19879210.2) array([1.0022057787097*ct - 0.066456172618675*x, -0.066456172618675*ct + 1.0022057787097*x, 1.0*y, 1.0*z], dtype=object) - - >>> transform(299792459, np.array([1,1,1,1])) + >>> transform(299792459, np.array([1, 1, 1, 1])) Traceback (most recent call last): ... - ValueError: Speed must not exceed Light Speed 299,792,458 [m/s]! - - >>> transform(-1, np.array([1,1,1,1])) + ValueError: Speed must not exceed light speed 299,792,458 [m/s]! + >>> transform(-1, np.array([1, 1, 1, 1])) Traceback (most recent call last): ... - ValueError: Speed must be greater than 1! + ValueError: Speed must be greater than or equal to 1! """ - # Ensure event is not a vector of zeros - if not symbolic: - - # x0 is ct (speed of ligt * time) - event[0] = event[0] * c + # Ensure event is not empty + if event is None: + event = np.array([ct, x, y, z]) # Symbolic four vector else: + event[0] *= c # x0 is ct (speed of light * time) - # Symbolic four vector - event = np.array([ct, x, y, z]) - - return transformation_matrix(velocity).dot(event) + return transformation_matrix(velocity) @ event if __name__ == "__main__": @@ -197,9 +182,8 @@ if __name__ == "__main__": print(f"y' = {four_vector[2]}") print(f"z' = {four_vector[3]}") - # Substitute symbols with numerical values: - values = np.array([1, 1, 1, 1]) - sub_dict = {ct: c * values[0], x: values[1], y: values[2], z: values[3]} - numerical_vector = [four_vector[i].subs(sub_dict) for i in range(0, 4)] + # Substitute symbols with numerical values + sub_dict = {ct: c, x: 1, y: 1, z: 1} + numerical_vector = [four_vector[i].subs(sub_dict) for i in range(4)] print(f"\n{numerical_vector}") From ed0a581f9347b8fddc1928e52232eea250108573 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 30 Jan 2023 23:42:15 +0100 Subject: [PATCH 582/726] [pre-commit.ci] pre-commit autoupdate (#8107) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/PyCQA/isort: 5.11.4 → 5.12.0](https://github.com/PyCQA/isort/compare/5.11.4...5.12.0) * updating DIRECTORY.md --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- DIRECTORY.md | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8eb6d297e..b97ef2889 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,7 +20,7 @@ repos: - id: black - repo: https://github.com/PyCQA/isort - rev: 5.11.4 + rev: 5.12.0 hooks: - id: isort args: diff --git a/DIRECTORY.md b/DIRECTORY.md index 31e86ea59..a8786cc25 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -543,8 +543,7 @@ * [Euler Modified](maths/euler_modified.py) * [Eulers Totient](maths/eulers_totient.py) * [Extended Euclidean Algorithm](maths/extended_euclidean_algorithm.py) - * [Factorial Iterative](maths/factorial_iterative.py) - * [Factorial Recursive](maths/factorial_recursive.py) + * [Factorial](maths/factorial.py) * [Factors](maths/factors.py) * [Fermat Little Theorem](maths/fermat_little_theorem.py) * [Fibonacci](maths/fibonacci.py) From c909da9b085957fcd16b6b30b6bdc0cf2855a150 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 1 Feb 2023 14:14:54 +0100 Subject: [PATCH 583/726] pre-commit: Upgrade psf/black for stable style 2023 (#8110) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * pre-commit: Upgrade psf/black for stable style 2023 Updating https://github.com/psf/black ... updating 22.12.0 -> 23.1.0 for their `2023 stable style`. * https://github.com/psf/black/blob/main/CHANGES.md#2310 > This is the first [psf/black] release of 2023, and following our stability policy, it comes with a number of improvements to our stable style… Also, add https://github.com/tox-dev/pyproject-fmt and https://github.com/abravalheri/validate-pyproject to pre-commit. I only modified `.pre-commit-config.yaml` and all other files were modified by pre-commit.ci and psf/black. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 12 +++++++++- arithmetic_analysis/newton_raphson_new.py | 1 - backtracking/n_queens_math.py | 1 - blockchain/chinese_remainder_theorem.py | 1 + ciphers/enigma_machine2.py | 1 - ciphers/playfair_cipher.py | 1 - ciphers/polybius.py | 1 - ciphers/xor_cipher.py | 2 -- compression/lz77.py | 1 - computer_vision/cnn_classification.py | 1 - computer_vision/harris_corner.py | 3 --- conversions/decimal_to_binary.py | 1 - conversions/molecular_chemistry.py | 1 - conversions/roman_numerals.py | 2 +- conversions/temperature_conversions.py | 1 - conversions/weight_conversion.py | 1 - .../binary_tree/binary_tree_traversals.py | 1 - .../inorder_tree_traversal_2022.py | 1 - data_structures/hashing/double_hash.py | 1 - data_structures/hashing/hash_table.py | 2 -- data_structures/heap/binomial_heap.py | 2 -- data_structures/heap/skew_heap.py | 1 - .../linked_list/doubly_linked_list_two.py | 2 -- data_structures/stacks/prefix_evaluation.py | 1 - .../stacks/stack_with_doubly_linked_list.py | 1 - data_structures/stacks/stock_span_problem.py | 2 -- .../filters/bilateral_filter.py | 1 - .../filters/local_binary_pattern.py | 1 - dynamic_programming/bitmask.py | 5 ---- .../iterating_through_submasks.py | 1 - electronics/coulombs_law.py | 1 - fractals/julia_sets.py | 1 - fractals/mandelbrot.py | 1 - geodesy/lamberts_ellipsoidal_distance.py | 1 - graphs/a_star.py | 1 - graphs/check_bipartite_graph_bfs.py | 1 - graphs/graph_matrix.py | 1 - graphs/karger.py | 1 - graphs/minimum_spanning_tree_boruvka.py | 1 - graphs/multi_heuristic_astar.py | 4 ++-- knapsack/recursive_approach_knapsack.py | 1 - linear_algebra/src/conjugate_gradient.py | 1 - machine_learning/k_means_clust.py | 3 --- machine_learning/self_organizing_map.py | 1 - .../sequential_minimum_optimization.py | 2 -- machine_learning/xgboost_classifier.py | 1 - maths/armstrong_numbers.py | 2 +- maths/binary_exponentiation.py | 1 - maths/combinations.py | 1 - maths/decimal_isolate.py | 1 - maths/fermat_little_theorem.py | 1 - maths/greedy_coin_change.py | 2 -- maths/integration_by_simpson_approx.py | 1 - maths/jaccard_similarity.py | 2 -- maths/least_common_multiple.py | 1 - maths/line_length.py | 2 -- maths/monte_carlo.py | 1 + maths/newton_raphson.py | 1 - maths/numerical_integration.py | 2 -- maths/primelib.py | 23 ------------------- maths/segmented_sieve.py | 1 - maths/two_pointer.py | 1 - maths/zellers_congruence.py | 1 - matrix/largest_square_area_in_matrix.py | 3 --- other/activity_selection.py | 1 - other/nested_brackets.py | 2 -- other/scoring_algorithm.py | 1 - other/sdes.py | 1 - physics/casimir_effect.py | 1 - physics/hubble_parameter.py | 1 - physics/newtons_law_of_gravitation.py | 1 - project_euler/problem_004/sol1.py | 2 -- project_euler/problem_074/sol2.py | 1 - project_euler/problem_089/sol1.py | 1 - project_euler/problem_092/sol1.py | 2 -- quantum/q_fourier_transform.py | 1 - quantum/quantum_teleportation.py | 1 - scheduling/highest_response_ratio_next.py | 2 -- searches/binary_search.py | 1 - searches/interpolation_search.py | 1 - searches/tabu_search.py | 1 - searches/ternary_search.py | 1 - sorts/comb_sort.py | 1 - sorts/odd_even_sort.py | 1 - sorts/odd_even_transposition_parallel.py | 1 - sorts/random_normal_distribution_quicksort.py | 2 -- sorts/shrink_shell_sort.py | 1 - sorts/stooge_sort.py | 1 - sorts/tim_sort.py | 1 - strings/dna.py | 1 - strings/hamming_distance.py | 1 - strings/levenshtein_distance.py | 2 -- strings/prefix_function.py | 1 - strings/text_justification.py | 1 - web_programming/fetch_anime_and_play.py | 9 ++------ web_programming/fetch_well_rx_price.py | 5 ---- web_programming/get_user_tweets.py | 1 - 97 files changed, 19 insertions(+), 154 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b97ef2889..f8d1a65db 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: - id: auto-walrus - repo: https://github.com/psf/black - rev: 22.12.0 + rev: 23.1.0 hooks: - id: black @@ -26,6 +26,16 @@ repos: args: - --profile=black + - repo: https://github.com/tox-dev/pyproject-fmt + rev: "0.6.0" + hooks: + - id: pyproject-fmt + + - repo: https://github.com/abravalheri/validate-pyproject + rev: v0.12.1 + hooks: + - id: validate-pyproject + - repo: https://github.com/asottile/pyupgrade rev: v3.3.1 hooks: diff --git a/arithmetic_analysis/newton_raphson_new.py b/arithmetic_analysis/newton_raphson_new.py index dd1d7e092..472cb5b5a 100644 --- a/arithmetic_analysis/newton_raphson_new.py +++ b/arithmetic_analysis/newton_raphson_new.py @@ -59,7 +59,6 @@ def newton_raphson( # Let's Execute if __name__ == "__main__": - # Find root of trigonometric function # Find value of pi print(f"The root of sin(x) = 0 is {newton_raphson('sin(x)', 2)}") diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index 2de784ded..23bd15906 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -107,7 +107,6 @@ def depth_first_search( # We iterate each column in the row to find all possible results in each row for col in range(n): - # We apply that we learned previously. First we check that in the current board # (possible_board) there are not other same value because if there is it means # that there are a collision in vertical. Then we apply the two formulas we diff --git a/blockchain/chinese_remainder_theorem.py b/blockchain/chinese_remainder_theorem.py index 54d861dd9..d3e75e779 100644 --- a/blockchain/chinese_remainder_theorem.py +++ b/blockchain/chinese_remainder_theorem.py @@ -53,6 +53,7 @@ def chinese_remainder_theorem(n1: int, r1: int, n2: int, r2: int) -> int: # ----------SAME SOLUTION USING InvertModulo instead ExtendedEuclid---------------- + # This function find the inverses of a i.e., a^(-1) def invert_modulo(a: int, n: int) -> int: """ diff --git a/ciphers/enigma_machine2.py b/ciphers/enigma_machine2.py index a877256eb..07d21893f 100644 --- a/ciphers/enigma_machine2.py +++ b/ciphers/enigma_machine2.py @@ -230,7 +230,6 @@ def enigma( # encryption/decryption process -------------------------- for symbol in text: if symbol in abc: - # 1st plugboard -------------------------- if symbol in plugboard: symbol = plugboard[symbol] diff --git a/ciphers/playfair_cipher.py b/ciphers/playfair_cipher.py index 89aedb7af..7279fb23e 100644 --- a/ciphers/playfair_cipher.py +++ b/ciphers/playfair_cipher.py @@ -39,7 +39,6 @@ def prepare_input(dirty: str) -> str: def generate_table(key: str) -> list[str]: - # I and J are used interchangeably to allow # us to use a 5x5 table (25 letters) alphabet = "ABCDEFGHIKLMNOPQRSTUVWXYZ" diff --git a/ciphers/polybius.py b/ciphers/polybius.py index c81c1d395..3539ab70c 100644 --- a/ciphers/polybius.py +++ b/ciphers/polybius.py @@ -19,7 +19,6 @@ SQUARE = [ class PolybiusCipher: def __init__(self) -> None: - self.SQUARE = np.array(SQUARE) def letter_to_numbers(self, letter: str) -> np.ndarray: diff --git a/ciphers/xor_cipher.py b/ciphers/xor_cipher.py index ca9dfe20f..379ef0ef7 100644 --- a/ciphers/xor_cipher.py +++ b/ciphers/xor_cipher.py @@ -130,7 +130,6 @@ class XORCipher: try: with open(file) as fin: with open("encrypt.out", "w+") as fout: - # actual encrypt-process for line in fin: fout.write(self.encrypt_string(line, key)) @@ -155,7 +154,6 @@ class XORCipher: try: with open(file) as fin: with open("decrypt.out", "w+") as fout: - # actual encrypt-process for line in fin: fout.write(self.decrypt_string(line, key)) diff --git a/compression/lz77.py b/compression/lz77.py index 7c1a6f6a4..1b201c59f 100644 --- a/compression/lz77.py +++ b/compression/lz77.py @@ -89,7 +89,6 @@ class LZ77Compressor: # while there are still characters in text to compress while text: - # find the next encoding phrase # - triplet with offset, length, indicator (the next encoding character) token = self._find_encoding_token(text, search_buffer) diff --git a/computer_vision/cnn_classification.py b/computer_vision/cnn_classification.py index 59e4556e0..1c193fcbb 100644 --- a/computer_vision/cnn_classification.py +++ b/computer_vision/cnn_classification.py @@ -28,7 +28,6 @@ import tensorflow as tf from tensorflow.keras import layers, models if __name__ == "__main__": - # Initialising the CNN # (Sequential- Building the model layer by layer) classifier = models.Sequential() diff --git a/computer_vision/harris_corner.py b/computer_vision/harris_corner.py index c8905bb6a..0cc7522bc 100644 --- a/computer_vision/harris_corner.py +++ b/computer_vision/harris_corner.py @@ -9,7 +9,6 @@ https://en.wikipedia.org/wiki/Harris_Corner_Detector class HarrisCorner: def __init__(self, k: float, window_size: int): - """ k : is an empirically determined constant in [0.04,0.06] window_size : neighbourhoods considered @@ -25,7 +24,6 @@ class HarrisCorner: return str(self.k) def detect(self, img_path: str) -> tuple[cv2.Mat, list[list[int]]]: - """ Returns the image with corners identified img_path : path of the image @@ -68,7 +66,6 @@ class HarrisCorner: if __name__ == "__main__": - edge_detect = HarrisCorner(0.04, 3) color_img, _ = edge_detect.detect("path_to_image") cv2.imwrite("detect.png", color_img) diff --git a/conversions/decimal_to_binary.py b/conversions/decimal_to_binary.py index cfda57ca7..973c47c8a 100644 --- a/conversions/decimal_to_binary.py +++ b/conversions/decimal_to_binary.py @@ -2,7 +2,6 @@ def decimal_to_binary(num: int) -> str: - """ Convert an Integer Decimal Number to a Binary Number as str. >>> decimal_to_binary(0) diff --git a/conversions/molecular_chemistry.py b/conversions/molecular_chemistry.py index 0024eb5cb..51ffe534d 100644 --- a/conversions/molecular_chemistry.py +++ b/conversions/molecular_chemistry.py @@ -86,7 +86,6 @@ def pressure_and_volume_to_temperature( if __name__ == "__main__": - import doctest doctest.testmod() diff --git a/conversions/roman_numerals.py b/conversions/roman_numerals.py index 61215a0c0..75af2ac72 100644 --- a/conversions/roman_numerals.py +++ b/conversions/roman_numerals.py @@ -47,7 +47,7 @@ def int_to_roman(number: int) -> str: True """ result = [] - for (arabic, roman) in ROMAN: + for arabic, roman in ROMAN: (factor, number) = divmod(number, arabic) result.append(roman * factor) if number == 0: diff --git a/conversions/temperature_conversions.py b/conversions/temperature_conversions.py index e5af46556..f7af6c8f1 100644 --- a/conversions/temperature_conversions.py +++ b/conversions/temperature_conversions.py @@ -380,7 +380,6 @@ def reaumur_to_rankine(reaumur: float, ndigits: int = 2) -> float: if __name__ == "__main__": - import doctest doctest.testmod() diff --git a/conversions/weight_conversion.py b/conversions/weight_conversion.py index 18c403731..5c032a497 100644 --- a/conversions/weight_conversion.py +++ b/conversions/weight_conversion.py @@ -307,7 +307,6 @@ def weight_conversion(from_type: str, to_type: str, value: float) -> float: if __name__ == "__main__": - import doctest doctest.testmod() diff --git a/data_structures/binary_tree/binary_tree_traversals.py b/data_structures/binary_tree/binary_tree_traversals.py index 54b1dc536..24dd1bd8c 100644 --- a/data_structures/binary_tree/binary_tree_traversals.py +++ b/data_structures/binary_tree/binary_tree_traversals.py @@ -105,7 +105,6 @@ def get_nodes_from_left_to_right( if not root: return if level == 1: - output.append(root.data) elif level > 1: populate_output(root.left, level - 1) diff --git a/data_structures/binary_tree/inorder_tree_traversal_2022.py b/data_structures/binary_tree/inorder_tree_traversal_2022.py index 08001738f..e94ba7013 100644 --- a/data_structures/binary_tree/inorder_tree_traversal_2022.py +++ b/data_structures/binary_tree/inorder_tree_traversal_2022.py @@ -58,7 +58,6 @@ def inorder(node: None | BinaryTreeNode) -> list[int]: # if node is None,return def make_tree() -> BinaryTreeNode | None: - root = insert(None, 15) insert(root, 10) insert(root, 25) diff --git a/data_structures/hashing/double_hash.py b/data_structures/hashing/double_hash.py index 453e0d131..be21e74ca 100644 --- a/data_structures/hashing/double_hash.py +++ b/data_structures/hashing/double_hash.py @@ -24,7 +24,6 @@ class DoubleHash(HashTable): super().__init__(*args, **kwargs) def __hash_function_2(self, value, data): - next_prime_gt = ( next_prime(value % self.size_table) if not is_prime(value % self.size_table) diff --git a/data_structures/hashing/hash_table.py b/data_structures/hashing/hash_table.py index 607454c82..7ca2f7c40 100644 --- a/data_structures/hashing/hash_table.py +++ b/data_structures/hashing/hash_table.py @@ -32,7 +32,6 @@ class HashTable: return key % self.size_table def _step_by_step(self, step_ord): - print(f"step {step_ord}") print(list(range(len(self.values)))) print(self.values) @@ -53,7 +52,6 @@ class HashTable: new_key = self.hash_function(key + 1) while self.values[new_key] is not None and self.values[new_key] != key: - if self.values.count(None) > 0: new_key = self.hash_function(new_key + 1) else: diff --git a/data_structures/heap/binomial_heap.py b/data_structures/heap/binomial_heap.py index d79fac7a9..2e05c5c80 100644 --- a/data_structures/heap/binomial_heap.py +++ b/data_structures/heap/binomial_heap.py @@ -174,7 +174,6 @@ class BinomialHeap: i.left_tree_size == i.parent.left_tree_size and i.left_tree_size != i.parent.parent.left_tree_size ): - # Neighbouring Nodes previous_node = i.left next_node = i.parent.parent @@ -233,7 +232,6 @@ class BinomialHeap: and self.bottom_root.left_tree_size == self.bottom_root.parent.left_tree_size ): - # Next node next_node = self.bottom_root.parent.parent diff --git a/data_structures/heap/skew_heap.py b/data_structures/heap/skew_heap.py index 490db061d..c4c13b082 100644 --- a/data_structures/heap/skew_heap.py +++ b/data_structures/heap/skew_heap.py @@ -71,7 +71,6 @@ class SkewHeap(Generic[T]): """ def __init__(self, data: Iterable[T] | None = ()) -> None: - """ >>> sh = SkewHeap([3, 1, 3, 7]) >>> list(sh) diff --git a/data_structures/linked_list/doubly_linked_list_two.py b/data_structures/linked_list/doubly_linked_list_two.py index 94b916a62..c19309c9f 100644 --- a/data_structures/linked_list/doubly_linked_list_two.py +++ b/data_structures/linked_list/doubly_linked_list_two.py @@ -80,7 +80,6 @@ class LinkedList: return None def set_head(self, node: Node) -> None: - if self.head is None: self.head = node self.tail = node @@ -143,7 +142,6 @@ class LinkedList: raise Exception("Node not found") def delete_value(self, value): - if (node := self.get_node(value)) is not None: if node == self.head: self.head = self.head.get_next() diff --git a/data_structures/stacks/prefix_evaluation.py b/data_structures/stacks/prefix_evaluation.py index 00df2c1e6..f48eca23d 100644 --- a/data_structures/stacks/prefix_evaluation.py +++ b/data_structures/stacks/prefix_evaluation.py @@ -36,7 +36,6 @@ def evaluate(expression): # iterate over the string in reverse order for c in expression.split()[::-1]: - # push operand to stack if is_operand(c): stack.append(int(c)) diff --git a/data_structures/stacks/stack_with_doubly_linked_list.py b/data_structures/stacks/stack_with_doubly_linked_list.py index a129665f2..50c5236e0 100644 --- a/data_structures/stacks/stack_with_doubly_linked_list.py +++ b/data_structures/stacks/stack_with_doubly_linked_list.py @@ -92,7 +92,6 @@ class Stack(Generic[T]): # Code execution starts here if __name__ == "__main__": - # Start with the empty stack stack: Stack[int] = Stack() diff --git a/data_structures/stacks/stock_span_problem.py b/data_structures/stacks/stock_span_problem.py index 19a81bd36..de423c1eb 100644 --- a/data_structures/stacks/stock_span_problem.py +++ b/data_structures/stacks/stock_span_problem.py @@ -9,7 +9,6 @@ on the current day is less than or equal to its price on the given day. def calculation_span(price, s): - n = len(price) # Create a stack and push index of fist element to it st = [] @@ -20,7 +19,6 @@ def calculation_span(price, s): # Calculate span values for rest of the elements for i in range(1, n): - # Pop elements from stack while stack is not # empty and top of stack is smaller than price[i] while len(st) > 0 and price[st[0]] <= price[i]: diff --git a/digital_image_processing/filters/bilateral_filter.py b/digital_image_processing/filters/bilateral_filter.py index 1afa01d3f..565da73f6 100644 --- a/digital_image_processing/filters/bilateral_filter.py +++ b/digital_image_processing/filters/bilateral_filter.py @@ -50,7 +50,6 @@ def bilateral_filter( size_x, size_y = img.shape for i in range(kernel_size // 2, size_x - kernel_size // 2): for j in range(kernel_size // 2, size_y - kernel_size // 2): - img_s = get_slice(img, i, j, kernel_size) img_i = img_s - img_s[kernel_size // 2, kernel_size // 2] img_ig = vec_gaussian(img_i, intensity_variance) diff --git a/digital_image_processing/filters/local_binary_pattern.py b/digital_image_processing/filters/local_binary_pattern.py index e92e554a3..907fe2cb0 100644 --- a/digital_image_processing/filters/local_binary_pattern.py +++ b/digital_image_processing/filters/local_binary_pattern.py @@ -61,7 +61,6 @@ def local_binary_value(image: np.ndarray, x_coordinate: int, y_coordinate: int) if __name__ == "__main__": - # Reading the image and converting it to grayscale. image = cv2.imread( "digital_image_processing/image_data/lena.jpg", cv2.IMREAD_GRAYSCALE diff --git a/dynamic_programming/bitmask.py b/dynamic_programming/bitmask.py index f45250c9c..56bb8e96b 100644 --- a/dynamic_programming/bitmask.py +++ b/dynamic_programming/bitmask.py @@ -13,7 +13,6 @@ from collections import defaultdict class AssignmentUsingBitmask: def __init__(self, task_performed, total): - self.total_tasks = total # total no of tasks (N) # DP table will have a dimension of (2^M)*N @@ -29,7 +28,6 @@ class AssignmentUsingBitmask: self.final_mask = (1 << len(task_performed)) - 1 def count_ways_until(self, mask, task_no): - # if mask == self.finalmask all persons are distributed tasks, return 1 if mask == self.final_mask: return 1 @@ -49,7 +47,6 @@ class AssignmentUsingBitmask: # assign for the remaining tasks. if task_no in self.task: for p in self.task[task_no]: - # if p is already given a task if mask & (1 << p): continue @@ -64,7 +61,6 @@ class AssignmentUsingBitmask: return self.dp[mask][task_no] def count_no_of_ways(self, task_performed): - # Store the list of persons for each task for i in range(len(task_performed)): for j in task_performed[i]: @@ -75,7 +71,6 @@ class AssignmentUsingBitmask: if __name__ == "__main__": - total_tasks = 5 # total no of tasks (the value of N) # the list of tasks that can be done by M persons. diff --git a/dynamic_programming/iterating_through_submasks.py b/dynamic_programming/iterating_through_submasks.py index 21c64dba4..4d0a250e8 100644 --- a/dynamic_programming/iterating_through_submasks.py +++ b/dynamic_programming/iterating_through_submasks.py @@ -9,7 +9,6 @@ from __future__ import annotations def list_of_submasks(mask: int) -> list[int]: - """ Args: mask : number which shows mask ( always integer > 0, zero does not have any diff --git a/electronics/coulombs_law.py b/electronics/coulombs_law.py index e41c0410c..18c1a8179 100644 --- a/electronics/coulombs_law.py +++ b/electronics/coulombs_law.py @@ -8,7 +8,6 @@ COULOMBS_CONSTANT = 8.988e9 # units = N * m^s * C^-2 def couloumbs_law( force: float, charge1: float, charge2: float, distance: float ) -> dict[str, float]: - """ Apply Coulomb's Law on any three given values. These can be force, charge1, charge2, or distance, and then in a Python dict return name/value pair of diff --git a/fractals/julia_sets.py b/fractals/julia_sets.py index 77d1d7c04..482e1eddf 100644 --- a/fractals/julia_sets.py +++ b/fractals/julia_sets.py @@ -170,7 +170,6 @@ def ignore_overflow_warnings() -> None: if __name__ == "__main__": - z_0 = prepare_grid(window_size, nb_pixels) ignore_overflow_warnings() # See file header for explanations diff --git a/fractals/mandelbrot.py b/fractals/mandelbrot.py index f97bcd170..84dbda997 100644 --- a/fractals/mandelbrot.py +++ b/fractals/mandelbrot.py @@ -114,7 +114,6 @@ def get_image( # loop through the image-coordinates for image_x in range(image_width): for image_y in range(image_height): - # determine the figure-coordinates based on the image-coordinates figure_height = figure_width / image_width * image_height figure_x = figure_center_x + (image_x / image_width - 0.5) * figure_width diff --git a/geodesy/lamberts_ellipsoidal_distance.py b/geodesy/lamberts_ellipsoidal_distance.py index 62ce59bb4..4805674e5 100644 --- a/geodesy/lamberts_ellipsoidal_distance.py +++ b/geodesy/lamberts_ellipsoidal_distance.py @@ -10,7 +10,6 @@ EQUATORIAL_RADIUS = 6378137 def lamberts_ellipsoidal_distance( lat1: float, lon1: float, lat2: float, lon2: float ) -> float: - """ Calculate the shortest distance along the surface of an ellipsoid between two points on the surface of earth given longitudes and latitudes diff --git a/graphs/a_star.py b/graphs/a_star.py index 793ba3bda..e8735179e 100644 --- a/graphs/a_star.py +++ b/graphs/a_star.py @@ -16,7 +16,6 @@ def search( cost: int, heuristic: list[list[int]], ) -> tuple[list[list[int]], list[list[int]]]: - closed = [ [0 for col in range(len(grid[0]))] for row in range(len(grid)) ] # the reference grid diff --git a/graphs/check_bipartite_graph_bfs.py b/graphs/check_bipartite_graph_bfs.py index 552b7eee2..7fc57cbc7 100644 --- a/graphs/check_bipartite_graph_bfs.py +++ b/graphs/check_bipartite_graph_bfs.py @@ -20,7 +20,6 @@ def check_bipartite(graph): visited[u] = True for neighbour in graph[u]: - if neighbour == u: return False diff --git a/graphs/graph_matrix.py b/graphs/graph_matrix.py index 987168426..4adc6c0bb 100644 --- a/graphs/graph_matrix.py +++ b/graphs/graph_matrix.py @@ -8,7 +8,6 @@ class Graph: self.graph[v - 1][u - 1] = 1 def show(self): - for i in self.graph: for j in i: print(j, end=" ") diff --git a/graphs/karger.py b/graphs/karger.py index f72128c81..3ef65c0d6 100644 --- a/graphs/karger.py +++ b/graphs/karger.py @@ -47,7 +47,6 @@ def partition_graph(graph: dict[str, list[str]]) -> set[tuple[str, str]]: graph_copy = {node: graph[node][:] for node in graph} while len(graph_copy) > 2: - # Choose a random edge. u = random.choice(list(graph_copy.keys())) v = random.choice(graph_copy[u]) diff --git a/graphs/minimum_spanning_tree_boruvka.py b/graphs/minimum_spanning_tree_boruvka.py index 6c72615cc..663d8e26c 100644 --- a/graphs/minimum_spanning_tree_boruvka.py +++ b/graphs/minimum_spanning_tree_boruvka.py @@ -4,7 +4,6 @@ class Graph: """ def __init__(self): - self.num_vertices = 0 self.num_edges = 0 self.adjacency = {} diff --git a/graphs/multi_heuristic_astar.py b/graphs/multi_heuristic_astar.py index cd8e37b00..0a18ede6e 100644 --- a/graphs/multi_heuristic_astar.py +++ b/graphs/multi_heuristic_astar.py @@ -33,7 +33,7 @@ class PriorityQueue: temp.append((pri, x)) (pri, x) = heapq.heappop(self.elements) temp.append((priority, item)) - for (pro, xxx) in temp: + for pro, xxx in temp: heapq.heappush(self.elements, (pro, xxx)) def remove_element(self, item): @@ -44,7 +44,7 @@ class PriorityQueue: while x != item: temp.append((pro, x)) (pro, x) = heapq.heappop(self.elements) - for (prito, yyy) in temp: + for prito, yyy in temp: heapq.heappush(self.elements, (prito, yyy)) def top_show(self): diff --git a/knapsack/recursive_approach_knapsack.py b/knapsack/recursive_approach_knapsack.py index d813981cb..9a8ed1886 100644 --- a/knapsack/recursive_approach_knapsack.py +++ b/knapsack/recursive_approach_knapsack.py @@ -46,7 +46,6 @@ def knapsack( if __name__ == "__main__": - import doctest doctest.testmod() diff --git a/linear_algebra/src/conjugate_gradient.py b/linear_algebra/src/conjugate_gradient.py index 418ae88a5..4cf566ec9 100644 --- a/linear_algebra/src/conjugate_gradient.py +++ b/linear_algebra/src/conjugate_gradient.py @@ -115,7 +115,6 @@ def conjugate_gradient( iterations = 0 while error > tol: - # Save this value so we only calculate the matrix-vector product once. w = np.dot(spd_matrix, p0) diff --git a/machine_learning/k_means_clust.py b/machine_learning/k_means_clust.py index 5dc2b7118..b6305469e 100644 --- a/machine_learning/k_means_clust.py +++ b/machine_learning/k_means_clust.py @@ -74,7 +74,6 @@ def centroid_pairwise_dist(x, centroids): def assign_clusters(data, centroids): - # Compute distances between each data point and the set of centroids: # Fill in the blank (RHS only) distances_from_centroids = centroid_pairwise_dist(data, centroids) @@ -100,10 +99,8 @@ def revise_centroids(data, k, cluster_assignment): def compute_heterogeneity(data, k, centroids, cluster_assignment): - heterogeneity = 0.0 for i in range(k): - # Select all data points that belong to cluster i. Fill in the blank (RHS only) member_data_points = data[cluster_assignment == i, :] diff --git a/machine_learning/self_organizing_map.py b/machine_learning/self_organizing_map.py index 057c2a76b..32fdf1d2b 100644 --- a/machine_learning/self_organizing_map.py +++ b/machine_learning/self_organizing_map.py @@ -49,7 +49,6 @@ def main() -> None: for _ in range(epochs): for j in range(len(training_samples)): - # training sample sample = training_samples[j] diff --git a/machine_learning/sequential_minimum_optimization.py b/machine_learning/sequential_minimum_optimization.py index f5185e1d9..9c45c3512 100644 --- a/machine_learning/sequential_minimum_optimization.py +++ b/machine_learning/sequential_minimum_optimization.py @@ -82,7 +82,6 @@ class SmoSVM: k = self._k state = None while True: - # 1: Find alpha1, alpha2 try: i1, i2 = self.choose_alpha.send(state) @@ -146,7 +145,6 @@ class SmoSVM: # Predict test samples def predict(self, test_samples, classify=True): - if test_samples.shape[1] > self.samples.shape[1]: raise ValueError( "Test samples' feature length does not equal to that of train samples" diff --git a/machine_learning/xgboost_classifier.py b/machine_learning/xgboost_classifier.py index 08967f171..1da933cf6 100644 --- a/machine_learning/xgboost_classifier.py +++ b/machine_learning/xgboost_classifier.py @@ -41,7 +41,6 @@ def xgboost(features: np.ndarray, target: np.ndarray) -> XGBClassifier: def main() -> None: - """ >>> main() diff --git a/maths/armstrong_numbers.py b/maths/armstrong_numbers.py index f62991b74..26709b428 100644 --- a/maths/armstrong_numbers.py +++ b/maths/armstrong_numbers.py @@ -62,7 +62,7 @@ def pluperfect_number(n: int) -> bool: digit_histogram[rem] += 1 digit_total += 1 - for (cnt, i) in zip(digit_histogram, range(len(digit_histogram))): + for cnt, i in zip(digit_histogram, range(len(digit_histogram))): total += cnt * i**digit_total return n == total diff --git a/maths/binary_exponentiation.py b/maths/binary_exponentiation.py index 8dda5245c..147b4285f 100644 --- a/maths/binary_exponentiation.py +++ b/maths/binary_exponentiation.py @@ -5,7 +5,6 @@ def binary_exponentiation(a, n): - if n == 0: return 1 diff --git a/maths/combinations.py b/maths/combinations.py index 6db1d773f..a2324012c 100644 --- a/maths/combinations.py +++ b/maths/combinations.py @@ -39,7 +39,6 @@ def combinations(n: int, k: int) -> int: if __name__ == "__main__": - print( "The number of five-card hands possible from a standard", f"fifty-two card deck is: {combinations(52, 5)}\n", diff --git a/maths/decimal_isolate.py b/maths/decimal_isolate.py index cdf43ea5d..058ed1bb9 100644 --- a/maths/decimal_isolate.py +++ b/maths/decimal_isolate.py @@ -5,7 +5,6 @@ https://stackoverflow.com/questions/3886402/how-to-get-numbers-after-decimal-poi def decimal_isolate(number: float, digit_amount: int) -> float: - """ Isolates the decimal part of a number. If digitAmount > 0 round to that decimal place, else print the entire decimal. diff --git a/maths/fermat_little_theorem.py b/maths/fermat_little_theorem.py index 73af3e28c..eea03be24 100644 --- a/maths/fermat_little_theorem.py +++ b/maths/fermat_little_theorem.py @@ -6,7 +6,6 @@ def binary_exponentiation(a, n, mod): - if n == 0: return 1 diff --git a/maths/greedy_coin_change.py b/maths/greedy_coin_change.py index 29c2f1803..7cf669bcb 100644 --- a/maths/greedy_coin_change.py +++ b/maths/greedy_coin_change.py @@ -62,7 +62,6 @@ def find_minimum_change(denominations: list[int], value: str) -> list[int]: # Traverse through all denomination for denomination in reversed(denominations): - # Find denominations while int(total_value) >= int(denomination): total_value -= int(denomination) @@ -73,7 +72,6 @@ def find_minimum_change(denominations: list[int], value: str) -> list[int]: # Driver Code if __name__ == "__main__": - denominations = [] value = "0" diff --git a/maths/integration_by_simpson_approx.py b/maths/integration_by_simpson_approx.py index 408041de9..f77ae7613 100644 --- a/maths/integration_by_simpson_approx.py +++ b/maths/integration_by_simpson_approx.py @@ -35,7 +35,6 @@ xn = b def simpson_integration(function, a: float, b: float, precision: int = 4) -> float: - """ Args: function : the function which's integration is desired diff --git a/maths/jaccard_similarity.py b/maths/jaccard_similarity.py index b299a8147..eab25188b 100644 --- a/maths/jaccard_similarity.py +++ b/maths/jaccard_similarity.py @@ -51,7 +51,6 @@ def jaccard_similarity(set_a, set_b, alternative_union=False): """ if isinstance(set_a, set) and isinstance(set_b, set): - intersection = len(set_a.intersection(set_b)) if alternative_union: @@ -62,7 +61,6 @@ def jaccard_similarity(set_a, set_b, alternative_union=False): return intersection / union if isinstance(set_a, (list, tuple)) and isinstance(set_b, (list, tuple)): - intersection = [element for element in set_a if element in set_b] if alternative_union: diff --git a/maths/least_common_multiple.py b/maths/least_common_multiple.py index 0d087643e..621d93720 100644 --- a/maths/least_common_multiple.py +++ b/maths/least_common_multiple.py @@ -67,7 +67,6 @@ def benchmark(): class TestLeastCommonMultiple(unittest.TestCase): - test_inputs = [ (10, 20), (13, 15), diff --git a/maths/line_length.py b/maths/line_length.py index ea27ee904..b810f2d9a 100644 --- a/maths/line_length.py +++ b/maths/line_length.py @@ -10,7 +10,6 @@ def line_length( x_end: int | float, steps: int = 100, ) -> float: - """ Approximates the arc length of a line segment by treating the curve as a sequence of linear lines and summing their lengths @@ -41,7 +40,6 @@ def line_length( length = 0.0 for _ in range(steps): - # Approximates curve as a sequence of linear lines and sums their length x2 = (x_end - x_start) / steps + x1 fx2 = fnc(x2) diff --git a/maths/monte_carlo.py b/maths/monte_carlo.py index c13b8d0a4..474f1f65d 100644 --- a/maths/monte_carlo.py +++ b/maths/monte_carlo.py @@ -18,6 +18,7 @@ def pi_estimator(iterations: int): 5. Multiply this value by 4 to get your estimate of pi. 6. Print the estimated and numpy value of pi """ + # A local function to see if a dot lands in the circle. def is_in_circle(x: float, y: float) -> bool: distance_from_centre = sqrt((x**2) + (y**2)) diff --git a/maths/newton_raphson.py b/maths/newton_raphson.py index f2b7cb976..2c9cd1de9 100644 --- a/maths/newton_raphson.py +++ b/maths/newton_raphson.py @@ -19,7 +19,6 @@ def calc_derivative(f, a, h=0.001): def newton_raphson(f, x0=0, maxiter=100, step=0.0001, maxerror=1e-6, logsteps=False): - a = x0 # set the initial guess steps = [a] error = abs(f(a)) diff --git a/maths/numerical_integration.py b/maths/numerical_integration.py index 8f32fd356..f2d65f89e 100644 --- a/maths/numerical_integration.py +++ b/maths/numerical_integration.py @@ -12,7 +12,6 @@ def trapezoidal_area( x_end: int | float, steps: int = 100, ) -> float: - """ Treats curve as a collection of linear lines and sums the area of the trapezium shape they form @@ -40,7 +39,6 @@ def trapezoidal_area( area = 0.0 for _ in range(steps): - # Approximates small segments of curve as linear and solve # for trapezoidal area x2 = (x_end - x_start) / steps + x1 diff --git a/maths/primelib.py b/maths/primelib.py index 9586227ea..81d573706 100644 --- a/maths/primelib.py +++ b/maths/primelib.py @@ -59,7 +59,6 @@ def is_prime(number: int) -> bool: status = False for divisor in range(2, int(round(sqrt(number))) + 1): - # if 'number' divisible by 'divisor' then sets 'status' # of false and break up the loop. if number % divisor == 0: @@ -95,9 +94,7 @@ def sieve_er(n): # actual sieve of erathostenes for i in range(len(begin_list)): - for j in range(i + 1, len(begin_list)): - if (begin_list[i] != 0) and (begin_list[j] % begin_list[i] == 0): begin_list[j] = 0 @@ -128,9 +125,7 @@ def get_prime_numbers(n): # iterates over all numbers between 2 up to N+1 # if a number is prime then appends to list 'ans' for number in range(2, n + 1): - if is_prime(number): - ans.append(number) # precondition @@ -160,14 +155,11 @@ def prime_factorization(number): quotient = number if number == 0 or number == 1: - ans.append(number) # if 'number' not prime then builds the prime factorization of 'number' elif not is_prime(number): - while quotient != 1: - if is_prime(factor) and (quotient % factor == 0): ans.append(factor) quotient /= factor @@ -298,11 +290,9 @@ def goldbach(number): loop = True while i < len_pn and loop: - j = i + 1 while j < len_pn and loop: - if prime_numbers[i] + prime_numbers[j] == number: loop = False ans.append(prime_numbers[i]) @@ -345,7 +335,6 @@ def gcd(number1, number2): rest = 0 while number2 != 0: - rest = number1 % number2 number1 = number2 number2 = rest @@ -380,13 +369,11 @@ def kg_v(number1, number2): # for kgV (x,1) if number1 > 1 and number2 > 1: - # builds the prime factorization of 'number1' and 'number2' prime_fac_1 = prime_factorization(number1) prime_fac_2 = prime_factorization(number2) elif number1 == 1 or number2 == 1: - prime_fac_1 = [] prime_fac_2 = [] ans = max(number1, number2) @@ -398,11 +385,8 @@ def kg_v(number1, number2): # iterates through primeFac1 for n in prime_fac_1: - if n not in done: - if n in prime_fac_2: - count1 = prime_fac_1.count(n) count2 = prime_fac_2.count(n) @@ -410,7 +394,6 @@ def kg_v(number1, number2): ans *= n else: - count1 = prime_fac_1.count(n) for _ in range(count1): @@ -420,9 +403,7 @@ def kg_v(number1, number2): # iterates through primeFac2 for n in prime_fac_2: - if n not in done: - count2 = prime_fac_2.count(n) for _ in range(count2): @@ -455,7 +436,6 @@ def get_prime(n): ans = 2 # this variable holds the answer while index < n: - index += 1 ans += 1 # counts to the next number @@ -499,7 +479,6 @@ def get_primes_between(p_number_1, p_number_2): number += 1 while number < p_number_2: - ans.append(number) number += 1 @@ -534,7 +513,6 @@ def get_divisors(n): ans = [] # will be returned. for divisor in range(1, n + 1): - if n % divisor == 0: ans.append(divisor) @@ -638,7 +616,6 @@ def fib(n): ans = 1 # this will be return for _ in range(n - 1): - tmp = ans ans += fib1 fib1 = tmp diff --git a/maths/segmented_sieve.py b/maths/segmented_sieve.py index 35ed9702b..e950a83b7 100644 --- a/maths/segmented_sieve.py +++ b/maths/segmented_sieve.py @@ -25,7 +25,6 @@ def sieve(n: int) -> list[int]: while low <= n: temp = [True] * (high - low + 1) for each in in_prime: - t = math.floor(low / each) * each if t < low: t += each diff --git a/maths/two_pointer.py b/maths/two_pointer.py index ff234cddc..d0fb0fc9c 100644 --- a/maths/two_pointer.py +++ b/maths/two_pointer.py @@ -43,7 +43,6 @@ def two_pointer(nums: list[int], target: int) -> list[int]: j = len(nums) - 1 while i < j: - if nums[i] + nums[j] == target: return [i, j] elif nums[i] + nums[j] < target: diff --git a/maths/zellers_congruence.py b/maths/zellers_congruence.py index 624bbfe10..483fb000f 100644 --- a/maths/zellers_congruence.py +++ b/maths/zellers_congruence.py @@ -3,7 +3,6 @@ import datetime def zeller(date_input: str) -> str: - """ Zellers Congruence Algorithm Find the day of the week for nearly any Gregorian or Julian calendar date diff --git a/matrix/largest_square_area_in_matrix.py b/matrix/largest_square_area_in_matrix.py index cf975cb7c..a93369c56 100644 --- a/matrix/largest_square_area_in_matrix.py +++ b/matrix/largest_square_area_in_matrix.py @@ -59,7 +59,6 @@ def largest_square_area_in_matrix_top_down_approch( """ def update_area_of_max_square(row: int, col: int) -> int: - # BASE CASE if row >= rows or col >= cols: return 0 @@ -138,7 +137,6 @@ def largest_square_area_in_matrix_bottom_up( largest_square_area = 0 for row in range(rows - 1, -1, -1): for col in range(cols - 1, -1, -1): - right = dp_array[row][col + 1] diagonal = dp_array[row + 1][col + 1] bottom = dp_array[row + 1][col] @@ -169,7 +167,6 @@ def largest_square_area_in_matrix_bottom_up_space_optimization( largest_square_area = 0 for row in range(rows - 1, -1, -1): for col in range(cols - 1, -1, -1): - right = current_row[col + 1] diagonal = next_row[col + 1] bottom = next_row[col] diff --git a/other/activity_selection.py b/other/activity_selection.py index 18ff6a24c..2cc08d959 100644 --- a/other/activity_selection.py +++ b/other/activity_selection.py @@ -25,7 +25,6 @@ def print_max_activities(start: list[int], finish: list[int]) -> None: # Consider rest of the activities for j in range(n): - # If this activity has start time greater than # or equal to the finish time of previously # selected activity, then select it diff --git a/other/nested_brackets.py b/other/nested_brackets.py index 9dd9a0f04..3f61a4e70 100644 --- a/other/nested_brackets.py +++ b/other/nested_brackets.py @@ -15,14 +15,12 @@ brackets and returns true if S is nested and false otherwise. def is_balanced(s): - stack = [] open_brackets = set({"(", "[", "{"}) closed_brackets = set({")", "]", "}"}) open_to_closed = dict({"{": "}", "[": "]", "(": ")"}) for i in range(len(s)): - if s[i] in open_brackets: stack.append(s[i]) diff --git a/other/scoring_algorithm.py b/other/scoring_algorithm.py index 1e6293f84..00d87cfc0 100644 --- a/other/scoring_algorithm.py +++ b/other/scoring_algorithm.py @@ -26,7 +26,6 @@ Thus the weights for each column are as follows: def procentual_proximity( source_data: list[list[float]], weights: list[int] ) -> list[list[float]]: - """ weights - int list possible values - 0 / 1 diff --git a/other/sdes.py b/other/sdes.py index 695675000..31105984b 100644 --- a/other/sdes.py +++ b/other/sdes.py @@ -54,7 +54,6 @@ def function(expansion, s0, s1, key, message): if __name__ == "__main__": - key = input("Enter 10 bit key: ") message = input("Enter 8 bit message: ") diff --git a/physics/casimir_effect.py b/physics/casimir_effect.py index ee8a6c1eb..e4a77e5b5 100644 --- a/physics/casimir_effect.py +++ b/physics/casimir_effect.py @@ -47,7 +47,6 @@ SPEED_OF_LIGHT = 3e8 # unit of c : m * s^-1 def casimir_force(force: float, area: float, distance: float) -> dict[str, float]: - """ Input Parameters ---------------- diff --git a/physics/hubble_parameter.py b/physics/hubble_parameter.py index 798564722..6bc62e713 100644 --- a/physics/hubble_parameter.py +++ b/physics/hubble_parameter.py @@ -34,7 +34,6 @@ def hubble_parameter( dark_energy: float, redshift: float, ) -> float: - """ Input Parameters ---------------- diff --git a/physics/newtons_law_of_gravitation.py b/physics/newtons_law_of_gravitation.py index 0bb27bb24..4bbeddd61 100644 --- a/physics/newtons_law_of_gravitation.py +++ b/physics/newtons_law_of_gravitation.py @@ -28,7 +28,6 @@ GRAVITATIONAL_CONSTANT = 6.6743e-11 # unit of G : m^3 * kg^-1 * s^-2 def gravitational_law( force: float, mass_1: float, mass_2: float, distance: float ) -> dict[str, float]: - """ Input Parameters ---------------- diff --git a/project_euler/problem_004/sol1.py b/project_euler/problem_004/sol1.py index b1e229289..f237afdd9 100644 --- a/project_euler/problem_004/sol1.py +++ b/project_euler/problem_004/sol1.py @@ -32,12 +32,10 @@ def solution(n: int = 998001) -> int: # fetches the next number for number in range(n - 1, 9999, -1): - str_number = str(number) # checks whether 'str_number' is a palindrome. if str_number == str_number[::-1]: - divisor = 999 # if 'number' is a product of two 3-digit numbers diff --git a/project_euler/problem_074/sol2.py b/project_euler/problem_074/sol2.py index d76bb014d..b54bc023e 100644 --- a/project_euler/problem_074/sol2.py +++ b/project_euler/problem_074/sol2.py @@ -111,7 +111,6 @@ def solution(chain_length: int = 60, number_limit: int = 1000000) -> int: chain_sets_lengths: dict[int, int] = {} for start_chain_element in range(1, number_limit): - # The temporary set will contain the elements of the chain chain_set = set() chain_set_length = 0 diff --git a/project_euler/problem_089/sol1.py b/project_euler/problem_089/sol1.py index 83609cd23..123159bdc 100644 --- a/project_euler/problem_089/sol1.py +++ b/project_euler/problem_089/sol1.py @@ -138,5 +138,4 @@ def solution(roman_numerals_filename: str = "/p089_roman.txt") -> int: if __name__ == "__main__": - print(f"{solution() = }") diff --git a/project_euler/problem_092/sol1.py b/project_euler/problem_092/sol1.py index 33a6c0694..8d3f0c9dd 100644 --- a/project_euler/problem_092/sol1.py +++ b/project_euler/problem_092/sol1.py @@ -15,7 +15,6 @@ DIGITS_SQUARED = [sum(int(c, 10) ** 2 for c in i.__str__()) for i in range(10000 def next_number(number: int) -> int: - """ Returns the next number of the chain by adding the square of each digit to form a new number. @@ -31,7 +30,6 @@ def next_number(number: int) -> int: sum_of_digits_squared = 0 while number: - # Increased Speed Slightly by checking every 5 digits together. sum_of_digits_squared += DIGITS_SQUARED[number % 100000] number //= 100000 diff --git a/quantum/q_fourier_transform.py b/quantum/q_fourier_transform.py index 07a257579..762ac4081 100644 --- a/quantum/q_fourier_transform.py +++ b/quantum/q_fourier_transform.py @@ -72,7 +72,6 @@ def quantum_fourier_transform(number_of_qubits: int = 3) -> qiskit.result.counts counter = number_of_qubits for i in range(counter): - quantum_circuit.h(number_of_qubits - i - 1) counter -= 1 for j in range(counter): diff --git a/quantum/quantum_teleportation.py b/quantum/quantum_teleportation.py index d04b44d15..5da79ed20 100644 --- a/quantum/quantum_teleportation.py +++ b/quantum/quantum_teleportation.py @@ -18,7 +18,6 @@ from qiskit import Aer, ClassicalRegister, QuantumCircuit, QuantumRegister, exec def quantum_teleportation( theta: float = np.pi / 2, phi: float = np.pi / 2, lam: float = np.pi / 2 ) -> qiskit.result.counts.Counts: - """ # >>> quantum_teleportation() #{'00': 500, '11': 500} # ideally diff --git a/scheduling/highest_response_ratio_next.py b/scheduling/highest_response_ratio_next.py index a5c62ddbe..9c999ec65 100644 --- a/scheduling/highest_response_ratio_next.py +++ b/scheduling/highest_response_ratio_next.py @@ -37,7 +37,6 @@ def calculate_turn_around_time( arrival_time.sort() while no_of_process > finished_process_count: - """ If the current time is less than the arrival time of the process that arrives first among the processes that have not been performed, @@ -94,7 +93,6 @@ def calculate_waiting_time( if __name__ == "__main__": - no_of_process = 5 process_name = ["A", "B", "C", "D", "E"] arrival_time = [1, 2, 3, 4, 5] diff --git a/searches/binary_search.py b/searches/binary_search.py index 88fee4715..05dadd4fe 100644 --- a/searches/binary_search.py +++ b/searches/binary_search.py @@ -261,7 +261,6 @@ def binary_search_std_lib(sorted_collection: list[int], item: int) -> int | None def binary_search_by_recursion( sorted_collection: list[int], item: int, left: int, right: int ) -> int | None: - """Pure implementation of binary search algorithm in Python by recursion Be careful collection must be ascending sorted, otherwise result will be diff --git a/searches/interpolation_search.py b/searches/interpolation_search.py index 35e6bc506..49194c260 100644 --- a/searches/interpolation_search.py +++ b/searches/interpolation_search.py @@ -49,7 +49,6 @@ def interpolation_search(sorted_collection, item): def interpolation_search_by_recursion(sorted_collection, item, left, right): - """Pure implementation of interpolation search algorithm in Python by recursion Be careful collection must be ascending sorted, otherwise result will be unpredictable diff --git a/searches/tabu_search.py b/searches/tabu_search.py index 3e1728286..d998ddc55 100644 --- a/searches/tabu_search.py +++ b/searches/tabu_search.py @@ -220,7 +220,6 @@ def tabu_search( while not found: i = 0 while i < len(best_solution): - if best_solution[i] != solution[i]: first_exchange_node = best_solution[i] second_exchange_node = solution[i] diff --git a/searches/ternary_search.py b/searches/ternary_search.py index 9830cce36..cb36e72fa 100644 --- a/searches/ternary_search.py +++ b/searches/ternary_search.py @@ -103,7 +103,6 @@ def ite_ternary_search(array: list[int], target: int) -> int: left = two_third + 1 else: - left = one_third + 1 right = two_third - 1 else: diff --git a/sorts/comb_sort.py b/sorts/comb_sort.py index 16bd10c78..3c8b1e99a 100644 --- a/sorts/comb_sort.py +++ b/sorts/comb_sort.py @@ -37,7 +37,6 @@ def comb_sort(data: list) -> list: completed = False while not completed: - # Update the gap value for a next comb gap = int(gap / shrink_factor) if gap <= 1: diff --git a/sorts/odd_even_sort.py b/sorts/odd_even_sort.py index 9ef4462c7..7dfe03054 100644 --- a/sorts/odd_even_sort.py +++ b/sorts/odd_even_sort.py @@ -30,7 +30,6 @@ def odd_even_sort(input_list: list) -> list: is_sorted = True for i in range(0, len(input_list) - 1, 2): # iterating over all even indices if input_list[i] > input_list[i + 1]: - input_list[i], input_list[i + 1] = input_list[i + 1], input_list[i] # swapping if elements not in order is_sorted = False diff --git a/sorts/odd_even_transposition_parallel.py b/sorts/odd_even_transposition_parallel.py index b656df3a3..87b0e4d1e 100644 --- a/sorts/odd_even_transposition_parallel.py +++ b/sorts/odd_even_transposition_parallel.py @@ -34,7 +34,6 @@ def oe_process(position, value, l_send, r_send, lr_cv, rr_cv, result_pipe): # we *could* stop early if we are sorted already, but it takes as long to # find out we are sorted as it does to sort the list with this algorithm for i in range(0, 10): - if (i + position) % 2 == 0 and r_send is not None: # send your value to your right neighbor process_lock.acquire() diff --git a/sorts/random_normal_distribution_quicksort.py b/sorts/random_normal_distribution_quicksort.py index 5777d5cb2..f7f60903c 100644 --- a/sorts/random_normal_distribution_quicksort.py +++ b/sorts/random_normal_distribution_quicksort.py @@ -19,7 +19,6 @@ def _in_place_quick_sort(a, start, end): def _in_place_partition(a, start, end): - count = 0 pivot = randint(start, end) temp = a[end] @@ -27,7 +26,6 @@ def _in_place_partition(a, start, end): a[pivot] = temp new_pivot_index = start - 1 for index in range(start, end): - count += 1 if a[index] < a[end]: # check if current val is less than pivot value new_pivot_index = new_pivot_index + 1 diff --git a/sorts/shrink_shell_sort.py b/sorts/shrink_shell_sort.py index 69992bfb7..f77b73d01 100644 --- a/sorts/shrink_shell_sort.py +++ b/sorts/shrink_shell_sort.py @@ -44,7 +44,6 @@ def shell_sort(collection: list) -> list: # Continue sorting until the gap is 1 while gap > 1: - # Decrease the gap value gap = int(gap / shrink) diff --git a/sorts/stooge_sort.py b/sorts/stooge_sort.py index de997a85d..9a5bedeae 100644 --- a/sorts/stooge_sort.py +++ b/sorts/stooge_sort.py @@ -12,7 +12,6 @@ def stooge_sort(arr): def stooge(arr, i, h): - if i >= h: return diff --git a/sorts/tim_sort.py b/sorts/tim_sort.py index b95ff34cf..c90c7e803 100644 --- a/sorts/tim_sort.py +++ b/sorts/tim_sort.py @@ -73,7 +73,6 @@ def tim_sort(lst): def main(): - lst = [5, 9, 10, 3, -4, 5, 178, 92, 46, -18, 0, 7] sorted_lst = tim_sort(lst) print(sorted_lst) diff --git a/strings/dna.py b/strings/dna.py index c2b96110b..33e1063f4 100644 --- a/strings/dna.py +++ b/strings/dna.py @@ -2,7 +2,6 @@ import re def dna(dna: str) -> str: - """ https://en.wikipedia.org/wiki/DNA Returns the second side of a DNA strand diff --git a/strings/hamming_distance.py b/strings/hamming_distance.py index 5de27dc77..a28949172 100644 --- a/strings/hamming_distance.py +++ b/strings/hamming_distance.py @@ -35,7 +35,6 @@ def hamming_distance(string1: str, string2: str) -> int: if __name__ == "__main__": - import doctest doctest.testmod() diff --git a/strings/levenshtein_distance.py b/strings/levenshtein_distance.py index 9f7a7e3e6..7be4074dc 100644 --- a/strings/levenshtein_distance.py +++ b/strings/levenshtein_distance.py @@ -44,11 +44,9 @@ def levenshtein_distance(first_word: str, second_word: str) -> int: previous_row = list(range(len(second_word) + 1)) for i, c1 in enumerate(first_word): - current_row = [i + 1] for j, c2 in enumerate(second_word): - # Calculate insertions, deletions and substitutions insertions = previous_row[j + 1] + 1 deletions = current_row[j] + 1 diff --git a/strings/prefix_function.py b/strings/prefix_function.py index 6eca01635..65bbe9100 100644 --- a/strings/prefix_function.py +++ b/strings/prefix_function.py @@ -29,7 +29,6 @@ def prefix_function(input_string: str) -> list: prefix_result = [0] * len(input_string) for i in range(1, len(input_string)): - # use last results for better performance - dynamic programming j = prefix_result[i - 1] while j > 0 and input_string[i] != input_string[j]: diff --git a/strings/text_justification.py b/strings/text_justification.py index 5e86456c2..b0ef12231 100644 --- a/strings/text_justification.py +++ b/strings/text_justification.py @@ -33,7 +33,6 @@ def text_justification(word: str, max_width: int) -> list: words = word.split() def justify(line: list, width: int, max_width: int) -> str: - overall_spaces_count = max_width - width words_count = len(line) if len(line) == 1: diff --git a/web_programming/fetch_anime_and_play.py b/web_programming/fetch_anime_and_play.py index e11948d0a..3bd4f704d 100644 --- a/web_programming/fetch_anime_and_play.py +++ b/web_programming/fetch_anime_and_play.py @@ -8,7 +8,6 @@ BASE_URL = "https://ww1.gogoanime2.org" def search_scraper(anime_name: str) -> list: - """[summary] Take an url and @@ -66,7 +65,6 @@ def search_scraper(anime_name: str) -> list: def search_anime_episode_list(episode_endpoint: str) -> list: - """[summary] Take an url and @@ -116,7 +114,6 @@ def search_anime_episode_list(episode_endpoint: str) -> list: def get_anime_episode(episode_endpoint: str) -> list: - """[summary] Get click url and download url from episode url @@ -153,7 +150,6 @@ def get_anime_episode(episode_endpoint: str) -> list: if __name__ == "__main__": - anime_name = input("Enter anime name: ").strip() anime_list = search_scraper(anime_name) print("\n") @@ -161,9 +157,8 @@ if __name__ == "__main__": if len(anime_list) == 0: print("No anime found with this name") else: - print(f"Found {len(anime_list)} results: ") - for (i, anime) in enumerate(anime_list): + for i, anime in enumerate(anime_list): anime_title = anime["title"] print(f"{i+1}. {anime_title}") @@ -176,7 +171,7 @@ if __name__ == "__main__": print("No episode found for this anime") else: print(f"Found {len(episode_list)} results: ") - for (i, episode) in enumerate(episode_list): + for i, episode in enumerate(episode_list): print(f"{i+1}. {episode['title']}") episode_choice = int(input("\nChoose an episode by serial no: ").strip()) diff --git a/web_programming/fetch_well_rx_price.py b/web_programming/fetch_well_rx_price.py index 5174f39f9..ee51b9a50 100644 --- a/web_programming/fetch_well_rx_price.py +++ b/web_programming/fetch_well_rx_price.py @@ -37,7 +37,6 @@ def fetch_pharmacy_and_price_list(drug_name: str, zip_code: str) -> list | None: """ try: - # Has user provided both inputs? if not drug_name or not zip_code: return None @@ -58,7 +57,6 @@ def fetch_pharmacy_and_price_list(drug_name: str, zip_code: str) -> list | None: grid_list = soup.find_all("div", {"class": "grid-x pharmCard"}) if grid_list and len(grid_list) > 0: for grid in grid_list: - # Get the pharmacy price. pharmacy_name = grid.find("p", {"class": "list-title"}).text @@ -79,7 +77,6 @@ def fetch_pharmacy_and_price_list(drug_name: str, zip_code: str) -> list | None: if __name__ == "__main__": - # Enter a drug name and a zip code drug_name = input("Enter drug name: ").strip() zip_code = input("Enter zip code: ").strip() @@ -89,10 +86,8 @@ if __name__ == "__main__": ) if pharmacy_price_list: - print(f"\nSearch results for {drug_name} at location {zip_code}:") for pharmacy_price in pharmacy_price_list: - name = pharmacy_price["pharmacy_name"] price = pharmacy_price["price"] diff --git a/web_programming/get_user_tweets.py b/web_programming/get_user_tweets.py index 28cf85541..3abc69715 100644 --- a/web_programming/get_user_tweets.py +++ b/web_programming/get_user_tweets.py @@ -10,7 +10,6 @@ access_secret = "" def get_all_tweets(screen_name: str) -> None: - # authorize twitter, initialize tweepy auth = tweepy.OAuthHandler(consumer_key, consumer_secret) auth.set_access_token(access_key, access_secret) From 77b4fa8b3f2070ff708405cca1381b7860e316ab Mon Sep 17 00:00:00 2001 From: Damon Gregory <46330424+SheriffHobo@users.noreply.github.com> Date: Sun, 12 Feb 2023 07:55:25 -0800 Subject: [PATCH 584/726] fix_ci_badge (#8134) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index da80c012b..68a6e5e6f 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@
- GitHub Workflow Status + GitHub Workflow Status pre-commit From 126e89d8a3983c1ffc9b3eefa1fbaff0f6fe4ead Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 13 Feb 2023 22:05:56 +0100 Subject: [PATCH 585/726] [pre-commit.ci] pre-commit autoupdate (#8141) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/tox-dev/pyproject-fmt: 0.6.0 → 0.8.0](https://github.com/tox-dev/pyproject-fmt/compare/0.6.0...0.8.0) - [github.com/pre-commit/mirrors-mypy: v0.991 → v1.0.0](https://github.com/pre-commit/mirrors-mypy/compare/v0.991...v1.0.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f8d1a65db..a1496984f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,7 +27,7 @@ repos: - --profile=black - repo: https://github.com/tox-dev/pyproject-fmt - rev: "0.6.0" + rev: "0.8.0" hooks: - id: pyproject-fmt @@ -62,7 +62,7 @@ repos: *flake8-plugins - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.991 + rev: v1.0.0 hooks: - id: mypy args: From 1bf03889c5e34420001e72b5d26cc0846dcd122a Mon Sep 17 00:00:00 2001 From: Jan Wojciechowski <96974442+yanvoi@users.noreply.github.com> Date: Sun, 19 Feb 2023 23:14:01 +0100 Subject: [PATCH 586/726] Update bogo_sort.py (#8144) --- sorts/bogo_sort.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/sorts/bogo_sort.py b/sorts/bogo_sort.py index b72f2089f..9c133f0d8 100644 --- a/sorts/bogo_sort.py +++ b/sorts/bogo_sort.py @@ -31,8 +31,6 @@ def bogo_sort(collection): """ def is_sorted(collection): - if len(collection) < 2: - return True for i in range(len(collection) - 1): if collection[i] > collection[i + 1]: return False From 67676c3b790d9631ea99c89f71dc2bf65e9aa2ca Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 21 Feb 2023 08:33:44 +0100 Subject: [PATCH 587/726] [pre-commit.ci] pre-commit autoupdate (#8149) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/tox-dev/pyproject-fmt: 0.8.0 → 0.9.1](https://github.com/tox-dev/pyproject-fmt/compare/0.8.0...0.9.1) - [github.com/pre-commit/mirrors-mypy: v1.0.0 → v1.0.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.0.0...v1.0.1) * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- pyproject.toml | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a1496984f..93064949e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,7 +27,7 @@ repos: - --profile=black - repo: https://github.com/tox-dev/pyproject-fmt - rev: "0.8.0" + rev: "0.9.1" hooks: - id: pyproject-fmt @@ -62,7 +62,7 @@ repos: *flake8-plugins - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.0.0 + rev: v1.0.1 hooks: - id: mypy args: diff --git a/pyproject.toml b/pyproject.toml index 410e7655b..5f9b1aa06 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,6 @@ addopts = [ "--showlocals", ] - [tool.coverage.report] omit = [".env/*"] sort = "Cover" From 1c15cdff70893bc27ced2b390959e1d9cc493628 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 27 Feb 2023 23:08:40 +0100 Subject: [PATCH 588/726] [pre-commit.ci] pre-commit autoupdate (#8160) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/tox-dev/pyproject-fmt: 0.9.1 → 0.9.2](https://github.com/tox-dev/pyproject-fmt/compare/0.9.1...0.9.2) * pre-commit: Add ruff --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .pre-commit-config.yaml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 93064949e..9f27f985b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,7 +27,7 @@ repos: - --profile=black - repo: https://github.com/tox-dev/pyproject-fmt - rev: "0.9.1" + rev: "0.9.2" hooks: - id: pyproject-fmt @@ -43,6 +43,13 @@ repos: args: - --py311-plus + - repo: https://github.com/charliermarsh/ruff-pre-commit + rev: v0.0.253 + hooks: + - id: ruff + args: + - --ignore=E741 + - repo: https://github.com/PyCQA/flake8 rev: 6.0.0 hooks: From 64543faa980b526f79d287a073ebb7554749faf9 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 1 Mar 2023 17:23:33 +0100 Subject: [PATCH 589/726] Make some ruff fixes (#8154) * Make some ruff fixes * Undo manual fix * Undo manual fix * Updates from ruff=0.0.251 --- audio_filters/iir_filter.py | 2 +- backtracking/n_queens_math.py | 6 +++--- backtracking/sum_of_subsets.py | 2 +- ciphers/bifid.py | 2 +- ciphers/diffie_hellman.py | 16 ++++++++-------- ciphers/polybius.py | 2 +- ciphers/xor_cipher.py | 18 ++++++++---------- computer_vision/mosaic_augmentation.py | 2 +- .../binary_tree/binary_search_tree.py | 2 +- .../binary_tree/binary_tree_traversals.py | 4 ++-- .../binary_tree/inorder_tree_traversal_2022.py | 2 +- data_structures/binary_tree/red_black_tree.py | 5 ++--- .../hashing/number_theory/prime_numbers.py | 2 +- data_structures/heap/binomial_heap.py | 4 ++-- .../linked_list/doubly_linked_list_two.py | 2 +- .../linked_list/singly_linked_list.py | 1 + data_structures/linked_list/skip_list.py | 5 +---- .../queue/circular_queue_linked_list.py | 2 +- .../dilation_operation.py | 2 +- .../erosion_operation.py | 2 +- dynamic_programming/all_construct.py | 2 +- dynamic_programming/fizz_buzz.py | 2 +- .../longest_common_subsequence.py | 10 ++-------- .../longest_increasing_subsequence.py | 2 +- graphs/basic_graphs.py | 14 ++++++-------- graphs/check_cycle.py | 9 ++++----- graphs/connected_components.py | 2 +- graphs/dijkstra_algorithm.py | 2 +- .../edmonds_karp_multiple_source_and_sink.py | 5 ++--- graphs/frequent_pattern_graph_miner.py | 6 +++--- graphs/minimum_spanning_tree_boruvka.py | 1 + graphs/minimum_spanning_tree_prims.py | 5 +---- graphs/minimum_spanning_tree_prims2.py | 16 +++++++--------- hashes/hamming_code.py | 5 ++--- linear_algebra/src/lib.py | 7 ++++--- machine_learning/gradient_descent.py | 2 ++ machine_learning/k_means_clust.py | 4 ++-- .../sequential_minimum_optimization.py | 9 ++++----- maths/abs.py | 6 +++--- maths/binary_exp_mod.py | 2 +- maths/jaccard_similarity.py | 1 + maths/largest_of_very_large_numbers.py | 1 + maths/radix2_fft.py | 5 +---- .../back_propagation_neural_network.py | 1 + other/graham_scan.py | 7 +++---- other/nested_brackets.py | 9 ++++----- physics/hubble_parameter.py | 4 ++-- project_euler/problem_005/sol1.py | 1 + project_euler/problem_009/sol1.py | 5 ++--- project_euler/problem_014/sol2.py | 5 +---- project_euler/problem_018/solution.py | 10 ++-------- project_euler/problem_019/sol1.py | 2 +- project_euler/problem_033/sol1.py | 8 +++----- project_euler/problem_064/sol1.py | 5 ++--- project_euler/problem_067/sol1.py | 10 ++-------- project_euler/problem_109/sol1.py | 2 +- project_euler/problem_203/sol1.py | 4 ++-- scheduling/shortest_job_first.py | 11 +++++------ scripts/build_directory_md.py | 5 ++--- searches/binary_tree_traversal.py | 1 + sorts/circle_sort.py | 13 ++++++------- sorts/counting_sort.py | 2 +- sorts/msd_radix_sort.py | 2 +- sorts/quick_sort.py | 2 +- sorts/recursive_quick_sort.py | 10 +++++----- sorts/tim_sort.py | 4 ++-- strings/autocomplete_using_trie.py | 5 +---- strings/check_anagrams.py | 5 +---- strings/is_palindrome.py | 5 +---- strings/snake_case_to_camel_pascal_case.py | 2 +- web_programming/convert_number_to_words.py | 6 +++--- web_programming/instagram_crawler.py | 2 +- web_programming/open_google_results.py | 5 +---- 73 files changed, 151 insertions(+), 203 deletions(-) diff --git a/audio_filters/iir_filter.py b/audio_filters/iir_filter.py index aae320365..bd448175f 100644 --- a/audio_filters/iir_filter.py +++ b/audio_filters/iir_filter.py @@ -47,7 +47,7 @@ class IIRFilter: >>> filt.set_coefficients(a_coeffs, b_coeffs) """ if len(a_coeffs) < self.order: - a_coeffs = [1.0] + a_coeffs + a_coeffs = [1.0, *a_coeffs] if len(a_coeffs) != self.order + 1: raise ValueError( diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index 23bd15906..f3b08ab0a 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -129,9 +129,9 @@ def depth_first_search( # If it is False we call dfs function again and we update the inputs depth_first_search( - possible_board + [col], - diagonal_right_collisions + [row - col], - diagonal_left_collisions + [row + col], + [*possible_board, col], + [*diagonal_right_collisions, row - col], + [*diagonal_left_collisions, row + col], boards, n, ) diff --git a/backtracking/sum_of_subsets.py b/backtracking/sum_of_subsets.py index 128e29071..c5e23321c 100644 --- a/backtracking/sum_of_subsets.py +++ b/backtracking/sum_of_subsets.py @@ -44,7 +44,7 @@ def create_state_space_tree( nums, max_sum, index + 1, - path + [nums[index]], + [*path, nums[index]], result, remaining_nums_sum - nums[index], ) diff --git a/ciphers/bifid.py b/ciphers/bifid.py index c005e051a..a15b38164 100644 --- a/ciphers/bifid.py +++ b/ciphers/bifid.py @@ -33,7 +33,7 @@ class BifidCipher: >>> np.array_equal(BifidCipher().letter_to_numbers('u'), [4,5]) True """ - index1, index2 = np.where(self.SQUARE == letter) + index1, index2 = np.where(letter == self.SQUARE) indexes = np.concatenate([index1 + 1, index2 + 1]) return indexes diff --git a/ciphers/diffie_hellman.py b/ciphers/diffie_hellman.py index 072f4aaaa..cd40a6b9c 100644 --- a/ciphers/diffie_hellman.py +++ b/ciphers/diffie_hellman.py @@ -228,10 +228,10 @@ class DiffieHellman: def is_valid_public_key(self, key: int) -> bool: # check if the other public key is valid based on NIST SP800-56 - if 2 <= key and key <= self.prime - 2: - if pow(key, (self.prime - 1) // 2, self.prime) == 1: - return True - return False + return ( + 2 <= key <= self.prime - 2 + and pow(key, (self.prime - 1) // 2, self.prime) == 1 + ) def generate_shared_key(self, other_key_str: str) -> str: other_key = int(other_key_str, base=16) @@ -243,10 +243,10 @@ class DiffieHellman: @staticmethod def is_valid_public_key_static(remote_public_key_str: int, prime: int) -> bool: # check if the other public key is valid based on NIST SP800-56 - if 2 <= remote_public_key_str and remote_public_key_str <= prime - 2: - if pow(remote_public_key_str, (prime - 1) // 2, prime) == 1: - return True - return False + return ( + 2 <= remote_public_key_str <= prime - 2 + and pow(remote_public_key_str, (prime - 1) // 2, prime) == 1 + ) @staticmethod def generate_shared_key_static( diff --git a/ciphers/polybius.py b/ciphers/polybius.py index 3539ab70c..d83badf4a 100644 --- a/ciphers/polybius.py +++ b/ciphers/polybius.py @@ -31,7 +31,7 @@ class PolybiusCipher: >>> np.array_equal(PolybiusCipher().letter_to_numbers('u'), [4,5]) True """ - index1, index2 = np.where(self.SQUARE == letter) + index1, index2 = np.where(letter == self.SQUARE) indexes = np.concatenate([index1 + 1, index2 + 1]) return indexes diff --git a/ciphers/xor_cipher.py b/ciphers/xor_cipher.py index 379ef0ef7..0f369e38f 100644 --- a/ciphers/xor_cipher.py +++ b/ciphers/xor_cipher.py @@ -128,11 +128,10 @@ class XORCipher: assert isinstance(file, str) and isinstance(key, int) try: - with open(file) as fin: - with open("encrypt.out", "w+") as fout: - # actual encrypt-process - for line in fin: - fout.write(self.encrypt_string(line, key)) + with open(file) as fin, open("encrypt.out", "w+") as fout: + # actual encrypt-process + for line in fin: + fout.write(self.encrypt_string(line, key)) except OSError: return False @@ -152,11 +151,10 @@ class XORCipher: assert isinstance(file, str) and isinstance(key, int) try: - with open(file) as fin: - with open("decrypt.out", "w+") as fout: - # actual encrypt-process - for line in fin: - fout.write(self.decrypt_string(line, key)) + with open(file) as fin, open("decrypt.out", "w+") as fout: + # actual encrypt-process + for line in fin: + fout.write(self.decrypt_string(line, key)) except OSError: return False diff --git a/computer_vision/mosaic_augmentation.py b/computer_vision/mosaic_augmentation.py index e29537497..c150126d6 100644 --- a/computer_vision/mosaic_augmentation.py +++ b/computer_vision/mosaic_augmentation.py @@ -159,7 +159,7 @@ def update_image_and_anno( new_anno.append([bbox[0], xmin, ymin, xmax, ymax]) # Remove bounding box small than scale of filter - if 0 < filter_scale: + if filter_scale > 0: new_anno = [ anno for anno in new_anno diff --git a/data_structures/binary_tree/binary_search_tree.py b/data_structures/binary_tree/binary_search_tree.py index fc512944e..cd88cc10e 100644 --- a/data_structures/binary_tree/binary_search_tree.py +++ b/data_structures/binary_tree/binary_search_tree.py @@ -60,7 +60,7 @@ class BinarySearchTree: else: # Tree is not empty parent_node = self.root # from root if parent_node is None: - return None + return while True: # While we don't get to a leaf if value < parent_node.value: # We go left if parent_node.left is None: diff --git a/data_structures/binary_tree/binary_tree_traversals.py b/data_structures/binary_tree/binary_tree_traversals.py index 24dd1bd8c..71a895e76 100644 --- a/data_structures/binary_tree/binary_tree_traversals.py +++ b/data_structures/binary_tree/binary_tree_traversals.py @@ -37,7 +37,7 @@ def preorder(root: Node | None) -> list[int]: >>> preorder(make_tree()) [1, 2, 4, 5, 3] """ - return [root.data] + preorder(root.left) + preorder(root.right) if root else [] + return [root.data, *preorder(root.left), *preorder(root.right)] if root else [] def postorder(root: Node | None) -> list[int]: @@ -55,7 +55,7 @@ def inorder(root: Node | None) -> list[int]: >>> inorder(make_tree()) [4, 2, 5, 1, 3] """ - return inorder(root.left) + [root.data] + inorder(root.right) if root else [] + return [*inorder(root.left), root.data, *inorder(root.right)] if root else [] def height(root: Node | None) -> int: diff --git a/data_structures/binary_tree/inorder_tree_traversal_2022.py b/data_structures/binary_tree/inorder_tree_traversal_2022.py index e94ba7013..1357527d2 100644 --- a/data_structures/binary_tree/inorder_tree_traversal_2022.py +++ b/data_structures/binary_tree/inorder_tree_traversal_2022.py @@ -50,7 +50,7 @@ def inorder(node: None | BinaryTreeNode) -> list[int]: # if node is None,return """ if node: inorder_array = inorder(node.left_child) - inorder_array = inorder_array + [node.data] + inorder_array = [*inorder_array, node.data] inorder_array = inorder_array + inorder(node.right_child) else: inorder_array = [] diff --git a/data_structures/binary_tree/red_black_tree.py b/data_structures/binary_tree/red_black_tree.py index a9dbd699c..b50d75d33 100644 --- a/data_structures/binary_tree/red_black_tree.py +++ b/data_structures/binary_tree/red_black_tree.py @@ -319,9 +319,8 @@ class RedBlackTree: """A helper function to recursively check Property 4 of a Red-Black Tree. See check_color_properties for more info. """ - if self.color == 1: - if color(self.left) == 1 or color(self.right) == 1: - return False + if self.color == 1 and 1 in (color(self.left), color(self.right)): + return False if self.left and not self.left.check_coloring(): return False if self.right and not self.right.check_coloring(): diff --git a/data_structures/hashing/number_theory/prime_numbers.py b/data_structures/hashing/number_theory/prime_numbers.py index b88ab76ec..0c25896f9 100644 --- a/data_structures/hashing/number_theory/prime_numbers.py +++ b/data_structures/hashing/number_theory/prime_numbers.py @@ -52,7 +52,7 @@ def next_prime(value, factor=1, **kwargs): first_value_val = value while not is_prime(value): - value += 1 if not ("desc" in kwargs.keys() and kwargs["desc"] is True) else -1 + value += 1 if not ("desc" in kwargs and kwargs["desc"] is True) else -1 if value == first_value_val: return next_prime(value + 1, **kwargs) diff --git a/data_structures/heap/binomial_heap.py b/data_structures/heap/binomial_heap.py index 2e05c5c80..099bd2871 100644 --- a/data_structures/heap/binomial_heap.py +++ b/data_structures/heap/binomial_heap.py @@ -136,12 +136,12 @@ class BinomialHeap: # Empty heaps corner cases if other.size == 0: - return + return None if self.size == 0: self.size = other.size self.bottom_root = other.bottom_root self.min_node = other.min_node - return + return None # Update size self.size = self.size + other.size diff --git a/data_structures/linked_list/doubly_linked_list_two.py b/data_structures/linked_list/doubly_linked_list_two.py index c19309c9f..e993cc5a2 100644 --- a/data_structures/linked_list/doubly_linked_list_two.py +++ b/data_structures/linked_list/doubly_linked_list_two.py @@ -128,7 +128,7 @@ class LinkedList: while node: if current_position == position: self.insert_before_node(node, new_node) - return None + return current_position += 1 node = node.next self.insert_after_node(self.tail, new_node) diff --git a/data_structures/linked_list/singly_linked_list.py b/data_structures/linked_list/singly_linked_list.py index 3e52c7e43..bdeb5922a 100644 --- a/data_structures/linked_list/singly_linked_list.py +++ b/data_structures/linked_list/singly_linked_list.py @@ -107,6 +107,7 @@ class LinkedList: for i, node in enumerate(self): if i == index: return node + return None # Used to change the data of a particular node def __setitem__(self, index: int, data: Any) -> None: diff --git a/data_structures/linked_list/skip_list.py b/data_structures/linked_list/skip_list.py index 96b0db7c8..4413c53e5 100644 --- a/data_structures/linked_list/skip_list.py +++ b/data_structures/linked_list/skip_list.py @@ -388,10 +388,7 @@ def test_delete_doesnt_leave_dead_nodes(): def test_iter_always_yields_sorted_values(): def is_sorted(lst): - for item, next_item in zip(lst, lst[1:]): - if next_item < item: - return False - return True + return all(next_item >= item for item, next_item in zip(lst, lst[1:])) skip_list = SkipList() for i in range(10): diff --git a/data_structures/queue/circular_queue_linked_list.py b/data_structures/queue/circular_queue_linked_list.py index e8c2b8bff..62042c4bc 100644 --- a/data_structures/queue/circular_queue_linked_list.py +++ b/data_structures/queue/circular_queue_linked_list.py @@ -127,7 +127,7 @@ class CircularQueueLinkedList: """ self.check_can_perform_operation() if self.rear is None or self.front is None: - return + return None if self.front == self.rear: data = self.front.data self.front.data = None diff --git a/digital_image_processing/morphological_operations/dilation_operation.py b/digital_image_processing/morphological_operations/dilation_operation.py index 274880b0a..c8380737d 100644 --- a/digital_image_processing/morphological_operations/dilation_operation.py +++ b/digital_image_processing/morphological_operations/dilation_operation.py @@ -32,7 +32,7 @@ def gray2binary(gray: np.array) -> np.array: [False, True, False], [False, True, False]]) """ - return (127 < gray) & (gray <= 255) + return (gray > 127) & (gray <= 255) def dilation(image: np.array, kernel: np.array) -> np.array: diff --git a/digital_image_processing/morphological_operations/erosion_operation.py b/digital_image_processing/morphological_operations/erosion_operation.py index 4b0a5eee8..c2cde2ea6 100644 --- a/digital_image_processing/morphological_operations/erosion_operation.py +++ b/digital_image_processing/morphological_operations/erosion_operation.py @@ -32,7 +32,7 @@ def gray2binary(gray: np.array) -> np.array: [False, True, False], [False, True, False]]) """ - return (127 < gray) & (gray <= 255) + return (gray > 127) & (gray <= 255) def erosion(image: np.array, kernel: np.array) -> np.array: diff --git a/dynamic_programming/all_construct.py b/dynamic_programming/all_construct.py index 3839d01e6..6e53a702c 100644 --- a/dynamic_programming/all_construct.py +++ b/dynamic_programming/all_construct.py @@ -34,7 +34,7 @@ def all_construct(target: str, word_bank: list[str] | None = None) -> list[list[ # slice condition if target[i : i + len(word)] == word: new_combinations: list[list[str]] = [ - [word] + way for way in table[i] + [word, *way] for way in table[i] ] # adds the word to every combination the current position holds # now,push that combination to the table[i+len(word)] diff --git a/dynamic_programming/fizz_buzz.py b/dynamic_programming/fizz_buzz.py index e77ab3de7..e29116437 100644 --- a/dynamic_programming/fizz_buzz.py +++ b/dynamic_programming/fizz_buzz.py @@ -49,7 +49,7 @@ def fizz_buzz(number: int, iterations: int) -> str: out += "Fizz" if number % 5 == 0: out += "Buzz" - if not number % 3 == 0 and not number % 5 == 0: + if 0 not in (number % 3, number % 5): out += str(number) # print(out) diff --git a/dynamic_programming/longest_common_subsequence.py b/dynamic_programming/longest_common_subsequence.py index 3468fd87d..178b4169b 100644 --- a/dynamic_programming/longest_common_subsequence.py +++ b/dynamic_programming/longest_common_subsequence.py @@ -42,20 +42,14 @@ def longest_common_subsequence(x: str, y: str): for i in range(1, m + 1): for j in range(1, n + 1): - if x[i - 1] == y[j - 1]: - match = 1 - else: - match = 0 + match = 1 if x[i - 1] == y[j - 1] else 0 l[i][j] = max(l[i - 1][j], l[i][j - 1], l[i - 1][j - 1] + match) seq = "" i, j = m, n while i > 0 and j > 0: - if x[i - 1] == y[j - 1]: - match = 1 - else: - match = 0 + match = 1 if x[i - 1] == y[j - 1] else 0 if l[i][j] == l[i - 1][j - 1] + match: if match == 1: diff --git a/dynamic_programming/longest_increasing_subsequence.py b/dynamic_programming/longest_increasing_subsequence.py index 6feed2352..d82789376 100644 --- a/dynamic_programming/longest_increasing_subsequence.py +++ b/dynamic_programming/longest_increasing_subsequence.py @@ -48,7 +48,7 @@ def longest_subsequence(array: list[int]) -> list[int]: # This function is recu i += 1 temp_array = [element for element in array[1:] if element >= pivot] - temp_array = [pivot] + longest_subsequence(temp_array) + temp_array = [pivot, *longest_subsequence(temp_array)] if len(temp_array) > len(longest_subseq): return temp_array else: diff --git a/graphs/basic_graphs.py b/graphs/basic_graphs.py index 298a97bf0..065b6185c 100644 --- a/graphs/basic_graphs.py +++ b/graphs/basic_graphs.py @@ -139,10 +139,9 @@ def dijk(g, s): u = i known.add(u) for v in g[u]: - if v[0] not in known: - if dist[u] + v[1] < dist.get(v[0], 100000): - dist[v[0]] = dist[u] + v[1] - path[v[0]] = u + if v[0] not in known and dist[u] + v[1] < dist.get(v[0], 100000): + dist[v[0]] = dist[u] + v[1] + path[v[0]] = u for i in dist: if i != s: print(dist[i]) @@ -243,10 +242,9 @@ def prim(g, s): u = i known.add(u) for v in g[u]: - if v[0] not in known: - if v[1] < dist.get(v[0], 100000): - dist[v[0]] = v[1] - path[v[0]] = u + if v[0] not in known and v[1] < dist.get(v[0], 100000): + dist[v[0]] = v[1] + path[v[0]] = u return dist diff --git a/graphs/check_cycle.py b/graphs/check_cycle.py index dcc864988..9fd1cd80f 100644 --- a/graphs/check_cycle.py +++ b/graphs/check_cycle.py @@ -15,11 +15,10 @@ def check_cycle(graph: dict) -> bool: visited: set[int] = set() # To detect a back edge, keep track of vertices currently in the recursion stack rec_stk: set[int] = set() - for node in graph: - if node not in visited: - if depth_first_search(graph, node, visited, rec_stk): - return True - return False + return any( + node not in visited and depth_first_search(graph, node, visited, rec_stk) + for node in graph + ) def depth_first_search(graph: dict, vertex: int, visited: set, rec_stk: set) -> bool: diff --git a/graphs/connected_components.py b/graphs/connected_components.py index 4af7803d7..15c7633e1 100644 --- a/graphs/connected_components.py +++ b/graphs/connected_components.py @@ -27,7 +27,7 @@ def dfs(graph: dict, vert: int, visited: list) -> list: if not visited[neighbour]: connected_verts += dfs(graph, neighbour, visited) - return [vert] + connected_verts + return [vert, *connected_verts] def connected_components(graph: dict) -> list: diff --git a/graphs/dijkstra_algorithm.py b/graphs/dijkstra_algorithm.py index 1845dad05..452138fe9 100644 --- a/graphs/dijkstra_algorithm.py +++ b/graphs/dijkstra_algorithm.py @@ -112,7 +112,7 @@ class Graph: self.dist[src] = 0 q = PriorityQueue() q.insert((0, src)) # (dist from src, node) - for u in self.adjList.keys(): + for u in self.adjList: if u != src: self.dist[u] = sys.maxsize # Infinity self.par[u] = -1 diff --git a/graphs/edmonds_karp_multiple_source_and_sink.py b/graphs/edmonds_karp_multiple_source_and_sink.py index 070d758e6..d06108041 100644 --- a/graphs/edmonds_karp_multiple_source_and_sink.py +++ b/graphs/edmonds_karp_multiple_source_and_sink.py @@ -163,9 +163,8 @@ class PushRelabelExecutor(MaximumFlowAlgorithmExecutor): self.graph[vertex_index][to_index] - self.preflow[vertex_index][to_index] > 0 - ): - if min_height is None or self.heights[to_index] < min_height: - min_height = self.heights[to_index] + ) and (min_height is None or self.heights[to_index] < min_height): + min_height = self.heights[to_index] if min_height is not None: self.heights[vertex_index] = min_height + 1 diff --git a/graphs/frequent_pattern_graph_miner.py b/graphs/frequent_pattern_graph_miner.py index 87d5605a0..208e57f9b 100644 --- a/graphs/frequent_pattern_graph_miner.py +++ b/graphs/frequent_pattern_graph_miner.py @@ -130,11 +130,11 @@ def create_edge(nodes, graph, cluster, c1): """ create edge between the nodes """ - for i in cluster[c1].keys(): + for i in cluster[c1]: count = 0 c2 = c1 + 1 while c2 < max(cluster.keys()): - for j in cluster[c2].keys(): + for j in cluster[c2]: """ creates edge only if the condition satisfies """ @@ -185,7 +185,7 @@ def find_freq_subgraph_given_support(s, cluster, graph): find edges of multiple frequent subgraphs """ k = int(s / 100 * (len(cluster) - 1)) - for i in cluster[k].keys(): + for i in cluster[k]: my_dfs(graph, tuple(cluster[k][i]), (["Header"],)) diff --git a/graphs/minimum_spanning_tree_boruvka.py b/graphs/minimum_spanning_tree_boruvka.py index 663d8e26c..3c6888037 100644 --- a/graphs/minimum_spanning_tree_boruvka.py +++ b/graphs/minimum_spanning_tree_boruvka.py @@ -144,6 +144,7 @@ class Graph: self.rank[root1] += 1 self.parent[root2] = root1 return root1 + return None @staticmethod def boruvka_mst(graph): diff --git a/graphs/minimum_spanning_tree_prims.py b/graphs/minimum_spanning_tree_prims.py index f577866f0..5a08ec57f 100644 --- a/graphs/minimum_spanning_tree_prims.py +++ b/graphs/minimum_spanning_tree_prims.py @@ -44,10 +44,7 @@ class Heap: temp = position[index] while index != 0: - if index % 2 == 0: - parent = int((index - 2) / 2) - else: - parent = int((index - 1) / 2) + parent = int((index - 2) / 2) if index % 2 == 0 else int((index - 1) / 2) if val < heap[parent]: heap[index] = heap[parent] diff --git a/graphs/minimum_spanning_tree_prims2.py b/graphs/minimum_spanning_tree_prims2.py index 707be783d..81f30ef61 100644 --- a/graphs/minimum_spanning_tree_prims2.py +++ b/graphs/minimum_spanning_tree_prims2.py @@ -135,14 +135,14 @@ class MinPriorityQueue(Generic[T]): # only] curr_pos = self.position_map[elem] if curr_pos == 0: - return + return None parent_position = get_parent_position(curr_pos) _, weight = self.heap[curr_pos] _, parent_weight = self.heap[parent_position] if parent_weight > weight: self._swap_nodes(parent_position, curr_pos) return self._bubble_up(elem) - return + return None def _bubble_down(self, elem: T) -> None: # Place a node at the proper position (downward movement) [to be used @@ -154,24 +154,22 @@ class MinPriorityQueue(Generic[T]): if child_left_position < self.elements and child_right_position < self.elements: _, child_left_weight = self.heap[child_left_position] _, child_right_weight = self.heap[child_right_position] - if child_right_weight < child_left_weight: - if child_right_weight < weight: - self._swap_nodes(child_right_position, curr_pos) - return self._bubble_down(elem) + if child_right_weight < child_left_weight and child_right_weight < weight: + self._swap_nodes(child_right_position, curr_pos) + return self._bubble_down(elem) if child_left_position < self.elements: _, child_left_weight = self.heap[child_left_position] if child_left_weight < weight: self._swap_nodes(child_left_position, curr_pos) return self._bubble_down(elem) else: - return + return None if child_right_position < self.elements: _, child_right_weight = self.heap[child_right_position] if child_right_weight < weight: self._swap_nodes(child_right_position, curr_pos) return self._bubble_down(elem) - else: - return + return None def _swap_nodes(self, node1_pos: int, node2_pos: int) -> None: # Swap the nodes at the given positions diff --git a/hashes/hamming_code.py b/hashes/hamming_code.py index 481a67507..dc9303218 100644 --- a/hashes/hamming_code.py +++ b/hashes/hamming_code.py @@ -126,9 +126,8 @@ def emitter_converter(size_par, data): aux = (bin_pos[cont_loop])[-1 * (bp)] except IndexError: aux = "0" - if aux == "1": - if x == "1": - cont_bo += 1 + if aux == "1" and x == "1": + cont_bo += 1 cont_loop += 1 parity.append(cont_bo % 2) diff --git a/linear_algebra/src/lib.py b/linear_algebra/src/lib.py index ac0398a31..e3556e74c 100644 --- a/linear_algebra/src/lib.py +++ b/linear_algebra/src/lib.py @@ -108,7 +108,7 @@ class Vector: mul implements the scalar multiplication and the dot-product """ - if isinstance(other, float) or isinstance(other, int): + if isinstance(other, (float, int)): ans = [c * other for c in self.__components] return Vector(ans) elif isinstance(other, Vector) and len(self) == len(other): @@ -216,7 +216,7 @@ def axpy(scalar: float, x: Vector, y: Vector) -> Vector: assert ( isinstance(x, Vector) and isinstance(y, Vector) - and (isinstance(scalar, int) or isinstance(scalar, float)) + and (isinstance(scalar, (int, float))) ) return x * scalar + y @@ -337,12 +337,13 @@ class Matrix: "vector must have the same size as the " "number of columns of the matrix!" ) - elif isinstance(other, int) or isinstance(other, float): # matrix-scalar + elif isinstance(other, (int, float)): # matrix-scalar matrix = [ [self.__matrix[i][j] * other for j in range(self.__width)] for i in range(self.__height) ] return Matrix(matrix, self.__width, self.__height) + return None def height(self) -> int: """ diff --git a/machine_learning/gradient_descent.py b/machine_learning/gradient_descent.py index 9fa460a07..5b74dad08 100644 --- a/machine_learning/gradient_descent.py +++ b/machine_learning/gradient_descent.py @@ -55,6 +55,7 @@ def output(example_no, data_set): return train_data[example_no][1] elif data_set == "test": return test_data[example_no][1] + return None def calculate_hypothesis_value(example_no, data_set): @@ -68,6 +69,7 @@ def calculate_hypothesis_value(example_no, data_set): return _hypothesis_value(train_data[example_no][0]) elif data_set == "test": return _hypothesis_value(test_data[example_no][0]) + return None def summation_of_cost_derivative(index, end=m): diff --git a/machine_learning/k_means_clust.py b/machine_learning/k_means_clust.py index b6305469e..7c8142aab 100644 --- a/machine_learning/k_means_clust.py +++ b/machine_learning/k_means_clust.py @@ -229,7 +229,7 @@ def report_generator( """ # Fill missing values with given rules if fill_missing_report: - df.fillna(value=fill_missing_report, inplace=True) + df = df.fillna(value=fill_missing_report) df["dummy"] = 1 numeric_cols = df.select_dtypes(np.number).columns report = ( @@ -338,7 +338,7 @@ def report_generator( ) report.columns.name = "" report = report.reset_index() - report.drop(columns=["index"], inplace=True) + report = report.drop(columns=["index"]) return report diff --git a/machine_learning/sequential_minimum_optimization.py b/machine_learning/sequential_minimum_optimization.py index 9c45c3512..37172c8e9 100644 --- a/machine_learning/sequential_minimum_optimization.py +++ b/machine_learning/sequential_minimum_optimization.py @@ -129,7 +129,7 @@ class SmoSVM: # error self._unbound = [i for i in self._all_samples if self._is_unbound(i)] for s in self.unbound: - if s == i1 or s == i2: + if s in (i1, i2): continue self._error[s] += ( y1 * (a1_new - a1) * k(i1, s) @@ -225,7 +225,7 @@ class SmoSVM: def _choose_alphas(self): locis = yield from self._choose_a1() if not locis: - return + return None return locis def _choose_a1(self): @@ -423,9 +423,8 @@ class Kernel: return np.exp(-1 * (self.gamma * np.linalg.norm(v1 - v2) ** 2)) def _check(self): - if self._kernel == self._rbf: - if self.gamma < 0: - raise ValueError("gamma value must greater than 0") + if self._kernel == self._rbf and self.gamma < 0: + raise ValueError("gamma value must greater than 0") def _get_kernel(self, kernel_name): maps = {"linear": self._linear, "poly": self._polynomial, "rbf": self._rbf} diff --git a/maths/abs.py b/maths/abs.py index cb0ffc8a5..b357e98d8 100644 --- a/maths/abs.py +++ b/maths/abs.py @@ -75,9 +75,9 @@ def test_abs_val(): """ >>> test_abs_val() """ - assert 0 == abs_val(0) - assert 34 == abs_val(34) - assert 100000000000 == abs_val(-100000000000) + assert abs_val(0) == 0 + assert abs_val(34) == 34 + assert abs_val(-100000000000) == 100000000000 a = [-3, -1, 2, -11] assert abs_max(a) == -11 diff --git a/maths/binary_exp_mod.py b/maths/binary_exp_mod.py index 67dd1e728..df688892d 100644 --- a/maths/binary_exp_mod.py +++ b/maths/binary_exp_mod.py @@ -6,7 +6,7 @@ def bin_exp_mod(a, n, b): 7 """ # mod b - assert not (b == 0), "This cannot accept modulo that is == 0" + assert b != 0, "This cannot accept modulo that is == 0" if n == 0: return 1 diff --git a/maths/jaccard_similarity.py b/maths/jaccard_similarity.py index eab25188b..32054414c 100644 --- a/maths/jaccard_similarity.py +++ b/maths/jaccard_similarity.py @@ -71,6 +71,7 @@ def jaccard_similarity(set_a, set_b, alternative_union=False): return len(intersection) / len(union) return len(intersection) / len(union) + return None if __name__ == "__main__": diff --git a/maths/largest_of_very_large_numbers.py b/maths/largest_of_very_large_numbers.py index d2dc0af18..7e7fea004 100644 --- a/maths/largest_of_very_large_numbers.py +++ b/maths/largest_of_very_large_numbers.py @@ -12,6 +12,7 @@ def res(x, y): return 0 elif y == 0: return 1 # any number raised to 0 is 1 + raise AssertionError("This should never happen") if __name__ == "__main__": # Main function diff --git a/maths/radix2_fft.py b/maths/radix2_fft.py index 1def58e1f..af98f24f9 100644 --- a/maths/radix2_fft.py +++ b/maths/radix2_fft.py @@ -80,10 +80,7 @@ class FFT: # Discrete fourier transform of A and B def __dft(self, which): - if which == "A": - dft = [[x] for x in self.polyA] - else: - dft = [[x] for x in self.polyB] + dft = [[x] for x in self.polyA] if which == "A" else [[x] for x in self.polyB] # Corner case if len(dft) <= 1: return dft[0] diff --git a/neural_network/back_propagation_neural_network.py b/neural_network/back_propagation_neural_network.py index cb47b8290..9dd112115 100644 --- a/neural_network/back_propagation_neural_network.py +++ b/neural_network/back_propagation_neural_network.py @@ -153,6 +153,7 @@ class BPNN: if mse < self.accuracy: print("----达到精度----") return mse + return None def cal_loss(self, ydata, ydata_): self.loss = np.sum(np.power((ydata - ydata_), 2)) diff --git a/other/graham_scan.py b/other/graham_scan.py index 8e83bfcf4..2eadb4e56 100644 --- a/other/graham_scan.py +++ b/other/graham_scan.py @@ -125,10 +125,9 @@ def graham_scan(points: list[tuple[int, int]]) -> list[tuple[int, int]]: miny = y minx = x minidx = i - if y == miny: - if x < minx: - minx = x - minidx = i + if y == miny and x < minx: + minx = x + minidx = i # remove the lowest and the most left point from points for preparing for sort points.pop(minidx) diff --git a/other/nested_brackets.py b/other/nested_brackets.py index 3f61a4e70..ea48c0a5f 100644 --- a/other/nested_brackets.py +++ b/other/nested_brackets.py @@ -24,11 +24,10 @@ def is_balanced(s): if s[i] in open_brackets: stack.append(s[i]) - elif s[i] in closed_brackets: - if len(stack) == 0 or ( - len(stack) > 0 and open_to_closed[stack.pop()] != s[i] - ): - return False + elif s[i] in closed_brackets and ( + len(stack) == 0 or (len(stack) > 0 and open_to_closed[stack.pop()] != s[i]) + ): + return False return len(stack) == 0 diff --git a/physics/hubble_parameter.py b/physics/hubble_parameter.py index 6bc62e713..f7b2d28a6 100644 --- a/physics/hubble_parameter.py +++ b/physics/hubble_parameter.py @@ -70,10 +70,10 @@ def hubble_parameter( 68.3 """ parameters = [redshift, radiation_density, matter_density, dark_energy] - if any(0 > p for p in parameters): + if any(p < 0 for p in parameters): raise ValueError("All input parameters must be positive") - if any(1 < p for p in parameters[1:4]): + if any(p > 1 for p in parameters[1:4]): raise ValueError("Relative densities cannot be greater than one") else: curvature = 1 - (matter_density + radiation_density + dark_energy) diff --git a/project_euler/problem_005/sol1.py b/project_euler/problem_005/sol1.py index f272c102d..01cbd0e15 100644 --- a/project_euler/problem_005/sol1.py +++ b/project_euler/problem_005/sol1.py @@ -63,6 +63,7 @@ def solution(n: int = 20) -> int: if i == 0: i = 1 return i + return None if __name__ == "__main__": diff --git a/project_euler/problem_009/sol1.py b/project_euler/problem_009/sol1.py index 1d908402b..e65c9b857 100644 --- a/project_euler/problem_009/sol1.py +++ b/project_euler/problem_009/sol1.py @@ -32,9 +32,8 @@ def solution() -> int: for a in range(300): for b in range(a + 1, 400): for c in range(b + 1, 500): - if (a + b + c) == 1000: - if (a**2) + (b**2) == (c**2): - return a * b * c + if (a + b + c) == 1000 and (a**2) + (b**2) == (c**2): + return a * b * c return -1 diff --git a/project_euler/problem_014/sol2.py b/project_euler/problem_014/sol2.py index d2a1d9f0e..2448e652c 100644 --- a/project_euler/problem_014/sol2.py +++ b/project_euler/problem_014/sol2.py @@ -34,10 +34,7 @@ def collatz_sequence_length(n: int) -> int: """Returns the Collatz sequence length for n.""" if n in COLLATZ_SEQUENCE_LENGTHS: return COLLATZ_SEQUENCE_LENGTHS[n] - if n % 2 == 0: - next_n = n // 2 - else: - next_n = 3 * n + 1 + next_n = n // 2 if n % 2 == 0 else 3 * n + 1 sequence_length = collatz_sequence_length(next_n) + 1 COLLATZ_SEQUENCE_LENGTHS[n] = sequence_length return sequence_length diff --git a/project_euler/problem_018/solution.py b/project_euler/problem_018/solution.py index 82fc3ce3c..70306148b 100644 --- a/project_euler/problem_018/solution.py +++ b/project_euler/problem_018/solution.py @@ -48,14 +48,8 @@ def solution(): for i in range(1, len(a)): for j in range(len(a[i])): - if j != len(a[i - 1]): - number1 = a[i - 1][j] - else: - number1 = 0 - if j > 0: - number2 = a[i - 1][j - 1] - else: - number2 = 0 + number1 = a[i - 1][j] if j != len(a[i - 1]) else 0 + number2 = a[i - 1][j - 1] if j > 0 else 0 a[i][j] += max(number1, number2) return max(a[-1]) diff --git a/project_euler/problem_019/sol1.py b/project_euler/problem_019/sol1.py index ab5936584..0e38137d4 100644 --- a/project_euler/problem_019/sol1.py +++ b/project_euler/problem_019/sol1.py @@ -39,7 +39,7 @@ def solution(): while year < 2001: day += 7 - if (year % 4 == 0 and not year % 100 == 0) or (year % 400 == 0): + if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0): if day > days_per_month[month - 1] and month != 2: month += 1 day = day - days_per_month[month - 2] diff --git a/project_euler/problem_033/sol1.py b/project_euler/problem_033/sol1.py index e0c9a058a..32be424b6 100644 --- a/project_euler/problem_033/sol1.py +++ b/project_euler/problem_033/sol1.py @@ -20,11 +20,9 @@ from fractions import Fraction def is_digit_cancelling(num: int, den: int) -> bool: - if num != den: - if num % 10 == den // 10: - if (num // 10) / (den % 10) == num / den: - return True - return False + return ( + num != den and num % 10 == den // 10 and (num // 10) / (den % 10) == num / den + ) def fraction_list(digit_len: int) -> list[str]: diff --git a/project_euler/problem_064/sol1.py b/project_euler/problem_064/sol1.py index 81ebcc7b7..12769decc 100644 --- a/project_euler/problem_064/sol1.py +++ b/project_euler/problem_064/sol1.py @@ -67,9 +67,8 @@ def solution(n: int = 10000) -> int: count_odd_periods = 0 for i in range(2, n + 1): sr = sqrt(i) - if sr - floor(sr) != 0: - if continuous_fraction_period(i) % 2 == 1: - count_odd_periods += 1 + if sr - floor(sr) != 0 and continuous_fraction_period(i) % 2 == 1: + count_odd_periods += 1 return count_odd_periods diff --git a/project_euler/problem_067/sol1.py b/project_euler/problem_067/sol1.py index f20c206cc..2b41fedc6 100644 --- a/project_euler/problem_067/sol1.py +++ b/project_euler/problem_067/sol1.py @@ -37,14 +37,8 @@ def solution(): for i in range(1, len(a)): for j in range(len(a[i])): - if j != len(a[i - 1]): - number1 = a[i - 1][j] - else: - number1 = 0 - if j > 0: - number2 = a[i - 1][j - 1] - else: - number2 = 0 + number1 = a[i - 1][j] if j != len(a[i - 1]) else 0 + number2 = a[i - 1][j - 1] if j > 0 else 0 a[i][j] += max(number1, number2) return max(a[-1]) diff --git a/project_euler/problem_109/sol1.py b/project_euler/problem_109/sol1.py index 852f001d3..ef145dda5 100644 --- a/project_euler/problem_109/sol1.py +++ b/project_euler/problem_109/sol1.py @@ -65,7 +65,7 @@ def solution(limit: int = 100) -> int: >>> solution(50) 12577 """ - singles: list[int] = list(range(1, 21)) + [25] + singles: list[int] = [*list(range(1, 21)), 25] doubles: list[int] = [2 * x for x in range(1, 21)] + [50] triples: list[int] = [3 * x for x in range(1, 21)] all_values: list[int] = singles + doubles + triples + [0] diff --git a/project_euler/problem_203/sol1.py b/project_euler/problem_203/sol1.py index 713b530b6..da9436246 100644 --- a/project_euler/problem_203/sol1.py +++ b/project_euler/problem_203/sol1.py @@ -50,8 +50,8 @@ def get_pascal_triangle_unique_coefficients(depth: int) -> set[int]: coefficients = {1} previous_coefficients = [1] for _ in range(2, depth + 1): - coefficients_begins_one = previous_coefficients + [0] - coefficients_ends_one = [0] + previous_coefficients + coefficients_begins_one = [*previous_coefficients, 0] + coefficients_ends_one = [0, *previous_coefficients] previous_coefficients = [] for x, y in zip(coefficients_begins_one, coefficients_ends_one): coefficients.add(x + y) diff --git a/scheduling/shortest_job_first.py b/scheduling/shortest_job_first.py index b3f81bfd1..871de8207 100644 --- a/scheduling/shortest_job_first.py +++ b/scheduling/shortest_job_first.py @@ -36,12 +36,11 @@ def calculate_waitingtime( # Process until all processes are completed while complete != no_of_processes: for j in range(no_of_processes): - if arrival_time[j] <= increment_time: - if remaining_time[j] > 0: - if remaining_time[j] < minm: - minm = remaining_time[j] - short = j - check = True + if arrival_time[j] <= increment_time and remaining_time[j] > 0: + if remaining_time[j] < minm: + minm = remaining_time[j] + short = j + check = True if not check: increment_time += 1 diff --git a/scripts/build_directory_md.py b/scripts/build_directory_md.py index 7572ce342..b95be9ebc 100755 --- a/scripts/build_directory_md.py +++ b/scripts/build_directory_md.py @@ -21,9 +21,8 @@ def md_prefix(i): def print_path(old_path: str, new_path: str) -> str: old_parts = old_path.split(os.sep) for i, new_part in enumerate(new_path.split(os.sep)): - if i + 1 > len(old_parts) or old_parts[i] != new_part: - if new_part: - print(f"{md_prefix(i)} {new_part.replace('_', ' ').title()}") + if (i + 1 > len(old_parts) or old_parts[i] != new_part) and new_part: + print(f"{md_prefix(i)} {new_part.replace('_', ' ').title()}") return new_path diff --git a/searches/binary_tree_traversal.py b/searches/binary_tree_traversal.py index 66814b478..76e80df25 100644 --- a/searches/binary_tree_traversal.py +++ b/searches/binary_tree_traversal.py @@ -37,6 +37,7 @@ def build_tree(): right_node = TreeNode(int(check)) node_found.right = right_node q.put(right_node) + return None def pre_order(node: TreeNode) -> None: diff --git a/sorts/circle_sort.py b/sorts/circle_sort.py index da3c59059..271fa1e8d 100644 --- a/sorts/circle_sort.py +++ b/sorts/circle_sort.py @@ -58,14 +58,13 @@ def circle_sort(collection: list) -> list: left += 1 right -= 1 - if left == right: - if collection[left] > collection[right + 1]: - collection[left], collection[right + 1] = ( - collection[right + 1], - collection[left], - ) + if left == right and collection[left] > collection[right + 1]: + collection[left], collection[right + 1] = ( + collection[right + 1], + collection[left], + ) - swapped = True + swapped = True mid = low + int((high - low) / 2) left_swap = circle_sort_util(collection, low, mid) diff --git a/sorts/counting_sort.py b/sorts/counting_sort.py index 892ec5d5f..18c4b0323 100644 --- a/sorts/counting_sort.py +++ b/sorts/counting_sort.py @@ -66,7 +66,7 @@ def counting_sort_string(string): if __name__ == "__main__": # Test string sort - assert "eghhiiinrsssttt" == counting_sort_string("thisisthestring") + assert counting_sort_string("thisisthestring") == "eghhiiinrsssttt" user_input = input("Enter numbers separated by a comma:\n").strip() unsorted = [int(item) for item in user_input.split(",")] diff --git a/sorts/msd_radix_sort.py b/sorts/msd_radix_sort.py index 74ce21762..03f84c75b 100644 --- a/sorts/msd_radix_sort.py +++ b/sorts/msd_radix_sort.py @@ -147,7 +147,7 @@ def _msd_radix_sort_inplace( list_of_ints[i], list_of_ints[j] = list_of_ints[j], list_of_ints[i] j -= 1 - if not j == i: + if j != i: i += 1 _msd_radix_sort_inplace(list_of_ints, bit_position, begin_index, i) diff --git a/sorts/quick_sort.py b/sorts/quick_sort.py index 70cd19d7a..b79d3eac3 100644 --- a/sorts/quick_sort.py +++ b/sorts/quick_sort.py @@ -39,7 +39,7 @@ def quick_sort(collection: list) -> list: for element in collection[pivot_index + 1 :]: (greater if element > pivot else lesser).append(element) - return quick_sort(lesser) + [pivot] + quick_sort(greater) + return [*quick_sort(lesser), pivot, *quick_sort(greater)] if __name__ == "__main__": diff --git a/sorts/recursive_quick_sort.py b/sorts/recursive_quick_sort.py index c28a14e37..c29009aca 100644 --- a/sorts/recursive_quick_sort.py +++ b/sorts/recursive_quick_sort.py @@ -9,11 +9,11 @@ def quick_sort(data: list) -> list: if len(data) <= 1: return data else: - return ( - quick_sort([e for e in data[1:] if e <= data[0]]) - + [data[0]] - + quick_sort([e for e in data[1:] if e > data[0]]) - ) + return [ + *quick_sort([e for e in data[1:] if e <= data[0]]), + data[0], + *quick_sort([e for e in data[1:] if e > data[0]]), + ] if __name__ == "__main__": diff --git a/sorts/tim_sort.py b/sorts/tim_sort.py index c90c7e803..138f11c71 100644 --- a/sorts/tim_sort.py +++ b/sorts/tim_sort.py @@ -32,9 +32,9 @@ def merge(left, right): return left if left[0] < right[0]: - return [left[0]] + merge(left[1:], right) + return [left[0], *merge(left[1:], right)] - return [right[0]] + merge(left, right[1:]) + return [right[0], *merge(left, right[1:])] def tim_sort(lst): diff --git a/strings/autocomplete_using_trie.py b/strings/autocomplete_using_trie.py index 758260292..77a3050ab 100644 --- a/strings/autocomplete_using_trie.py +++ b/strings/autocomplete_using_trie.py @@ -27,10 +27,7 @@ class Trie: def _elements(self, d: dict) -> tuple: result = [] for c, v in d.items(): - if c == END: - sub_result = [" "] - else: - sub_result = [c + s for s in self._elements(v)] + sub_result = [" "] if c == END else [(c + s) for s in self._elements(v)] result.extend(sub_result) return tuple(result) diff --git a/strings/check_anagrams.py b/strings/check_anagrams.py index 0d2f8091a..a364b9821 100644 --- a/strings/check_anagrams.py +++ b/strings/check_anagrams.py @@ -38,10 +38,7 @@ def check_anagrams(first_str: str, second_str: str) -> bool: count[first_str[i]] += 1 count[second_str[i]] -= 1 - for _count in count.values(): - if _count != 0: - return False - return True + return all(_count == 0 for _count in count.values()) if __name__ == "__main__": diff --git a/strings/is_palindrome.py b/strings/is_palindrome.py index 9bf2abd98..406aa2e8d 100644 --- a/strings/is_palindrome.py +++ b/strings/is_palindrome.py @@ -30,10 +30,7 @@ def is_palindrome(s: str) -> bool: # with the help of 1st index (i==n-i-1) # where n is length of string - for i in range(end): - if s[i] != s[n - i - 1]: - return False - return True + return all(s[i] == s[n - i - 1] for i in range(end)) if __name__ == "__main__": diff --git a/strings/snake_case_to_camel_pascal_case.py b/strings/snake_case_to_camel_pascal_case.py index eaabdcb87..28a28b517 100644 --- a/strings/snake_case_to_camel_pascal_case.py +++ b/strings/snake_case_to_camel_pascal_case.py @@ -43,7 +43,7 @@ def snake_to_camel_case(input_str: str, use_pascal: bool = False) -> str: initial_word = "" if use_pascal else words[0] - return "".join([initial_word] + capitalized_words) + return "".join([initial_word, *capitalized_words]) if __name__ == "__main__": diff --git a/web_programming/convert_number_to_words.py b/web_programming/convert_number_to_words.py index 50612dec2..1e293df96 100644 --- a/web_programming/convert_number_to_words.py +++ b/web_programming/convert_number_to_words.py @@ -63,7 +63,7 @@ def convert(number: int) -> str: current = temp_num % 10 if counter % 2 == 0: addition = "" - if counter in placevalue.keys() and current != 0: + if counter in placevalue and current != 0: addition = placevalue[counter] if counter == 2: words = singles[current] + addition + words @@ -84,12 +84,12 @@ def convert(number: int) -> str: words = teens[number % 10] + words else: addition = "" - if counter in placevalue.keys(): + if counter in placevalue: addition = placevalue[counter] words = doubles[current] + addition + words else: addition = "" - if counter in placevalue.keys(): + if counter in placevalue: if current == 0 and ((temp_num % 100) // 10) == 0: addition = "" else: diff --git a/web_programming/instagram_crawler.py b/web_programming/instagram_crawler.py index 4536257a9..0816cd181 100644 --- a/web_programming/instagram_crawler.py +++ b/web_programming/instagram_crawler.py @@ -105,7 +105,7 @@ def test_instagram_user(username: str = "github") -> None: import os if os.environ.get("CI"): - return None # test failing on GitHub Actions + return # test failing on GitHub Actions instagram_user = InstagramUser(username) assert instagram_user.user_data assert isinstance(instagram_user.user_data, dict) diff --git a/web_programming/open_google_results.py b/web_programming/open_google_results.py index 2685bf621..f61e3666d 100644 --- a/web_programming/open_google_results.py +++ b/web_programming/open_google_results.py @@ -7,10 +7,7 @@ from bs4 import BeautifulSoup from fake_useragent import UserAgent if __name__ == "__main__": - if len(argv) > 1: - query = "%20".join(argv[1:]) - else: - query = quote(str(input("Search: "))) + query = "%20".join(argv[1:]) if len(argv) > 1 else quote(str(input("Search: "))) print("Googling.....") From 069a14b1c55112bc4f4e08571fc3c2156bb69e5a Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Thu, 2 Mar 2023 07:55:47 +0300 Subject: [PATCH 590/726] Add Project Euler problem 082 solution 1 (#6282) Update DIRECTORY.md --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 2 + project_euler/problem_082/__init__.py | 0 project_euler/problem_082/input.txt | 80 +++++++++++++++++++++++ project_euler/problem_082/sol1.py | 65 ++++++++++++++++++ project_euler/problem_082/test_matrix.txt | 5 ++ 5 files changed, 152 insertions(+) create mode 100644 project_euler/problem_082/__init__.py create mode 100644 project_euler/problem_082/input.txt create mode 100644 project_euler/problem_082/sol1.py create mode 100644 project_euler/problem_082/test_matrix.txt diff --git a/DIRECTORY.md b/DIRECTORY.md index a8786cc25..3d1bc967e 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -918,6 +918,8 @@ * [Sol1](project_euler/problem_080/sol1.py) * Problem 081 * [Sol1](project_euler/problem_081/sol1.py) + * Problem 082 + * [Sol1](project_euler/problem_082/sol1.py) * Problem 085 * [Sol1](project_euler/problem_085/sol1.py) * Problem 086 diff --git a/project_euler/problem_082/__init__.py b/project_euler/problem_082/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_082/input.txt b/project_euler/problem_082/input.txt new file mode 100644 index 000000000..f65322a7e --- /dev/null +++ b/project_euler/problem_082/input.txt @@ -0,0 +1,80 @@ +4445,2697,5115,718,2209,2212,654,4348,3079,6821,7668,3276,8874,4190,3785,2752,9473,7817,9137,496,7338,3434,7152,4355,4552,7917,7827,2460,2350,691,3514,5880,3145,7633,7199,3783,5066,7487,3285,1084,8985,760,872,8609,8051,1134,9536,5750,9716,9371,7619,5617,275,9721,2997,2698,1887,8825,6372,3014,2113,7122,7050,6775,5948,2758,1219,3539,348,7989,2735,9862,1263,8089,6401,9462,3168,2758,3748,5870 +1096,20,1318,7586,5167,2642,1443,5741,7621,7030,5526,4244,2348,4641,9827,2448,6918,5883,3737,300,7116,6531,567,5997,3971,6623,820,6148,3287,1874,7981,8424,7672,7575,6797,6717,1078,5008,4051,8795,5820,346,1851,6463,2117,6058,3407,8211,117,4822,1317,4377,4434,5925,8341,4800,1175,4173,690,8978,7470,1295,3799,8724,3509,9849,618,3320,7068,9633,2384,7175,544,6583,1908,9983,481,4187,9353,9377 +9607,7385,521,6084,1364,8983,7623,1585,6935,8551,2574,8267,4781,3834,2764,2084,2669,4656,9343,7709,2203,9328,8004,6192,5856,3555,2260,5118,6504,1839,9227,1259,9451,1388,7909,5733,6968,8519,9973,1663,5315,7571,3035,4325,4283,2304,6438,3815,9213,9806,9536,196,5542,6907,2475,1159,5820,9075,9470,2179,9248,1828,4592,9167,3713,4640,47,3637,309,7344,6955,346,378,9044,8635,7466,5036,9515,6385,9230 +7206,3114,7760,1094,6150,5182,7358,7387,4497,955,101,1478,7777,6966,7010,8417,6453,4955,3496,107,449,8271,131,2948,6185,784,5937,8001,6104,8282,4165,3642,710,2390,575,715,3089,6964,4217,192,5949,7006,715,3328,1152,66,8044,4319,1735,146,4818,5456,6451,4113,1063,4781,6799,602,1504,6245,6550,1417,1343,2363,3785,5448,4545,9371,5420,5068,4613,4882,4241,5043,7873,8042,8434,3939,9256,2187 +3620,8024,577,9997,7377,7682,1314,1158,6282,6310,1896,2509,5436,1732,9480,706,496,101,6232,7375,2207,2306,110,6772,3433,2878,8140,5933,8688,1399,2210,7332,6172,6403,7333,4044,2291,1790,2446,7390,8698,5723,3678,7104,1825,2040,140,3982,4905,4160,2200,5041,2512,1488,2268,1175,7588,8321,8078,7312,977,5257,8465,5068,3453,3096,1651,7906,253,9250,6021,8791,8109,6651,3412,345,4778,5152,4883,7505 +1074,5438,9008,2679,5397,5429,2652,3403,770,9188,4248,2493,4361,8327,9587,707,9525,5913,93,1899,328,2876,3604,673,8576,6908,7659,2544,3359,3883,5273,6587,3065,1749,3223,604,9925,6941,2823,8767,7039,3290,3214,1787,7904,3421,7137,9560,8451,2669,9219,6332,1576,5477,6755,8348,4164,4307,2984,4012,6629,1044,2874,6541,4942,903,1404,9125,5160,8836,4345,2581,460,8438,1538,5507,668,3352,2678,6942 +4295,1176,5596,1521,3061,9868,7037,7129,8933,6659,5947,5063,3653,9447,9245,2679,767,714,116,8558,163,3927,8779,158,5093,2447,5782,3967,1716,931,7772,8164,1117,9244,5783,7776,3846,8862,6014,2330,6947,1777,3112,6008,3491,1906,5952,314,4602,8994,5919,9214,3995,5026,7688,6809,5003,3128,2509,7477,110,8971,3982,8539,2980,4689,6343,5411,2992,5270,5247,9260,2269,7474,1042,7162,5206,1232,4556,4757 +510,3556,5377,1406,5721,4946,2635,7847,4251,8293,8281,6351,4912,287,2870,3380,3948,5322,3840,4738,9563,1906,6298,3234,8959,1562,6297,8835,7861,239,6618,1322,2553,2213,5053,5446,4402,6500,5182,8585,6900,5756,9661,903,5186,7687,5998,7997,8081,8955,4835,6069,2621,1581,732,9564,1082,1853,5442,1342,520,1737,3703,5321,4793,2776,1508,1647,9101,2499,6891,4336,7012,3329,3212,1442,9993,3988,4930,7706 +9444,3401,5891,9716,1228,7107,109,3563,2700,6161,5039,4992,2242,8541,7372,2067,1294,3058,1306,320,8881,5756,9326,411,8650,8824,5495,8282,8397,2000,1228,7817,2099,6473,3571,5994,4447,1299,5991,543,7874,2297,1651,101,2093,3463,9189,6872,6118,872,1008,1779,2805,9084,4048,2123,5877,55,3075,1737,9459,4535,6453,3644,108,5982,4437,5213,1340,6967,9943,5815,669,8074,1838,6979,9132,9315,715,5048 +3327,4030,7177,6336,9933,5296,2621,4785,2755,4832,2512,2118,2244,4407,2170,499,7532,9742,5051,7687,970,6924,3527,4694,5145,1306,2165,5940,2425,8910,3513,1909,6983,346,6377,4304,9330,7203,6605,3709,3346,970,369,9737,5811,4427,9939,3693,8436,5566,1977,3728,2399,3985,8303,2492,5366,9802,9193,7296,1033,5060,9144,2766,1151,7629,5169,5995,58,7619,7565,4208,1713,6279,3209,4908,9224,7409,1325,8540 +6882,1265,1775,3648,4690,959,5837,4520,5394,1378,9485,1360,4018,578,9174,2932,9890,3696,116,1723,1178,9355,7063,1594,1918,8574,7594,7942,1547,6166,7888,354,6932,4651,1010,7759,6905,661,7689,6092,9292,3845,9605,8443,443,8275,5163,7720,7265,6356,7779,1798,1754,5225,6661,1180,8024,5666,88,9153,1840,3508,1193,4445,2648,3538,6243,6375,8107,5902,5423,2520,1122,5015,6113,8859,9370,966,8673,2442 +7338,3423,4723,6533,848,8041,7921,8277,4094,5368,7252,8852,9166,2250,2801,6125,8093,5738,4038,9808,7359,9494,601,9116,4946,2702,5573,2921,9862,1462,1269,2410,4171,2709,7508,6241,7522,615,2407,8200,4189,5492,5649,7353,2590,5203,4274,710,7329,9063,956,8371,3722,4253,4785,1194,4828,4717,4548,940,983,2575,4511,2938,1827,2027,2700,1236,841,5760,1680,6260,2373,3851,1841,4968,1172,5179,7175,3509 +4420,1327,3560,2376,6260,2988,9537,4064,4829,8872,9598,3228,1792,7118,9962,9336,4368,9189,6857,1829,9863,6287,7303,7769,2707,8257,2391,2009,3975,4993,3068,9835,3427,341,8412,2134,4034,8511,6421,3041,9012,2983,7289,100,1355,7904,9186,6920,5856,2008,6545,8331,3655,5011,839,8041,9255,6524,3862,8788,62,7455,3513,5003,8413,3918,2076,7960,6108,3638,6999,3436,1441,4858,4181,1866,8731,7745,3744,1000 +356,8296,8325,1058,1277,4743,3850,2388,6079,6462,2815,5620,8495,5378,75,4324,3441,9870,1113,165,1544,1179,2834,562,6176,2313,6836,8839,2986,9454,5199,6888,1927,5866,8760,320,1792,8296,7898,6121,7241,5886,5814,2815,8336,1576,4314,3109,2572,6011,2086,9061,9403,3947,5487,9731,7281,3159,1819,1334,3181,5844,5114,9898,4634,2531,4412,6430,4262,8482,4546,4555,6804,2607,9421,686,8649,8860,7794,6672 +9870,152,1558,4963,8750,4754,6521,6256,8818,5208,5691,9659,8377,9725,5050,5343,2539,6101,1844,9700,7750,8114,5357,3001,8830,4438,199,9545,8496,43,2078,327,9397,106,6090,8181,8646,6414,7499,5450,4850,6273,5014,4131,7639,3913,6571,8534,9703,4391,7618,445,1320,5,1894,6771,7383,9191,4708,9706,6939,7937,8726,9382,5216,3685,2247,9029,8154,1738,9984,2626,9438,4167,6351,5060,29,1218,1239,4785 +192,5213,8297,8974,4032,6966,5717,1179,6523,4679,9513,1481,3041,5355,9303,9154,1389,8702,6589,7818,6336,3539,5538,3094,6646,6702,6266,2759,4608,4452,617,9406,8064,6379,444,5602,4950,1810,8391,1536,316,8714,1178,5182,5863,5110,5372,4954,1978,2971,5680,4863,2255,4630,5723,2168,538,1692,1319,7540,440,6430,6266,7712,7385,5702,620,641,3136,7350,1478,3155,2820,9109,6261,1122,4470,14,8493,2095 +1046,4301,6082,474,4974,7822,2102,5161,5172,6946,8074,9716,6586,9962,9749,5015,2217,995,5388,4402,7652,6399,6539,1349,8101,3677,1328,9612,7922,2879,231,5887,2655,508,4357,4964,3554,5930,6236,7384,4614,280,3093,9600,2110,7863,2631,6626,6620,68,1311,7198,7561,1768,5139,1431,221,230,2940,968,5283,6517,2146,1646,869,9402,7068,8645,7058,1765,9690,4152,2926,9504,2939,7504,6074,2944,6470,7859 +4659,736,4951,9344,1927,6271,8837,8711,3241,6579,7660,5499,5616,3743,5801,4682,9748,8796,779,1833,4549,8138,4026,775,4170,2432,4174,3741,7540,8017,2833,4027,396,811,2871,1150,9809,2719,9199,8504,1224,540,2051,3519,7982,7367,2761,308,3358,6505,2050,4836,5090,7864,805,2566,2409,6876,3361,8622,5572,5895,3280,441,7893,8105,1634,2929,274,3926,7786,6123,8233,9921,2674,5340,1445,203,4585,3837 +5759,338,7444,7968,7742,3755,1591,4839,1705,650,7061,2461,9230,9391,9373,2413,1213,431,7801,4994,2380,2703,6161,6878,8331,2538,6093,1275,5065,5062,2839,582,1014,8109,3525,1544,1569,8622,7944,2905,6120,1564,1839,5570,7579,1318,2677,5257,4418,5601,7935,7656,5192,1864,5886,6083,5580,6202,8869,1636,7907,4759,9082,5854,3185,7631,6854,5872,5632,5280,1431,2077,9717,7431,4256,8261,9680,4487,4752,4286 +1571,1428,8599,1230,7772,4221,8523,9049,4042,8726,7567,6736,9033,2104,4879,4967,6334,6716,3994,1269,8995,6539,3610,7667,6560,6065,874,848,4597,1711,7161,4811,6734,5723,6356,6026,9183,2586,5636,1092,7779,7923,8747,6887,7505,9909,1792,3233,4526,3176,1508,8043,720,5212,6046,4988,709,5277,8256,3642,1391,5803,1468,2145,3970,6301,7767,2359,8487,9771,8785,7520,856,1605,8972,2402,2386,991,1383,5963 +1822,4824,5957,6511,9868,4113,301,9353,6228,2881,2966,6956,9124,9574,9233,1601,7340,973,9396,540,4747,8590,9535,3650,7333,7583,4806,3593,2738,8157,5215,8472,2284,9473,3906,6982,5505,6053,7936,6074,7179,6688,1564,1103,6860,5839,2022,8490,910,7551,7805,881,7024,1855,9448,4790,1274,3672,2810,774,7623,4223,4850,6071,9975,4935,1915,9771,6690,3846,517,463,7624,4511,614,6394,3661,7409,1395,8127 +8738,3850,9555,3695,4383,2378,87,6256,6740,7682,9546,4255,6105,2000,1851,4073,8957,9022,6547,5189,2487,303,9602,7833,1628,4163,6678,3144,8589,7096,8913,5823,4890,7679,1212,9294,5884,2972,3012,3359,7794,7428,1579,4350,7246,4301,7779,7790,3294,9547,4367,3549,1958,8237,6758,3497,3250,3456,6318,1663,708,7714,6143,6890,3428,6853,9334,7992,591,6449,9786,1412,8500,722,5468,1371,108,3939,4199,2535 +7047,4323,1934,5163,4166,461,3544,2767,6554,203,6098,2265,9078,2075,4644,6641,8412,9183,487,101,7566,5622,1975,5726,2920,5374,7779,5631,3753,3725,2672,3621,4280,1162,5812,345,8173,9785,1525,955,5603,2215,2580,5261,2765,2990,5979,389,3907,2484,1232,5933,5871,3304,1138,1616,5114,9199,5072,7442,7245,6472,4760,6359,9053,7876,2564,9404,3043,9026,2261,3374,4460,7306,2326,966,828,3274,1712,3446 +3975,4565,8131,5800,4570,2306,8838,4392,9147,11,3911,7118,9645,4994,2028,6062,5431,2279,8752,2658,7836,994,7316,5336,7185,3289,1898,9689,2331,5737,3403,1124,2679,3241,7748,16,2724,5441,6640,9368,9081,5618,858,4969,17,2103,6035,8043,7475,2181,939,415,1617,8500,8253,2155,7843,7974,7859,1746,6336,3193,2617,8736,4079,6324,6645,8891,9396,5522,6103,1857,8979,3835,2475,1310,7422,610,8345,7615 +9248,5397,5686,2988,3446,4359,6634,9141,497,9176,6773,7448,1907,8454,916,1596,2241,1626,1384,2741,3649,5362,8791,7170,2903,2475,5325,6451,924,3328,522,90,4813,9737,9557,691,2388,1383,4021,1609,9206,4707,5200,7107,8104,4333,9860,5013,1224,6959,8527,1877,4545,7772,6268,621,4915,9349,5970,706,9583,3071,4127,780,8231,3017,9114,3836,7503,2383,1977,4870,8035,2379,9704,1037,3992,3642,1016,4303 +5093,138,4639,6609,1146,5565,95,7521,9077,2272,974,4388,2465,2650,722,4998,3567,3047,921,2736,7855,173,2065,4238,1048,5,6847,9548,8632,9194,5942,4777,7910,8971,6279,7253,2516,1555,1833,3184,9453,9053,6897,7808,8629,4877,1871,8055,4881,7639,1537,7701,2508,7564,5845,5023,2304,5396,3193,2955,1088,3801,6203,1748,3737,1276,13,4120,7715,8552,3047,2921,106,7508,304,1280,7140,2567,9135,5266 +6237,4607,7527,9047,522,7371,4883,2540,5867,6366,5301,1570,421,276,3361,527,6637,4861,2401,7522,5808,9371,5298,2045,5096,5447,7755,5115,7060,8529,4078,1943,1697,1764,5453,7085,960,2405,739,2100,5800,728,9737,5704,5693,1431,8979,6428,673,7540,6,7773,5857,6823,150,5869,8486,684,5816,9626,7451,5579,8260,3397,5322,6920,1879,2127,2884,5478,4977,9016,6165,6292,3062,5671,5968,78,4619,4763 +9905,7127,9390,5185,6923,3721,9164,9705,4341,1031,1046,5127,7376,6528,3248,4941,1178,7889,3364,4486,5358,9402,9158,8600,1025,874,1839,1783,309,9030,1843,845,8398,1433,7118,70,8071,2877,3904,8866,6722,4299,10,1929,5897,4188,600,1889,3325,2485,6473,4474,7444,6992,4846,6166,4441,2283,2629,4352,7775,1101,2214,9985,215,8270,9750,2740,8361,7103,5930,8664,9690,8302,9267,344,2077,1372,1880,9550 +5825,8517,7769,2405,8204,1060,3603,7025,478,8334,1997,3692,7433,9101,7294,7498,9415,5452,3850,3508,6857,9213,6807,4412,7310,854,5384,686,4978,892,8651,3241,2743,3801,3813,8588,6701,4416,6990,6490,3197,6838,6503,114,8343,5844,8646,8694,65,791,5979,2687,2621,2019,8097,1423,3644,9764,4921,3266,3662,5561,2476,8271,8138,6147,1168,3340,1998,9874,6572,9873,6659,5609,2711,3931,9567,4143,7833,8887 +6223,2099,2700,589,4716,8333,1362,5007,2753,2848,4441,8397,7192,8191,4916,9955,6076,3370,6396,6971,3156,248,3911,2488,4930,2458,7183,5455,170,6809,6417,3390,1956,7188,577,7526,2203,968,8164,479,8699,7915,507,6393,4632,1597,7534,3604,618,3280,6061,9793,9238,8347,568,9645,2070,5198,6482,5000,9212,6655,5961,7513,1323,3872,6170,3812,4146,2736,67,3151,5548,2781,9679,7564,5043,8587,1893,4531 +5826,3690,6724,2121,9308,6986,8106,6659,2142,1642,7170,2877,5757,6494,8026,6571,8387,9961,6043,9758,9607,6450,8631,8334,7359,5256,8523,2225,7487,1977,9555,8048,5763,2414,4948,4265,2427,8978,8088,8841,9208,9601,5810,9398,8866,9138,4176,5875,7212,3272,6759,5678,7649,4922,5422,1343,8197,3154,3600,687,1028,4579,2084,9467,4492,7262,7296,6538,7657,7134,2077,1505,7332,6890,8964,4879,7603,7400,5973,739 +1861,1613,4879,1884,7334,966,2000,7489,2123,4287,1472,3263,4726,9203,1040,4103,6075,6049,330,9253,4062,4268,1635,9960,577,1320,3195,9628,1030,4092,4979,6474,6393,2799,6967,8687,7724,7392,9927,2085,3200,6466,8702,265,7646,8665,7986,7266,4574,6587,612,2724,704,3191,8323,9523,3002,704,5064,3960,8209,2027,2758,8393,4875,4641,9584,6401,7883,7014,768,443,5490,7506,1852,2005,8850,5776,4487,4269 +4052,6687,4705,7260,6645,6715,3706,5504,8672,2853,1136,8187,8203,4016,871,1809,1366,4952,9294,5339,6872,2645,6083,7874,3056,5218,7485,8796,7401,3348,2103,426,8572,4163,9171,3176,948,7654,9344,3217,1650,5580,7971,2622,76,2874,880,2034,9929,1546,2659,5811,3754,7096,7436,9694,9960,7415,2164,953,2360,4194,2397,1047,2196,6827,575,784,2675,8821,6802,7972,5996,6699,2134,7577,2887,1412,4349,4380 +4629,2234,6240,8132,7592,3181,6389,1214,266,1910,2451,8784,2790,1127,6932,1447,8986,2492,5476,397,889,3027,7641,5083,5776,4022,185,3364,5701,2442,2840,4160,9525,4828,6602,2614,7447,3711,4505,7745,8034,6514,4907,2605,7753,6958,7270,6936,3006,8968,439,2326,4652,3085,3425,9863,5049,5361,8688,297,7580,8777,7916,6687,8683,7141,306,9569,2384,1500,3346,4601,7329,9040,6097,2727,6314,4501,4974,2829 +8316,4072,2025,6884,3027,1808,5714,7624,7880,8528,4205,8686,7587,3230,1139,7273,6163,6986,3914,9309,1464,9359,4474,7095,2212,7302,2583,9462,7532,6567,1606,4436,8981,5612,6796,4385,5076,2007,6072,3678,8331,1338,3299,8845,4783,8613,4071,1232,6028,2176,3990,2148,3748,103,9453,538,6745,9110,926,3125,473,5970,8728,7072,9062,1404,1317,5139,9862,6496,6062,3338,464,1600,2532,1088,8232,7739,8274,3873 +2341,523,7096,8397,8301,6541,9844,244,4993,2280,7689,4025,4196,5522,7904,6048,2623,9258,2149,9461,6448,8087,7245,1917,8340,7127,8466,5725,6996,3421,5313,512,9164,9837,9794,8369,4185,1488,7210,1524,1016,4620,9435,2478,7765,8035,697,6677,3724,6988,5853,7662,3895,9593,1185,4727,6025,5734,7665,3070,138,8469,6748,6459,561,7935,8646,2378,462,7755,3115,9690,8877,3946,2728,8793,244,6323,8666,4271 +6430,2406,8994,56,1267,3826,9443,7079,7579,5232,6691,3435,6718,5698,4144,7028,592,2627,217,734,6194,8156,9118,58,2640,8069,4127,3285,694,3197,3377,4143,4802,3324,8134,6953,7625,3598,3584,4289,7065,3434,2106,7132,5802,7920,9060,7531,3321,1725,1067,3751,444,5503,6785,7937,6365,4803,198,6266,8177,1470,6390,1606,2904,7555,9834,8667,2033,1723,5167,1666,8546,8152,473,4475,6451,7947,3062,3281 +2810,3042,7759,1741,2275,2609,7676,8640,4117,1958,7500,8048,1757,3954,9270,1971,4796,2912,660,5511,3553,1012,5757,4525,6084,7198,8352,5775,7726,8591,7710,9589,3122,4392,6856,5016,749,2285,3356,7482,9956,7348,2599,8944,495,3462,3578,551,4543,7207,7169,7796,1247,4278,6916,8176,3742,8385,2310,1345,8692,2667,4568,1770,8319,3585,4920,3890,4928,7343,5385,9772,7947,8786,2056,9266,3454,2807,877,2660 +6206,8252,5928,5837,4177,4333,207,7934,5581,9526,8906,1498,8411,2984,5198,5134,2464,8435,8514,8674,3876,599,5327,826,2152,4084,2433,9327,9697,4800,2728,3608,3849,3861,3498,9943,1407,3991,7191,9110,5666,8434,4704,6545,5944,2357,1163,4995,9619,6754,4200,9682,6654,4862,4744,5953,6632,1054,293,9439,8286,2255,696,8709,1533,1844,6441,430,1999,6063,9431,7018,8057,2920,6266,6799,356,3597,4024,6665 +3847,6356,8541,7225,2325,2946,5199,469,5450,7508,2197,9915,8284,7983,6341,3276,3321,16,1321,7608,5015,3362,8491,6968,6818,797,156,2575,706,9516,5344,5457,9210,5051,8099,1617,9951,7663,8253,9683,2670,1261,4710,1068,8753,4799,1228,2621,3275,6188,4699,1791,9518,8701,5932,4275,6011,9877,2933,4182,6059,2930,6687,6682,9771,654,9437,3169,8596,1827,5471,8909,2352,123,4394,3208,8756,5513,6917,2056 +5458,8173,3138,3290,4570,4892,3317,4251,9699,7973,1163,1935,5477,6648,9614,5655,9592,975,9118,2194,7322,8248,8413,3462,8560,1907,7810,6650,7355,2939,4973,6894,3933,3784,3200,2419,9234,4747,2208,2207,1945,2899,1407,6145,8023,3484,5688,7686,2737,3828,3704,9004,5190,9740,8643,8650,5358,4426,1522,1707,3613,9887,6956,2447,2762,833,1449,9489,2573,1080,4167,3456,6809,2466,227,7125,2759,6250,6472,8089 +3266,7025,9756,3914,1265,9116,7723,9788,6805,5493,2092,8688,6592,9173,4431,4028,6007,7131,4446,4815,3648,6701,759,3312,8355,4485,4187,5188,8746,7759,3528,2177,5243,8379,3838,7233,4607,9187,7216,2190,6967,2920,6082,7910,5354,3609,8958,6949,7731,494,8753,8707,1523,4426,3543,7085,647,6771,9847,646,5049,824,8417,5260,2730,5702,2513,9275,4279,2767,8684,1165,9903,4518,55,9682,8963,6005,2102,6523 +1998,8731,936,1479,5259,7064,4085,91,7745,7136,3773,3810,730,8255,2705,2653,9790,6807,2342,355,9344,2668,3690,2028,9679,8102,574,4318,6481,9175,5423,8062,2867,9657,7553,3442,3920,7430,3945,7639,3714,3392,2525,4995,4850,2867,7951,9667,486,9506,9888,781,8866,1702,3795,90,356,1483,4200,2131,6969,5931,486,6880,4404,1084,5169,4910,6567,8335,4686,5043,2614,3352,2667,4513,6472,7471,5720,1616 +8878,1613,1716,868,1906,2681,564,665,5995,2474,7496,3432,9491,9087,8850,8287,669,823,347,6194,2264,2592,7871,7616,8508,4827,760,2676,4660,4881,7572,3811,9032,939,4384,929,7525,8419,5556,9063,662,8887,7026,8534,3111,1454,2082,7598,5726,6687,9647,7608,73,3014,5063,670,5461,5631,3367,9796,8475,7908,5073,1565,5008,5295,4457,1274,4788,1728,338,600,8415,8535,9351,7750,6887,5845,1741,125 +3637,6489,9634,9464,9055,2413,7824,9517,7532,3577,7050,6186,6980,9365,9782,191,870,2497,8498,2218,2757,5420,6468,586,3320,9230,1034,1393,9886,5072,9391,1178,8464,8042,6869,2075,8275,3601,7715,9470,8786,6475,8373,2159,9237,2066,3264,5000,679,355,3069,4073,494,2308,5512,4334,9438,8786,8637,9774,1169,1949,6594,6072,4270,9158,7916,5752,6794,9391,6301,5842,3285,2141,3898,8027,4310,8821,7079,1307 +8497,6681,4732,7151,7060,5204,9030,7157,833,5014,8723,3207,9796,9286,4913,119,5118,7650,9335,809,3675,2597,5144,3945,5090,8384,187,4102,1260,2445,2792,4422,8389,9290,50,1765,1521,6921,8586,4368,1565,5727,7855,2003,4834,9897,5911,8630,5070,1330,7692,7557,7980,6028,5805,9090,8265,3019,3802,698,9149,5748,1965,9658,4417,5994,5584,8226,2937,272,5743,1278,5698,8736,2595,6475,5342,6596,1149,6920 +8188,8009,9546,6310,8772,2500,9846,6592,6872,3857,1307,8125,7042,1544,6159,2330,643,4604,7899,6848,371,8067,2062,3200,7295,1857,9505,6936,384,2193,2190,301,8535,5503,1462,7380,5114,4824,8833,1763,4974,8711,9262,6698,3999,2645,6937,7747,1128,2933,3556,7943,2885,3122,9105,5447,418,2899,5148,3699,9021,9501,597,4084,175,1621,1,1079,6067,5812,4326,9914,6633,5394,4233,6728,9084,1864,5863,1225 +9935,8793,9117,1825,9542,8246,8437,3331,9128,9675,6086,7075,319,1334,7932,3583,7167,4178,1726,7720,695,8277,7887,6359,5912,1719,2780,8529,1359,2013,4498,8072,1129,9998,1147,8804,9405,6255,1619,2165,7491,1,8882,7378,3337,503,5758,4109,3577,985,3200,7615,8058,5032,1080,6410,6873,5496,1466,2412,9885,5904,4406,3605,8770,4361,6205,9193,1537,9959,214,7260,9566,1685,100,4920,7138,9819,5637,976 +3466,9854,985,1078,7222,8888,5466,5379,3578,4540,6853,8690,3728,6351,7147,3134,6921,9692,857,3307,4998,2172,5783,3931,9417,2541,6299,13,787,2099,9131,9494,896,8600,1643,8419,7248,2660,2609,8579,91,6663,5506,7675,1947,6165,4286,1972,9645,3805,1663,1456,8853,5705,9889,7489,1107,383,4044,2969,3343,152,7805,4980,9929,5033,1737,9953,7197,9158,4071,1324,473,9676,3984,9680,3606,8160,7384,5432 +1005,4512,5186,3953,2164,3372,4097,3247,8697,3022,9896,4101,3871,6791,3219,2742,4630,6967,7829,5991,6134,1197,1414,8923,8787,1394,8852,5019,7768,5147,8004,8825,5062,9625,7988,1110,3992,7984,9966,6516,6251,8270,421,3723,1432,4830,6935,8095,9059,2214,6483,6846,3120,1587,6201,6691,9096,9627,6671,4002,3495,9939,7708,7465,5879,6959,6634,3241,3401,2355,9061,2611,7830,3941,2177,2146,5089,7079,519,6351 +7280,8586,4261,2831,7217,3141,9994,9940,5462,2189,4005,6942,9848,5350,8060,6665,7519,4324,7684,657,9453,9296,2944,6843,7499,7847,1728,9681,3906,6353,5529,2822,3355,3897,7724,4257,7489,8672,4356,3983,1948,6892,7415,4153,5893,4190,621,1736,4045,9532,7701,3671,1211,1622,3176,4524,9317,7800,5638,6644,6943,5463,3531,2821,1347,5958,3436,1438,2999,994,850,4131,2616,1549,3465,5946,690,9273,6954,7991 +9517,399,3249,2596,7736,2142,1322,968,7350,1614,468,3346,3265,7222,6086,1661,5317,2582,7959,4685,2807,2917,1037,5698,1529,3972,8716,2634,3301,3412,8621,743,8001,4734,888,7744,8092,3671,8941,1487,5658,7099,2781,99,1932,4443,4756,4652,9328,1581,7855,4312,5976,7255,6480,3996,2748,1973,9731,4530,2790,9417,7186,5303,3557,351,7182,9428,1342,9020,7599,1392,8304,2070,9138,7215,2008,9937,1106,7110 +7444,769,9688,632,1571,6820,8743,4338,337,3366,3073,1946,8219,104,4210,6986,249,5061,8693,7960,6546,1004,8857,5997,9352,4338,6105,5008,2556,6518,6694,4345,3727,7956,20,3954,8652,4424,9387,2035,8358,5962,5304,5194,8650,8282,1256,1103,2138,6679,1985,3653,2770,2433,4278,615,2863,1715,242,3790,2636,6998,3088,1671,2239,957,5411,4595,6282,2881,9974,2401,875,7574,2987,4587,3147,6766,9885,2965 +3287,3016,3619,6818,9073,6120,5423,557,2900,2015,8111,3873,1314,4189,1846,4399,7041,7583,2427,2864,3525,5002,2069,748,1948,6015,2684,438,770,8367,1663,7887,7759,1885,157,7770,4520,4878,3857,1137,3525,3050,6276,5569,7649,904,4533,7843,2199,5648,7628,9075,9441,3600,7231,2388,5640,9096,958,3058,584,5899,8150,1181,9616,1098,8162,6819,8171,1519,1140,7665,8801,2632,1299,9192,707,9955,2710,7314 +1772,2963,7578,3541,3095,1488,7026,2634,6015,4633,4370,2762,1650,2174,909,8158,2922,8467,4198,4280,9092,8856,8835,5457,2790,8574,9742,5054,9547,4156,7940,8126,9824,7340,8840,6574,3547,1477,3014,6798,7134,435,9484,9859,3031,4,1502,4133,1738,1807,4825,463,6343,9701,8506,9822,9555,8688,8168,3467,3234,6318,1787,5591,419,6593,7974,8486,9861,6381,6758,194,3061,4315,2863,4665,3789,2201,1492,4416 +126,8927,6608,5682,8986,6867,1715,6076,3159,788,3140,4744,830,9253,5812,5021,7616,8534,1546,9590,1101,9012,9821,8132,7857,4086,1069,7491,2988,1579,2442,4321,2149,7642,6108,250,6086,3167,24,9528,7663,2685,1220,9196,1397,5776,1577,1730,5481,977,6115,199,6326,2183,3767,5928,5586,7561,663,8649,9688,949,5913,9160,1870,5764,9887,4477,6703,1413,4995,5494,7131,2192,8969,7138,3997,8697,646,1028 +8074,1731,8245,624,4601,8706,155,8891,309,2552,8208,8452,2954,3124,3469,4246,3352,1105,4509,8677,9901,4416,8191,9283,5625,7120,2952,8881,7693,830,4580,8228,9459,8611,4499,1179,4988,1394,550,2336,6089,6872,269,7213,1848,917,6672,4890,656,1478,6536,3165,4743,4990,1176,6211,7207,5284,9730,4738,1549,4986,4942,8645,3698,9429,1439,2175,6549,3058,6513,1574,6988,8333,3406,5245,5431,7140,7085,6407 +7845,4694,2530,8249,290,5948,5509,1588,5940,4495,5866,5021,4626,3979,3296,7589,4854,1998,5627,3926,8346,6512,9608,1918,7070,4747,4182,2858,2766,4606,6269,4107,8982,8568,9053,4244,5604,102,2756,727,5887,2566,7922,44,5986,621,1202,374,6988,4130,3627,6744,9443,4568,1398,8679,397,3928,9159,367,2917,6127,5788,3304,8129,911,2669,1463,9749,264,4478,8940,1109,7309,2462,117,4692,7724,225,2312 +4164,3637,2000,941,8903,39,3443,7172,1031,3687,4901,8082,4945,4515,7204,9310,9349,9535,9940,218,1788,9245,2237,1541,5670,6538,6047,5553,9807,8101,1925,8714,445,8332,7309,6830,5786,5736,7306,2710,3034,1838,7969,6318,7912,2584,2080,7437,6705,2254,7428,820,782,9861,7596,3842,3631,8063,5240,6666,394,4565,7865,4895,9890,6028,6117,4724,9156,4473,4552,602,470,6191,4927,5387,884,3146,1978,3000 +4258,6880,1696,3582,5793,4923,2119,1155,9056,9698,6603,3768,5514,9927,9609,6166,6566,4536,4985,4934,8076,9062,6741,6163,7399,4562,2337,5600,2919,9012,8459,1308,6072,1225,9306,8818,5886,7243,7365,8792,6007,9256,6699,7171,4230,7002,8720,7839,4533,1671,478,7774,1607,2317,5437,4705,7886,4760,6760,7271,3081,2997,3088,7675,6208,3101,6821,6840,122,9633,4900,2067,8546,4549,2091,7188,5605,8599,6758,5229 +7854,5243,9155,3556,8812,7047,2202,1541,5993,4600,4760,713,434,7911,7426,7414,8729,322,803,7960,7563,4908,6285,6291,736,3389,9339,4132,8701,7534,5287,3646,592,3065,7582,2592,8755,6068,8597,1982,5782,1894,2900,6236,4039,6569,3037,5837,7698,700,7815,2491,7272,5878,3083,6778,6639,3589,5010,8313,2581,6617,5869,8402,6808,2951,2321,5195,497,2190,6187,1342,1316,4453,7740,4154,2959,1781,1482,8256 +7178,2046,4419,744,8312,5356,6855,8839,319,2962,5662,47,6307,8662,68,4813,567,2712,9931,1678,3101,8227,6533,4933,6656,92,5846,4780,6256,6361,4323,9985,1231,2175,7178,3034,9744,6155,9165,7787,5836,9318,7860,9644,8941,6480,9443,8188,5928,161,6979,2352,5628,6991,1198,8067,5867,6620,3778,8426,2994,3122,3124,6335,3918,8897,2655,9670,634,1088,1576,8935,7255,474,8166,7417,9547,2886,5560,3842 +6957,3111,26,7530,7143,1295,1744,6057,3009,1854,8098,5405,2234,4874,9447,2620,9303,27,7410,969,40,2966,5648,7596,8637,4238,3143,3679,7187,690,9980,7085,7714,9373,5632,7526,6707,3951,9734,4216,2146,3602,5371,6029,3039,4433,4855,4151,1449,3376,8009,7240,7027,4602,2947,9081,4045,8424,9352,8742,923,2705,4266,3232,2264,6761,363,2651,3383,7770,6730,7856,7340,9679,2158,610,4471,4608,910,6241 +4417,6756,1013,8797,658,8809,5032,8703,7541,846,3357,2920,9817,1745,9980,7593,4667,3087,779,3218,6233,5568,4296,2289,2654,7898,5021,9461,5593,8214,9173,4203,2271,7980,2983,5952,9992,8399,3468,1776,3188,9314,1720,6523,2933,621,8685,5483,8986,6163,3444,9539,4320,155,3992,2828,2150,6071,524,2895,5468,8063,1210,3348,9071,4862,483,9017,4097,6186,9815,3610,5048,1644,1003,9865,9332,2145,1944,2213 +9284,3803,4920,1927,6706,4344,7383,4786,9890,2010,5228,1224,3158,6967,8580,8990,8883,5213,76,8306,2031,4980,5639,9519,7184,5645,7769,3259,8077,9130,1317,3096,9624,3818,1770,695,2454,947,6029,3474,9938,3527,5696,4760,7724,7738,2848,6442,5767,6845,8323,4131,2859,7595,2500,4815,3660,9130,8580,7016,8231,4391,8369,3444,4069,4021,556,6154,627,2778,1496,4206,6356,8434,8491,3816,8231,3190,5575,1015 +3787,7572,1788,6803,5641,6844,1961,4811,8535,9914,9999,1450,8857,738,4662,8569,6679,2225,7839,8618,286,2648,5342,2294,3205,4546,176,8705,3741,6134,8324,8021,7004,5205,7032,6637,9442,5539,5584,4819,5874,5807,8589,6871,9016,983,1758,3786,1519,6241,185,8398,495,3370,9133,3051,4549,9674,7311,9738,3316,9383,2658,2776,9481,7558,619,3943,3324,6491,4933,153,9738,4623,912,3595,7771,7939,1219,4405 +2650,3883,4154,5809,315,7756,4430,1788,4451,1631,6461,7230,6017,5751,138,588,5282,2442,9110,9035,6349,2515,1570,6122,4192,4174,3530,1933,4186,4420,4609,5739,4135,2963,6308,1161,8809,8619,2796,3819,6971,8228,4188,1492,909,8048,2328,6772,8467,7671,9068,2226,7579,6422,7056,8042,3296,2272,3006,2196,7320,3238,3490,3102,37,1293,3212,4767,5041,8773,5794,4456,6174,7279,7054,2835,7053,9088,790,6640 +3101,1057,7057,3826,6077,1025,2955,1224,1114,6729,5902,4698,6239,7203,9423,1804,4417,6686,1426,6941,8071,1029,4985,9010,6122,6597,1622,1574,3513,1684,7086,5505,3244,411,9638,4150,907,9135,829,981,1707,5359,8781,9751,5,9131,3973,7159,1340,6955,7514,7993,6964,8198,1933,2797,877,3993,4453,8020,9349,8646,2779,8679,2961,3547,3374,3510,1129,3568,2241,2625,9138,5974,8206,7669,7678,1833,8700,4480 +4865,9912,8038,8238,782,3095,8199,1127,4501,7280,2112,2487,3626,2790,9432,1475,6312,8277,4827,2218,5806,7132,8752,1468,7471,6386,739,8762,8323,8120,5169,9078,9058,3370,9560,7987,8585,8531,5347,9312,1058,4271,1159,5286,5404,6925,8606,9204,7361,2415,560,586,4002,2644,1927,2824,768,4409,2942,3345,1002,808,4941,6267,7979,5140,8643,7553,9438,7320,4938,2666,4609,2778,8158,6730,3748,3867,1866,7181 +171,3771,7134,8927,4778,2913,3326,2004,3089,7853,1378,1729,4777,2706,9578,1360,5693,3036,1851,7248,2403,2273,8536,6501,9216,613,9671,7131,7719,6425,773,717,8803,160,1114,7554,7197,753,4513,4322,8499,4533,2609,4226,8710,6627,644,9666,6260,4870,5744,7385,6542,6203,7703,6130,8944,5589,2262,6803,6381,7414,6888,5123,7320,9392,9061,6780,322,8975,7050,5089,1061,2260,3199,1150,1865,5386,9699,6501 +3744,8454,6885,8277,919,1923,4001,6864,7854,5519,2491,6057,8794,9645,1776,5714,9786,9281,7538,6916,3215,395,2501,9618,4835,8846,9708,2813,3303,1794,8309,7176,2206,1602,1838,236,4593,2245,8993,4017,10,8215,6921,5206,4023,5932,6997,7801,262,7640,3107,8275,4938,7822,2425,3223,3886,2105,8700,9526,2088,8662,8034,7004,5710,2124,7164,3574,6630,9980,4242,2901,9471,1491,2117,4562,1130,9086,4117,6698 +2810,2280,2331,1170,4554,4071,8387,1215,2274,9848,6738,1604,7281,8805,439,1298,8318,7834,9426,8603,6092,7944,1309,8828,303,3157,4638,4439,9175,1921,4695,7716,1494,1015,1772,5913,1127,1952,1950,8905,4064,9890,385,9357,7945,5035,7082,5369,4093,6546,5187,5637,2041,8946,1758,7111,6566,1027,1049,5148,7224,7248,296,6169,375,1656,7993,2816,3717,4279,4675,1609,3317,42,6201,3100,3144,163,9530,4531 +7096,6070,1009,4988,3538,5801,7149,3063,2324,2912,7911,7002,4338,7880,2481,7368,3516,2016,7556,2193,1388,3865,8125,4637,4096,8114,750,3144,1938,7002,9343,4095,1392,4220,3455,6969,9647,1321,9048,1996,1640,6626,1788,314,9578,6630,2813,6626,4981,9908,7024,4355,3201,3521,3864,3303,464,1923,595,9801,3391,8366,8084,9374,1041,8807,9085,1892,9431,8317,9016,9221,8574,9981,9240,5395,2009,6310,2854,9255 +8830,3145,2960,9615,8220,6061,3452,2918,6481,9278,2297,3385,6565,7066,7316,5682,107,7646,4466,68,1952,9603,8615,54,7191,791,6833,2560,693,9733,4168,570,9127,9537,1925,8287,5508,4297,8452,8795,6213,7994,2420,4208,524,5915,8602,8330,2651,8547,6156,1812,6271,7991,9407,9804,1553,6866,1128,2119,4691,9711,8315,5879,9935,6900,482,682,4126,1041,428,6247,3720,5882,7526,2582,4327,7725,3503,2631 +2738,9323,721,7434,1453,6294,2957,3786,5722,6019,8685,4386,3066,9057,6860,499,5315,3045,5194,7111,3137,9104,941,586,3066,755,4177,8819,7040,5309,3583,3897,4428,7788,4721,7249,6559,7324,825,7311,3760,6064,6070,9672,4882,584,1365,9739,9331,5783,2624,7889,1604,1303,1555,7125,8312,425,8936,3233,7724,1480,403,7440,1784,1754,4721,1569,652,3893,4574,5692,9730,4813,9844,8291,9199,7101,3391,8914 +6044,2928,9332,3328,8588,447,3830,1176,3523,2705,8365,6136,5442,9049,5526,8575,8869,9031,7280,706,2794,8814,5767,4241,7696,78,6570,556,5083,1426,4502,3336,9518,2292,1885,3740,3153,9348,9331,8051,2759,5407,9028,7840,9255,831,515,2612,9747,7435,8964,4971,2048,4900,5967,8271,1719,9670,2810,6777,1594,6367,6259,8316,3815,1689,6840,9437,4361,822,9619,3065,83,6344,7486,8657,8228,9635,6932,4864 +8478,4777,6334,4678,7476,4963,6735,3096,5860,1405,5127,7269,7793,4738,227,9168,2996,8928,765,733,1276,7677,6258,1528,9558,3329,302,8901,1422,8277,6340,645,9125,8869,5952,141,8141,1816,9635,4025,4184,3093,83,2344,2747,9352,7966,1206,1126,1826,218,7939,2957,2729,810,8752,5247,4174,4038,8884,7899,9567,301,5265,5752,7524,4381,1669,3106,8270,6228,6373,754,2547,4240,2313,5514,3022,1040,9738 +2265,8192,1763,1369,8469,8789,4836,52,1212,6690,5257,8918,6723,6319,378,4039,2421,8555,8184,9577,1432,7139,8078,5452,9628,7579,4161,7490,5159,8559,1011,81,478,5840,1964,1334,6875,8670,9900,739,1514,8692,522,9316,6955,1345,8132,2277,3193,9773,3923,4177,2183,1236,6747,6575,4874,6003,6409,8187,745,8776,9440,7543,9825,2582,7381,8147,7236,5185,7564,6125,218,7991,6394,391,7659,7456,5128,5294 +2132,8992,8160,5782,4420,3371,3798,5054,552,5631,7546,4716,1332,6486,7892,7441,4370,6231,4579,2121,8615,1145,9391,1524,1385,2400,9437,2454,7896,7467,2928,8400,3299,4025,7458,4703,7206,6358,792,6200,725,4275,4136,7390,5984,4502,7929,5085,8176,4600,119,3568,76,9363,6943,2248,9077,9731,6213,5817,6729,4190,3092,6910,759,2682,8380,1254,9604,3011,9291,5329,9453,9746,2739,6522,3765,5634,1113,5789 +5304,5499,564,2801,679,2653,1783,3608,7359,7797,3284,796,3222,437,7185,6135,8571,2778,7488,5746,678,6140,861,7750,803,9859,9918,2425,3734,2698,9005,4864,9818,6743,2475,132,9486,3825,5472,919,292,4411,7213,7699,6435,9019,6769,1388,802,2124,1345,8493,9487,8558,7061,8777,8833,2427,2238,5409,4957,8503,3171,7622,5779,6145,2417,5873,5563,5693,9574,9491,1937,7384,4563,6842,5432,2751,3406,7981 diff --git a/project_euler/problem_082/sol1.py b/project_euler/problem_082/sol1.py new file mode 100644 index 000000000..7b50dc887 --- /dev/null +++ b/project_euler/problem_082/sol1.py @@ -0,0 +1,65 @@ +""" +Project Euler Problem 82: https://projecteuler.net/problem=82 + +The minimal path sum in the 5 by 5 matrix below, by starting in any cell +in the left column and finishing in any cell in the right column, +and only moving up, down, and right, is indicated in red and bold; +the sum is equal to 994. + + 131 673 [234] [103] [18] + [201] [96] [342] 965 150 + 630 803 746 422 111 + 537 699 497 121 956 + 805 732 524 37 331 + +Find the minimal path sum from the left column to the right column in matrix.txt +(https://projecteuler.net/project/resources/p082_matrix.txt) +(right click and "Save Link/Target As..."), +a 31K text file containing an 80 by 80 matrix. +""" + +import os + + +def solution(filename: str = "input.txt") -> int: + """ + Returns the minimal path sum in the matrix from the file, by starting in any cell + in the left column and finishing in any cell in the right column, + and only moving up, down, and right + + >>> solution("test_matrix.txt") + 994 + """ + + with open(os.path.join(os.path.dirname(__file__), filename)) as input_file: + matrix = [ + [int(element) for element in line.split(",")] + for line in input_file.readlines() + ] + + rows = len(matrix) + cols = len(matrix[0]) + + minimal_path_sums = [[-1 for _ in range(cols)] for _ in range(rows)] + for i in range(rows): + minimal_path_sums[i][0] = matrix[i][0] + + for j in range(1, cols): + for i in range(rows): + minimal_path_sums[i][j] = minimal_path_sums[i][j - 1] + matrix[i][j] + + for i in range(1, rows): + minimal_path_sums[i][j] = min( + minimal_path_sums[i][j], minimal_path_sums[i - 1][j] + matrix[i][j] + ) + + for i in range(rows - 2, -1, -1): + minimal_path_sums[i][j] = min( + minimal_path_sums[i][j], minimal_path_sums[i + 1][j] + matrix[i][j] + ) + + return min(minimal_path_sums_row[-1] for minimal_path_sums_row in minimal_path_sums) + + +if __name__ == "__main__": + print(f"{solution() = }") diff --git a/project_euler/problem_082/test_matrix.txt b/project_euler/problem_082/test_matrix.txt new file mode 100644 index 000000000..76167d9e7 --- /dev/null +++ b/project_euler/problem_082/test_matrix.txt @@ -0,0 +1,5 @@ +131,673,234,103,18 +201,96,342,965,150 +630,803,746,422,111 +537,699,497,121,956 +805,732,524,37,331 From ee778128bdf8d4d6d386cfdc500f3b3173f56c06 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Thu, 2 Mar 2023 07:57:07 +0300 Subject: [PATCH 591/726] Reduce the complexity of other/scoring_algorithm.py (#8045) * Increase the --max-complexity threshold in the file .flake8 --- other/scoring_algorithm.py | 57 ++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/other/scoring_algorithm.py b/other/scoring_algorithm.py index 00d87cfc0..8e04a8f30 100644 --- a/other/scoring_algorithm.py +++ b/other/scoring_algorithm.py @@ -23,29 +23,29 @@ Thus the weights for each column are as follows: """ -def procentual_proximity( - source_data: list[list[float]], weights: list[int] -) -> list[list[float]]: +def get_data(source_data: list[list[float]]) -> list[list[float]]: """ - weights - int list - possible values - 0 / 1 - 0 if lower values have higher weight in the data set - 1 if higher values have higher weight in the data set - - >>> procentual_proximity([[20, 60, 2012],[23, 90, 2015],[22, 50, 2011]], [0, 0, 1]) - [[20, 60, 2012, 2.0], [23, 90, 2015, 1.0], [22, 50, 2011, 1.3333333333333335]] + >>> get_data([[20, 60, 2012],[23, 90, 2015],[22, 50, 2011]]) + [[20.0, 23.0, 22.0], [60.0, 90.0, 50.0], [2012.0, 2015.0, 2011.0]] """ - - # getting data data_lists: list[list[float]] = [] for data in source_data: for i, el in enumerate(data): if len(data_lists) < i + 1: data_lists.append([]) data_lists[i].append(float(el)) + return data_lists + +def calculate_each_score( + data_lists: list[list[float]], weights: list[int] +) -> list[list[float]]: + """ + >>> calculate_each_score([[20, 23, 22], [60, 90, 50], [2012, 2015, 2011]], + ... [0, 0, 1]) + [[1.0, 0.0, 0.33333333333333337], [0.75, 0.0, 1.0], [0.25, 1.0, 0.0]] + """ score_lists: list[list[float]] = [] - # calculating each score for dlist, weight in zip(data_lists, weights): mind = min(dlist) maxd = max(dlist) @@ -72,14 +72,43 @@ def procentual_proximity( score_lists.append(score) + return score_lists + + +def generate_final_scores(score_lists: list[list[float]]) -> list[float]: + """ + >>> generate_final_scores([[1.0, 0.0, 0.33333333333333337], + ... [0.75, 0.0, 1.0], + ... [0.25, 1.0, 0.0]]) + [2.0, 1.0, 1.3333333333333335] + """ # initialize final scores final_scores: list[float] = [0 for i in range(len(score_lists[0]))] - # generate final scores for slist in score_lists: for j, ele in enumerate(slist): final_scores[j] = final_scores[j] + ele + return final_scores + + +def procentual_proximity( + source_data: list[list[float]], weights: list[int] +) -> list[list[float]]: + """ + weights - int list + possible values - 0 / 1 + 0 if lower values have higher weight in the data set + 1 if higher values have higher weight in the data set + + >>> procentual_proximity([[20, 60, 2012],[23, 90, 2015],[22, 50, 2011]], [0, 0, 1]) + [[20, 60, 2012, 2.0], [23, 90, 2015, 1.0], [22, 50, 2011, 1.3333333333333335]] + """ + + data_lists = get_data(source_data) + score_lists = calculate_each_score(data_lists, weights) + final_scores = generate_final_scores(score_lists) + # append scores to source data for i, ele in enumerate(final_scores): source_data[i].append(ele) From 9720e6a6cf52e2395e2d7ef3ef6ae91a355d318e Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Thu, 2 Mar 2023 19:51:48 +0300 Subject: [PATCH 592/726] Add Project Euler problem 117 solution 1 (#6872) Update DIRECTORY.md --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 2 + project_euler/problem_117/__init__.py | 0 project_euler/problem_117/sol1.py | 53 +++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 project_euler/problem_117/__init__.py create mode 100644 project_euler/problem_117/sol1.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 3d1bc967e..484484104 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -956,6 +956,8 @@ * [Sol1](project_euler/problem_115/sol1.py) * Problem 116 * [Sol1](project_euler/problem_116/sol1.py) + * Problem 117 + * [Sol1](project_euler/problem_117/sol1.py) * Problem 119 * [Sol1](project_euler/problem_119/sol1.py) * Problem 120 diff --git a/project_euler/problem_117/__init__.py b/project_euler/problem_117/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_117/sol1.py b/project_euler/problem_117/sol1.py new file mode 100644 index 000000000..e8214454f --- /dev/null +++ b/project_euler/problem_117/sol1.py @@ -0,0 +1,53 @@ +""" +Project Euler Problem 117: https://projecteuler.net/problem=117 + +Using a combination of grey square tiles and oblong tiles chosen from: +red tiles (measuring two units), green tiles (measuring three units), +and blue tiles (measuring four units), +it is possible to tile a row measuring five units in length +in exactly fifteen different ways. + + |grey|grey|grey|grey|grey| |red,red|grey|grey|grey| + + |grey|red,red|grey|grey| |grey|grey|red,red|grey| + + |grey|grey|grey|red,red| |red,red|red,red|grey| + + |red,red|grey|red,red| |grey|red,red|red,red| + + |green,green,green|grey|grey| |grey|green,green,green|grey| + + |grey|grey|green,green,green| |red,red|green,green,green| + + |green,green,green|red,red| |blue,blue,blue,blue|grey| + + |grey|blue,blue,blue,blue| + +How many ways can a row measuring fifty units in length be tiled? + +NOTE: This is related to Problem 116 (https://projecteuler.net/problem=116). +""" + + +def solution(length: int = 50) -> int: + """ + Returns the number of ways can a row of the given length be tiled + + >>> solution(5) + 15 + """ + + ways_number = [1] * (length + 1) + + for row_length in range(length + 1): + for tile_length in range(2, 5): + for tile_start in range(row_length - tile_length + 1): + ways_number[row_length] += ways_number[ + row_length - tile_start - tile_length + ] + + return ways_number[length] + + +if __name__ == "__main__": + print(f"{solution() = }") From 41b633a841084acac5a640042d365c985e23b357 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 7 Mar 2023 00:10:39 +0100 Subject: [PATCH 593/726] [pre-commit.ci] pre-commit autoupdate (#8168) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/charliermarsh/ruff-pre-commit: v0.0.253 → v0.0.254](https://github.com/charliermarsh/ruff-pre-commit/compare/v0.0.253...v0.0.254) * Rename get_top_billionaires.py to get_top_billionaires.py.disabled * updating DIRECTORY.md --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- DIRECTORY.md | 1 - ...get_top_billionaires.py => get_top_billionaires.py.disabled} | 0 3 files changed, 1 insertion(+), 2 deletions(-) rename web_programming/{get_top_billionaires.py => get_top_billionaires.py.disabled} (100%) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9f27f985b..329407265 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -44,7 +44,7 @@ repos: - --py311-plus - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.253 + rev: v0.0.254 hooks: - id: ruff args: diff --git a/DIRECTORY.md b/DIRECTORY.md index 484484104..f25b0c6ff 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -1167,7 +1167,6 @@ * [Get Amazon Product Data](web_programming/get_amazon_product_data.py) * [Get Imdb Top 250 Movies Csv](web_programming/get_imdb_top_250_movies_csv.py) * [Get Imdbtop](web_programming/get_imdbtop.py) - * [Get Top Billionaires](web_programming/get_top_billionaires.py) * [Get Top Hn Posts](web_programming/get_top_hn_posts.py) * [Get User Tweets](web_programming/get_user_tweets.py) * [Giphy](web_programming/giphy.py) diff --git a/web_programming/get_top_billionaires.py b/web_programming/get_top_billionaires.py.disabled similarity index 100% rename from web_programming/get_top_billionaires.py rename to web_programming/get_top_billionaires.py.disabled From 9e28ecca28176254c39bcc791733589c6091422e Mon Sep 17 00:00:00 2001 From: Subhendu Dash <71781104+subhendudash02@users.noreply.github.com> Date: Tue, 7 Mar 2023 21:46:25 +0530 Subject: [PATCH 594/726] Add circular convolution (#8158) * add circular convolution * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add type hint for __init__ * rounding off final values to 2 and minor changes * add test case for unequal signals * changes in list comprehension and enumeraton --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- electronics/circular_convolution.py | 99 +++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 electronics/circular_convolution.py diff --git a/electronics/circular_convolution.py b/electronics/circular_convolution.py new file mode 100644 index 000000000..f2e35742e --- /dev/null +++ b/electronics/circular_convolution.py @@ -0,0 +1,99 @@ +# https://en.wikipedia.org/wiki/Circular_convolution + +""" +Circular convolution, also known as cyclic convolution, +is a special case of periodic convolution, which is the convolution of two +periodic functions that have the same period. Periodic convolution arises, +for example, in the context of the discrete-time Fourier transform (DTFT). +In particular, the DTFT of the product of two discrete sequences is the periodic +convolution of the DTFTs of the individual sequences. And each DTFT is a periodic +summation of a continuous Fourier transform function. + +Source: https://en.wikipedia.org/wiki/Circular_convolution +""" + +import doctest +from collections import deque + +import numpy as np + + +class CircularConvolution: + """ + This class stores the first and second signal and performs the circular convolution + """ + + def __init__(self) -> None: + """ + First signal and second signal are stored as 1-D array + """ + + self.first_signal = [2, 1, 2, -1] + self.second_signal = [1, 2, 3, 4] + + def circular_convolution(self) -> list[float]: + """ + This function performs the circular convolution of the first and second signal + using matrix method + + Usage: + >>> import circular_convolution as cc + >>> convolution = cc.CircularConvolution() + >>> convolution.circular_convolution() + [10, 10, 6, 14] + + >>> convolution.first_signal = [0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6] + >>> convolution.second_signal = [0.1, 0.3, 0.5, 0.7, 0.9, 1.1, 1.3, 1.5] + >>> convolution.circular_convolution() + [5.2, 6.0, 6.48, 6.64, 6.48, 6.0, 5.2, 4.08] + + >>> convolution.first_signal = [-1, 1, 2, -2] + >>> convolution.second_signal = [0.5, 1, -1, 2, 0.75] + >>> convolution.circular_convolution() + [6.25, -3.0, 1.5, -2.0, -2.75] + + >>> convolution.first_signal = [1, -1, 2, 3, -1] + >>> convolution.second_signal = [1, 2, 3] + >>> convolution.circular_convolution() + [8, -2, 3, 4, 11] + + """ + + length_first_signal = len(self.first_signal) + length_second_signal = len(self.second_signal) + + max_length = max(length_first_signal, length_second_signal) + + # create a zero matrix of max_length x max_length + matrix = [[0] * max_length for i in range(max_length)] + + # fills the smaller signal with zeros to make both signals of same length + if length_first_signal < length_second_signal: + self.first_signal += [0] * (max_length - length_first_signal) + elif length_first_signal > length_second_signal: + self.second_signal += [0] * (max_length - length_second_signal) + + """ + Fills the matrix in the following way assuming 'x' is the signal of length 4 + [ + [x[0], x[3], x[2], x[1]], + [x[1], x[0], x[3], x[2]], + [x[2], x[1], x[0], x[3]], + [x[3], x[2], x[1], x[0]] + ] + """ + for i in range(max_length): + rotated_signal = deque(self.second_signal) + rotated_signal.rotate(i) + for j, item in enumerate(rotated_signal): + matrix[i][j] += item + + # multiply the matrix with the first signal + final_signal = np.matmul(np.transpose(matrix), np.transpose(self.first_signal)) + + # rounding-off to two decimal places + return [round(i, 2) for i in final_signal] + + +if __name__ == "__main__": + doctest.testmod() From f9cc25221c1521a0da9ee27d6a9bea1f14f4c986 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Fri, 10 Mar 2023 12:48:05 +0300 Subject: [PATCH 595/726] Reduce the complexity of backtracking/word_search.py (#8166) * Lower the --max-complexity threshold in the file .flake8 --- backtracking/word_search.py | 112 +++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 52 deletions(-) diff --git a/backtracking/word_search.py b/backtracking/word_search.py index 25d1436be..c9d52012b 100644 --- a/backtracking/word_search.py +++ b/backtracking/word_search.py @@ -33,6 +33,61 @@ leetcode: https://leetcode.com/problems/word-search/ """ +def get_point_key(len_board: int, len_board_column: int, row: int, column: int) -> int: + """ + Returns the hash key of matrix indexes. + + >>> get_point_key(10, 20, 1, 0) + 200 + """ + + return len_board * len_board_column * row + column + + +def exits_word( + board: list[list[str]], + word: str, + row: int, + column: int, + word_index: int, + visited_points_set: set[int], +) -> bool: + """ + Return True if it's possible to search the word suffix + starting from the word_index. + + >>> exits_word([["A"]], "B", 0, 0, 0, set()) + False + """ + + if board[row][column] != word[word_index]: + return False + + if word_index == len(word) - 1: + return True + + traverts_directions = [(0, 1), (0, -1), (-1, 0), (1, 0)] + len_board = len(board) + len_board_column = len(board[0]) + for direction in traverts_directions: + next_i = row + direction[0] + next_j = column + direction[1] + if not (0 <= next_i < len_board and 0 <= next_j < len_board_column): + continue + + key = get_point_key(len_board, len_board_column, next_i, next_j) + if key in visited_points_set: + continue + + visited_points_set.add(key) + if exits_word(board, word, next_i, next_j, word_index + 1, visited_points_set): + return True + + visited_points_set.remove(key) + + return False + + def word_exists(board: list[list[str]], word: str) -> bool: """ >>> word_exists([["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], "ABCCED") @@ -77,6 +132,8 @@ def word_exists(board: list[list[str]], word: str) -> bool: board_error_message = ( "The board should be a non empty matrix of single chars strings." ) + + len_board = len(board) if not isinstance(board, list) or len(board) == 0: raise ValueError(board_error_message) @@ -94,61 +151,12 @@ def word_exists(board: list[list[str]], word: str) -> bool: "The word parameter should be a string of length greater than 0." ) - traverts_directions = [(0, 1), (0, -1), (-1, 0), (1, 0)] - len_word = len(word) - len_board = len(board) len_board_column = len(board[0]) - - # Returns the hash key of matrix indexes. - def get_point_key(row: int, column: int) -> int: - """ - >>> len_board=10 - >>> len_board_column=20 - >>> get_point_key(0, 0) - 200 - """ - - return len_board * len_board_column * row + column - - # Return True if it's possible to search the word suffix - # starting from the word_index. - def exits_word( - row: int, column: int, word_index: int, visited_points_set: set[int] - ) -> bool: - """ - >>> board=[["A"]] - >>> word="B" - >>> exits_word(0, 0, 0, set()) - False - """ - - if board[row][column] != word[word_index]: - return False - - if word_index == len_word - 1: - return True - - for direction in traverts_directions: - next_i = row + direction[0] - next_j = column + direction[1] - if not (0 <= next_i < len_board and 0 <= next_j < len_board_column): - continue - - key = get_point_key(next_i, next_j) - if key in visited_points_set: - continue - - visited_points_set.add(key) - if exits_word(next_i, next_j, word_index + 1, visited_points_set): - return True - - visited_points_set.remove(key) - - return False - for i in range(len_board): for j in range(len_board_column): - if exits_word(i, j, 0, {get_point_key(i, j)}): + if exits_word( + board, word, i, j, 0, {get_point_key(len_board, len_board_column, i, j)} + ): return True return False From 8959211100ba7a612d42a6e7db4755303b78c5a7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 13 Mar 2023 23:18:35 +0100 Subject: [PATCH 596/726] [pre-commit.ci] pre-commit autoupdate (#8177) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/charliermarsh/ruff-pre-commit: v0.0.254 → v0.0.255](https://github.com/charliermarsh/ruff-pre-commit/compare/v0.0.254...v0.0.255) - [github.com/pre-commit/mirrors-mypy: v1.0.1 → v1.1.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.0.1...v1.1.1) - [github.com/codespell-project/codespell: v2.2.2 → v2.2.4](https://github.com/codespell-project/codespell/compare/v2.2.2...v2.2.4) * updating DIRECTORY.md * Fixes for new version of codespell --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss --- .pre-commit-config.yaml | 8 ++++---- DIRECTORY.md | 1 + machine_learning/sequential_minimum_optimization.py | 2 +- physics/lorentz_transformation_four_vector.py | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 329407265..9aa965e42 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -44,7 +44,7 @@ repos: - --py311-plus - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.254 + rev: v0.0.255 hooks: - id: ruff args: @@ -69,7 +69,7 @@ repos: *flake8-plugins - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.0.1 + rev: v1.1.1 hooks: - id: mypy args: @@ -79,11 +79,11 @@ repos: additional_dependencies: [types-requests] - repo: https://github.com/codespell-project/codespell - rev: v2.2.2 + rev: v2.2.4 hooks: - id: codespell args: - - --ignore-words-list=ans,crate,damon,fo,followings,hist,iff,mater,secant,som,sur,tim,zar + - --ignore-words-list=3rt,ans,crate,damon,fo,followings,hist,iff,kwanza,mater,secant,som,sur,tim,zar exclude: | (?x)^( ciphers/prehistoric_men.txt | diff --git a/DIRECTORY.md b/DIRECTORY.md index f25b0c6ff..b2daaaa9c 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -334,6 +334,7 @@ ## Electronics * [Builtin Voltage](electronics/builtin_voltage.py) * [Carrier Concentration](electronics/carrier_concentration.py) + * [Circular Convolution](electronics/circular_convolution.py) * [Coulombs Law](electronics/coulombs_law.py) * [Electric Conductivity](electronics/electric_conductivity.py) * [Electric Power](electronics/electric_power.py) diff --git a/machine_learning/sequential_minimum_optimization.py b/machine_learning/sequential_minimum_optimization.py index 37172c8e9..b68bd52f4 100644 --- a/machine_learning/sequential_minimum_optimization.py +++ b/machine_learning/sequential_minimum_optimization.py @@ -569,7 +569,7 @@ def plot_partition_boundary( """ We can not get the optimum w of our kernel svm model which is different from linear svm. For this reason, we generate randomly distributed points with high desity and - prediced values of these points are calculated by using our tained model. Then we + prediced values of these points are calculated by using our trained model. Then we could use this prediced values to draw contour map. And this contour map can represent svm's partition boundary. """ diff --git a/physics/lorentz_transformation_four_vector.py b/physics/lorentz_transformation_four_vector.py index 64be97245..f4fda4dff 100644 --- a/physics/lorentz_transformation_four_vector.py +++ b/physics/lorentz_transformation_four_vector.py @@ -2,7 +2,7 @@ Lorentz transformations describe the transition between two inertial reference frames F and F', each of which is moving in some direction with respect to the other. This code only calculates Lorentz transformations for movement in the x -direction with no spacial rotation (i.e., a Lorentz boost in the x direction). +direction with no spatial rotation (i.e., a Lorentz boost in the x direction). The Lorentz transformations are calculated here as linear transformations of four-vectors [ct, x, y, z] described by Minkowski space. Note that t (time) is multiplied by c (the speed of light) in the first entry of each four-vector. From b797e437aeadcac50556d6606a547dc634cf5329 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 14 Mar 2023 01:31:27 +0100 Subject: [PATCH 597/726] Add hashmap implementation (#7967) --- data_structures/hashing/hash_map.py | 162 ++++++++++++++++++ .../hashing/tests/test_hash_map.py | 97 +++++++++++ 2 files changed, 259 insertions(+) create mode 100644 data_structures/hashing/hash_map.py create mode 100644 data_structures/hashing/tests/test_hash_map.py diff --git a/data_structures/hashing/hash_map.py b/data_structures/hashing/hash_map.py new file mode 100644 index 000000000..1dfcc8bbf --- /dev/null +++ b/data_structures/hashing/hash_map.py @@ -0,0 +1,162 @@ +""" +Hash map with open addressing. + +https://en.wikipedia.org/wiki/Hash_table + +Another hash map implementation, with a good explanation. +Modern Dictionaries by Raymond Hettinger +https://www.youtube.com/watch?v=p33CVV29OG8 +""" +from collections.abc import Iterator, MutableMapping +from dataclasses import dataclass +from typing import Generic, TypeVar + +KEY = TypeVar("KEY") +VAL = TypeVar("VAL") + + +@dataclass(frozen=True, slots=True) +class _Item(Generic[KEY, VAL]): + key: KEY + val: VAL + + +class _DeletedItem(_Item): + def __init__(self) -> None: + super().__init__(None, None) + + def __bool__(self) -> bool: + return False + + +_deleted = _DeletedItem() + + +class HashMap(MutableMapping[KEY, VAL]): + """ + Hash map with open addressing. + """ + + def __init__( + self, initial_block_size: int = 8, capacity_factor: float = 0.75 + ) -> None: + self._initial_block_size = initial_block_size + self._buckets: list[_Item | None] = [None] * initial_block_size + assert 0.0 < capacity_factor < 1.0 + self._capacity_factor = capacity_factor + self._len = 0 + + def _get_bucket_index(self, key: KEY) -> int: + return hash(key) % len(self._buckets) + + def _get_next_ind(self, ind: int) -> int: + """ + Get next index. + + Implements linear open addressing. + """ + return (ind + 1) % len(self._buckets) + + def _try_set(self, ind: int, key: KEY, val: VAL) -> bool: + """ + Try to add value to the bucket. + + If bucket is empty or key is the same, does insert and return True. + + If bucket has another key or deleted placeholder, + that means that we need to check next bucket. + """ + stored = self._buckets[ind] + if not stored: + self._buckets[ind] = _Item(key, val) + self._len += 1 + return True + elif stored.key == key: + self._buckets[ind] = _Item(key, val) + return True + else: + return False + + def _is_full(self) -> bool: + """ + Return true if we have reached safe capacity. + + So we need to increase the number of buckets to avoid collisions. + """ + limit = len(self._buckets) * self._capacity_factor + return len(self) >= int(limit) + + def _is_sparse(self) -> bool: + """Return true if we need twice fewer buckets when we have now.""" + if len(self._buckets) <= self._initial_block_size: + return False + limit = len(self._buckets) * self._capacity_factor / 2 + return len(self) < limit + + def _resize(self, new_size: int) -> None: + old_buckets = self._buckets + self._buckets = [None] * new_size + self._len = 0 + for item in old_buckets: + if item: + self._add_item(item.key, item.val) + + def _size_up(self) -> None: + self._resize(len(self._buckets) * 2) + + def _size_down(self) -> None: + self._resize(len(self._buckets) // 2) + + def _iterate_buckets(self, key: KEY) -> Iterator[int]: + ind = self._get_bucket_index(key) + for _ in range(len(self._buckets)): + yield ind + ind = self._get_next_ind(ind) + + def _add_item(self, key: KEY, val: VAL) -> None: + for ind in self._iterate_buckets(key): + if self._try_set(ind, key, val): + break + + def __setitem__(self, key: KEY, val: VAL) -> None: + if self._is_full(): + self._size_up() + + self._add_item(key, val) + + def __delitem__(self, key: KEY) -> None: + for ind in self._iterate_buckets(key): + item = self._buckets[ind] + if item is None: + raise KeyError(key) + if item is _deleted: + continue + if item.key == key: + self._buckets[ind] = _deleted + self._len -= 1 + break + if self._is_sparse(): + self._size_down() + + def __getitem__(self, key: KEY) -> VAL: + for ind in self._iterate_buckets(key): + item = self._buckets[ind] + if item is None: + break + if item is _deleted: + continue + if item.key == key: + return item.val + raise KeyError(key) + + def __len__(self) -> int: + return self._len + + def __iter__(self) -> Iterator[KEY]: + yield from (item.key for item in self._buckets if item) + + def __repr__(self) -> str: + val_string = " ,".join( + f"{item.key}: {item.val}" for item in self._buckets if item + ) + return f"HashMap({val_string})" diff --git a/data_structures/hashing/tests/test_hash_map.py b/data_structures/hashing/tests/test_hash_map.py new file mode 100644 index 000000000..929e67311 --- /dev/null +++ b/data_structures/hashing/tests/test_hash_map.py @@ -0,0 +1,97 @@ +from operator import delitem, getitem, setitem + +import pytest + +from data_structures.hashing.hash_map import HashMap + + +def _get(k): + return getitem, k + + +def _set(k, v): + return setitem, k, v + + +def _del(k): + return delitem, k + + +def _run_operation(obj, fun, *args): + try: + return fun(obj, *args), None + except Exception as e: + return None, e + + +_add_items = ( + _set("key_a", "val_a"), + _set("key_b", "val_b"), +) + +_overwrite_items = [ + _set("key_a", "val_a"), + _set("key_a", "val_b"), +] + +_delete_items = [ + _set("key_a", "val_a"), + _set("key_b", "val_b"), + _del("key_a"), + _del("key_b"), + _set("key_a", "val_a"), + _del("key_a"), +] + +_access_absent_items = [ + _get("key_a"), + _del("key_a"), + _set("key_a", "val_a"), + _del("key_a"), + _del("key_a"), + _get("key_a"), +] + +_add_with_resize_up = [ + *[_set(x, x) for x in range(5)], # guaranteed upsize +] + +_add_with_resize_down = [ + *[_set(x, x) for x in range(5)], # guaranteed upsize + *[_del(x) for x in range(5)], + _set("key_a", "val_b"), +] + + +@pytest.mark.parametrize( + "operations", + ( + pytest.param(_add_items, id="add items"), + pytest.param(_overwrite_items, id="overwrite items"), + pytest.param(_delete_items, id="delete items"), + pytest.param(_access_absent_items, id="access absent items"), + pytest.param(_add_with_resize_up, id="add with resize up"), + pytest.param(_add_with_resize_down, id="add with resize down"), + ), +) +def test_hash_map_is_the_same_as_dict(operations): + my = HashMap(initial_block_size=4) + py = {} + for _, (fun, *args) in enumerate(operations): + my_res, my_exc = _run_operation(my, fun, *args) + py_res, py_exc = _run_operation(py, fun, *args) + assert my_res == py_res + assert str(my_exc) == str(py_exc) + assert set(py) == set(my) + assert len(py) == len(my) + assert set(my.items()) == set(py.items()) + + +def test_no_new_methods_was_added_to_api(): + def is_public(name: str) -> bool: + return not name.startswith("_") + + dict_public_names = {name for name in dir({}) if is_public(name)} + hash_public_names = {name for name in dir(HashMap()) if is_public(name)} + + assert dict_public_names > hash_public_names From 9701e459e884e883fc720277452ec592eae305d0 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Tue, 14 Mar 2023 08:39:36 +0300 Subject: [PATCH 598/726] Add Project Euler problem 100 solution 1 (#8175) Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- DIRECTORY.md | 2 ++ project_euler/problem_100/__init__.py | 0 project_euler/problem_100/sol1.py | 48 +++++++++++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 project_euler/problem_100/__init__.py create mode 100644 project_euler/problem_100/sol1.py diff --git a/DIRECTORY.md b/DIRECTORY.md index b2daaaa9c..e1ce44eed 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -937,6 +937,8 @@ * [Sol1](project_euler/problem_097/sol1.py) * Problem 099 * [Sol1](project_euler/problem_099/sol1.py) + * Problem 100 + * [Sol1](project_euler/problem_100/sol1.py) * Problem 101 * [Sol1](project_euler/problem_101/sol1.py) * Problem 102 diff --git a/project_euler/problem_100/__init__.py b/project_euler/problem_100/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_100/sol1.py b/project_euler/problem_100/sol1.py new file mode 100644 index 000000000..367378e7a --- /dev/null +++ b/project_euler/problem_100/sol1.py @@ -0,0 +1,48 @@ +""" +Project Euler Problem 100: https://projecteuler.net/problem=100 + +If a box contains twenty-one coloured discs, composed of fifteen blue discs and +six red discs, and two discs were taken at random, it can be seen that +the probability of taking two blue discs, P(BB) = (15/21) x (14/20) = 1/2. + +The next such arrangement, for which there is exactly 50% chance of taking two blue +discs at random, is a box containing eighty-five blue discs and thirty-five red discs. + +By finding the first arrangement to contain over 10^12 = 1,000,000,000,000 discs +in total, determine the number of blue discs that the box would contain. +""" + + +def solution(min_total: int = 10**12) -> int: + """ + Returns the number of blue discs for the first arrangement to contain + over min_total discs in total + + >>> solution(2) + 3 + + >>> solution(4) + 15 + + >>> solution(21) + 85 + """ + + prev_numerator = 1 + prev_denominator = 0 + + numerator = 1 + denominator = 1 + + while numerator <= 2 * min_total - 1: + prev_numerator += 2 * numerator + numerator += 2 * prev_numerator + + prev_denominator += 2 * denominator + denominator += 2 * prev_denominator + + return (denominator + 1) // 2 + + +if __name__ == "__main__": + print(f"{solution() = }") From 47b3c729826e864fb1d0a30b03cf95fa2adae591 Mon Sep 17 00:00:00 2001 From: David Leal Date: Mon, 13 Mar 2023 23:46:52 -0600 Subject: [PATCH 599/726] docs: add the other/miscellaneous form (#8163) Co-authored-by: Christian Clauss Co-authored-by: Dhruv Manilawala --- .github/ISSUE_TEMPLATE/other.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/other.yml diff --git a/.github/ISSUE_TEMPLATE/other.yml b/.github/ISSUE_TEMPLATE/other.yml new file mode 100644 index 000000000..44d6ff541 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/other.yml @@ -0,0 +1,19 @@ +name: Other +description: Use this for any other issues. PLEASE do not create blank issues +labels: ["awaiting triage"] +body: + - type: textarea + id: issuedescription + attributes: + label: What would you like to share? + description: Provide a clear and concise explanation of your issue. + validations: + required: true + + - type: textarea + id: extrainfo + attributes: + label: Additional information + description: Is there anything else we should know about this issue? + validations: + required: false From adc3ccdabede375df5cff62c3c8f06d8a191a803 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Wed, 15 Mar 2023 15:56:03 +0300 Subject: [PATCH 600/726] Add Project Euler problem 131 solution 1 (#8179) Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- DIRECTORY.md | 5 +++ project_euler/problem_131/__init__.py | 0 project_euler/problem_131/sol1.py | 56 +++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 project_euler/problem_131/__init__.py create mode 100644 project_euler/problem_131/sol1.py diff --git a/DIRECTORY.md b/DIRECTORY.md index e1ce44eed..1d3177801 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -196,11 +196,14 @@ * [Disjoint Set](data_structures/disjoint_set/disjoint_set.py) * Hashing * [Double Hash](data_structures/hashing/double_hash.py) + * [Hash Map](data_structures/hashing/hash_map.py) * [Hash Table](data_structures/hashing/hash_table.py) * [Hash Table With Linked List](data_structures/hashing/hash_table_with_linked_list.py) * Number Theory * [Prime Numbers](data_structures/hashing/number_theory/prime_numbers.py) * [Quadratic Probing](data_structures/hashing/quadratic_probing.py) + * Tests + * [Test Hash Map](data_structures/hashing/tests/test_hash_map.py) * Heap * [Binomial Heap](data_structures/heap/binomial_heap.py) * [Heap](data_structures/heap/heap.py) @@ -973,6 +976,8 @@ * [Sol1](project_euler/problem_125/sol1.py) * Problem 129 * [Sol1](project_euler/problem_129/sol1.py) + * Problem 131 + * [Sol1](project_euler/problem_131/sol1.py) * Problem 135 * [Sol1](project_euler/problem_135/sol1.py) * Problem 144 diff --git a/project_euler/problem_131/__init__.py b/project_euler/problem_131/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_131/sol1.py b/project_euler/problem_131/sol1.py new file mode 100644 index 000000000..f5302aac8 --- /dev/null +++ b/project_euler/problem_131/sol1.py @@ -0,0 +1,56 @@ +""" +Project Euler Problem 131: https://projecteuler.net/problem=131 + +There are some prime values, p, for which there exists a positive integer, n, +such that the expression n^3 + n^2p is a perfect cube. + +For example, when p = 19, 8^3 + 8^2 x 19 = 12^3. + +What is perhaps most surprising is that for each prime with this property +the value of n is unique, and there are only four such primes below one-hundred. + +How many primes below one million have this remarkable property? +""" + +from math import isqrt + + +def is_prime(number: int) -> bool: + """ + Determines whether number is prime + + >>> is_prime(3) + True + + >>> is_prime(4) + False + """ + + for divisor in range(2, isqrt(number) + 1): + if number % divisor == 0: + return False + return True + + +def solution(max_prime: int = 10**6) -> int: + """ + Returns number of primes below max_prime with the property + + >>> solution(100) + 4 + """ + + primes_count = 0 + cube_index = 1 + prime_candidate = 7 + while prime_candidate < max_prime: + primes_count += is_prime(prime_candidate) + + cube_index += 1 + prime_candidate += 6 * cube_index + + return primes_count + + +if __name__ == "__main__": + print(f"{solution() = }") From c96241b5a5052af466894ef90c7a7c749ba872eb Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 15 Mar 2023 13:58:25 +0100 Subject: [PATCH 601/726] Replace bandit, flake8, isort, and pyupgrade with ruff (#8178) * Replace bandit, flake8, isort, and pyupgrade with ruff * Comment on ruff rules * updating DIRECTORY.md --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .flake8 | 10 --- .github/workflows/ruff.yml | 16 ++++ .pre-commit-config.yaml | 78 +++++-------------- arithmetic_analysis/newton_raphson.py | 2 +- arithmetic_analysis/newton_raphson_new.py | 2 +- data_structures/heap/heap_generic.py | 1 - dynamic_programming/min_distance_up_bottom.py | 9 +-- dynamic_programming/minimum_tickets_cost.py | 4 +- dynamic_programming/word_break.py | 4 +- hashes/sha1.py | 12 +-- machine_learning/support_vector_machines.py | 4 +- maths/eulers_totient.py | 34 ++++---- maths/fibonacci.py | 4 +- maths/pythagoras.py | 6 +- other/quine.py | 1 + project_euler/problem_075/sol1.py | 3 +- pyproject.toml | 59 ++++++++++++-- sorts/external_sort.py | 2 +- strings/check_anagrams.py | 3 +- strings/word_occurrence.py | 3 +- web_programming/currency_converter.py | 2 +- 21 files changed, 127 insertions(+), 132 deletions(-) delete mode 100644 .flake8 create mode 100644 .github/workflows/ruff.yml diff --git a/.flake8 b/.flake8 deleted file mode 100644 index b68ee8533..000000000 --- a/.flake8 +++ /dev/null @@ -1,10 +0,0 @@ -[flake8] -max-line-length = 88 -# max-complexity should be 10 -max-complexity = 19 -extend-ignore = - # Formatting style for `black` - # E203 is whitespace before ':' - E203, - # W503 is line break occurred before a binary operator - W503 diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml new file mode 100644 index 000000000..ca2d5be47 --- /dev/null +++ b/.github/workflows/ruff.yml @@ -0,0 +1,16 @@ +# https://beta.ruff.rs +name: ruff +on: + push: + branches: + - master + pull_request: + branches: + - master +jobs: + ruff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - run: pip install --user ruff + - run: ruff --format=github . diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9aa965e42..82aad6c65 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,6 +3,7 @@ repos: rev: v4.4.0 hooks: - id: check-executables-have-shebangs + - id: check-toml - id: check-yaml - id: end-of-file-fixer types: [python] @@ -14,60 +15,41 @@ repos: hooks: - id: auto-walrus + - repo: https://github.com/charliermarsh/ruff-pre-commit + rev: v0.0.255 + hooks: + - id: ruff + - repo: https://github.com/psf/black rev: 23.1.0 hooks: - id: black - - repo: https://github.com/PyCQA/isort - rev: 5.12.0 + - repo: https://github.com/codespell-project/codespell + rev: v2.2.4 hooks: - - id: isort - args: - - --profile=black + - id: codespell + additional_dependencies: + - tomli - repo: https://github.com/tox-dev/pyproject-fmt rev: "0.9.2" hooks: - id: pyproject-fmt + - repo: local + hooks: + - id: validate-filenames + name: Validate filenames + entry: ./scripts/validate_filenames.py + language: script + pass_filenames: false + - repo: https://github.com/abravalheri/validate-pyproject rev: v0.12.1 hooks: - id: validate-pyproject - - repo: https://github.com/asottile/pyupgrade - rev: v3.3.1 - hooks: - - id: pyupgrade - args: - - --py311-plus - - - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.255 - hooks: - - id: ruff - args: - - --ignore=E741 - - - repo: https://github.com/PyCQA/flake8 - rev: 6.0.0 - hooks: - - id: flake8 # See .flake8 for args - additional_dependencies: &flake8-plugins - - flake8-bugbear - - flake8-builtins - # - flake8-broken-line - - flake8-comprehensions - - pep8-naming - - - repo: https://github.com/asottile/yesqa - rev: v1.4.0 - hooks: - - id: yesqa - additional_dependencies: - *flake8-plugins - - repo: https://github.com/pre-commit/mirrors-mypy rev: v1.1.1 hooks: @@ -77,25 +59,3 @@ repos: - --install-types # See mirrors-mypy README.md - --non-interactive additional_dependencies: [types-requests] - - - repo: https://github.com/codespell-project/codespell - rev: v2.2.4 - hooks: - - id: codespell - args: - - --ignore-words-list=3rt,ans,crate,damon,fo,followings,hist,iff,kwanza,mater,secant,som,sur,tim,zar - exclude: | - (?x)^( - ciphers/prehistoric_men.txt | - strings/dictionary.txt | - strings/words.txt | - project_euler/problem_022/p022_names.txt - )$ - - - repo: local - hooks: - - id: validate-filenames - name: Validate filenames - entry: ./scripts/validate_filenames.py - language: script - pass_filenames: false diff --git a/arithmetic_analysis/newton_raphson.py b/arithmetic_analysis/newton_raphson.py index 86ff9d350..aee2f07e5 100644 --- a/arithmetic_analysis/newton_raphson.py +++ b/arithmetic_analysis/newton_raphson.py @@ -5,7 +5,7 @@ from __future__ import annotations from decimal import Decimal -from math import * # noqa: F401, F403 +from math import * # noqa: F403 from sympy import diff diff --git a/arithmetic_analysis/newton_raphson_new.py b/arithmetic_analysis/newton_raphson_new.py index 472cb5b5a..f61841e2e 100644 --- a/arithmetic_analysis/newton_raphson_new.py +++ b/arithmetic_analysis/newton_raphson_new.py @@ -8,7 +8,7 @@ # Newton's Method - https://en.wikipedia.org/wiki/Newton's_method from sympy import diff, lambdify, symbols -from sympy.functions import * # noqa: F401, F403 +from sympy.functions import * # noqa: F403 def newton_raphson( diff --git a/data_structures/heap/heap_generic.py b/data_structures/heap/heap_generic.py index b4d7019f4..ee92149e2 100644 --- a/data_structures/heap/heap_generic.py +++ b/data_structures/heap/heap_generic.py @@ -166,7 +166,6 @@ def test_heap() -> None: >>> h.get_top() [9, -40] """ - pass if __name__ == "__main__": diff --git a/dynamic_programming/min_distance_up_bottom.py b/dynamic_programming/min_distance_up_bottom.py index 49c361f24..4870c7ef4 100644 --- a/dynamic_programming/min_distance_up_bottom.py +++ b/dynamic_programming/min_distance_up_bottom.py @@ -6,13 +6,13 @@ to find edit distance. The aim is to demonstate up bottom approach for solving the task. The implementation was tested on the leetcode: https://leetcode.com/problems/edit-distance/ -""" -""" Levinstein distance Dynamic Programming: up -> down. """ +import functools + def min_distance_up_bottom(word1: str, word2: str) -> int: """ @@ -25,13 +25,10 @@ def min_distance_up_bottom(word1: str, word2: str) -> int: >>> min_distance_up_bottom("zooicoarchaeologist", "zoologist") 10 """ - - from functools import lru_cache - len_word1 = len(word1) len_word2 = len(word2) - @lru_cache(maxsize=None) + @functools.cache def min_distance(index1: int, index2: int) -> int: # if first word index is overflow - delete all from the second word if index1 >= len_word1: diff --git a/dynamic_programming/minimum_tickets_cost.py b/dynamic_programming/minimum_tickets_cost.py index d07056d92..6790c21f1 100644 --- a/dynamic_programming/minimum_tickets_cost.py +++ b/dynamic_programming/minimum_tickets_cost.py @@ -22,7 +22,7 @@ Minimum Cost For Tickets Dynamic Programming: up -> down. """ -from functools import lru_cache +import functools def mincost_tickets(days: list[int], costs: list[int]) -> int: @@ -106,7 +106,7 @@ def mincost_tickets(days: list[int], costs: list[int]) -> int: days_set = set(days) - @lru_cache(maxsize=None) + @functools.cache def dynamic_programming(index: int) -> int: if index > 365: return 0 diff --git a/dynamic_programming/word_break.py b/dynamic_programming/word_break.py index 642ea0edf..4d7ac8690 100644 --- a/dynamic_programming/word_break.py +++ b/dynamic_programming/word_break.py @@ -20,7 +20,7 @@ Runtime: O(n * n) Space: O(n) """ -from functools import lru_cache +import functools from typing import Any @@ -80,7 +80,7 @@ def word_break(string: str, words: list[str]) -> bool: len_string = len(string) # Dynamic programming method - @lru_cache(maxsize=None) + @functools.cache def is_breakable(index: int) -> bool: """ >>> string = 'a' diff --git a/hashes/sha1.py b/hashes/sha1.py index b19e0cfaf..9f0437f20 100644 --- a/hashes/sha1.py +++ b/hashes/sha1.py @@ -26,7 +26,6 @@ Reference: https://deadhacker.com/2006/02/21/sha-1-illustrated/ import argparse import hashlib # hashlib is only used inside the Test class import struct -import unittest class SHA1Hash: @@ -128,14 +127,9 @@ class SHA1Hash: return "%08x%08x%08x%08x%08x" % tuple(self.h) -class SHA1HashTest(unittest.TestCase): - """ - Test class for the SHA1Hash class. Inherits the TestCase class from unittest - """ - - def testMatchHashes(self): # noqa: N802 - msg = bytes("Test String", "utf-8") - self.assertEqual(SHA1Hash(msg).final_hash(), hashlib.sha1(msg).hexdigest()) +def test_sha1_hash(): + msg = b"Test String" + assert SHA1Hash(msg).final_hash() == hashlib.sha1(msg).hexdigest() # noqa: S324 def main(): diff --git a/machine_learning/support_vector_machines.py b/machine_learning/support_vector_machines.py index caec10175..df854cc85 100644 --- a/machine_learning/support_vector_machines.py +++ b/machine_learning/support_vector_machines.py @@ -56,7 +56,7 @@ class SVC: *, regularization: float = np.inf, kernel: str = "linear", - gamma: float = 0, + gamma: float = 0.0, ) -> None: self.regularization = regularization self.gamma = gamma @@ -65,7 +65,7 @@ class SVC: elif kernel == "rbf": if self.gamma == 0: raise ValueError("rbf kernel requires gamma") - if not (isinstance(self.gamma, float) or isinstance(self.gamma, int)): + if not isinstance(self.gamma, (float, int)): raise ValueError("gamma must be float or int") if not self.gamma > 0: raise ValueError("gamma must be > 0") diff --git a/maths/eulers_totient.py b/maths/eulers_totient.py index 6a35e69bd..a15664703 100644 --- a/maths/eulers_totient.py +++ b/maths/eulers_totient.py @@ -1,5 +1,20 @@ # Eulers Totient function finds the number of relative primes of a number n from 1 to n def totient(n: int) -> list: + """ + >>> n = 10 + >>> totient_calculation = totient(n) + >>> for i in range(1, n): + ... print(f"{i} has {totient_calculation[i]} relative primes.") + 1 has 0 relative primes. + 2 has 1 relative primes. + 3 has 2 relative primes. + 4 has 2 relative primes. + 5 has 4 relative primes. + 6 has 2 relative primes. + 7 has 6 relative primes. + 8 has 4 relative primes. + 9 has 6 relative primes. + """ is_prime = [True for i in range(n + 1)] totients = [i - 1 for i in range(n + 1)] primes = [] @@ -20,25 +35,6 @@ def totient(n: int) -> list: return totients -def test_totient() -> None: - """ - >>> n = 10 - >>> totient_calculation = totient(n) - >>> for i in range(1, n): - ... print(f"{i} has {totient_calculation[i]} relative primes.") - 1 has 0 relative primes. - 2 has 1 relative primes. - 3 has 2 relative primes. - 4 has 2 relative primes. - 5 has 4 relative primes. - 6 has 2 relative primes. - 7 has 6 relative primes. - 8 has 4 relative primes. - 9 has 6 relative primes. - """ - pass - - if __name__ == "__main__": import doctest diff --git a/maths/fibonacci.py b/maths/fibonacci.py index d58c9fc68..e810add69 100644 --- a/maths/fibonacci.py +++ b/maths/fibonacci.py @@ -16,7 +16,7 @@ fib_memoization runtime: 0.0107 ms fib_binet runtime: 0.0174 ms """ -from functools import lru_cache +import functools from math import sqrt from time import time @@ -110,7 +110,7 @@ def fib_recursive_cached(n: int) -> list[int]: Exception: n is negative """ - @lru_cache(maxsize=None) + @functools.cache def fib_recursive_term(i: int) -> int: """ Calculates the i-th (0-indexed) Fibonacci number using recursion diff --git a/maths/pythagoras.py b/maths/pythagoras.py index 69a17731a..7770e981d 100644 --- a/maths/pythagoras.py +++ b/maths/pythagoras.py @@ -14,17 +14,13 @@ class Point: def distance(a: Point, b: Point) -> float: - return math.sqrt(abs((b.x - a.x) ** 2 + (b.y - a.y) ** 2 + (b.z - a.z) ** 2)) - - -def test_distance() -> None: """ >>> point1 = Point(2, -1, 7) >>> point2 = Point(1, -3, 5) >>> print(f"Distance from {point1} to {point2} is {distance(point1, point2)}") Distance from Point(2, -1, 7) to Point(1, -3, 5) is 3.0 """ - pass + return math.sqrt(abs((b.x - a.x) ** 2 + (b.y - a.y) ** 2 + (b.z - a.z) ** 2)) if __name__ == "__main__": diff --git a/other/quine.py b/other/quine.py index 01e03bbb0..500a351d3 100644 --- a/other/quine.py +++ b/other/quine.py @@ -1,4 +1,5 @@ #!/bin/python3 +# ruff: noqa """ Quine: diff --git a/project_euler/problem_075/sol1.py b/project_euler/problem_075/sol1.py index b57604d76..0ccaf5dee 100644 --- a/project_euler/problem_075/sol1.py +++ b/project_euler/problem_075/sol1.py @@ -29,7 +29,6 @@ Reference: https://en.wikipedia.org/wiki/Pythagorean_triple#Generating_a_triple from collections import defaultdict from math import gcd -from typing import DefaultDict def solution(limit: int = 1500000) -> int: @@ -43,7 +42,7 @@ def solution(limit: int = 1500000) -> int: >>> solution(50000) 5502 """ - frequencies: DefaultDict = defaultdict(int) + frequencies: defaultdict = defaultdict(int) euclid_m = 2 while 2 * euclid_m * (euclid_m + 1) <= limit: for euclid_n in range((euclid_m % 2) + 1, euclid_m, 2): diff --git a/pyproject.toml b/pyproject.toml index 5f9b1aa06..6552101d2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,8 +12,57 @@ addopts = [ omit = [".env/*"] sort = "Cover" -#[report] -#sort = Cover -#omit = -# .env/* -# backtracking/* +[tool.codespell] +ignore-words-list = "3rt,ans,crate,damon,fo,followings,hist,iff,kwanza,mater,secant,som,sur,tim,zar" +skip = "./.*,*.json,ciphers/prehistoric_men.txt,project_euler/problem_022/p022_names.txt,pyproject.toml,strings/dictionary.txt,strings/words.txt" + +[tool.ruff] +ignore = [ # `ruff rule S101` for a description of that rule + "B904", # B904: Within an `except` clause, raise exceptions with `raise ... from err` + "B905", # B905: `zip()` without an explicit `strict=` parameter + "E741", # E741: Ambiguous variable name 'l' + "G004", # G004 Logging statement uses f-string + "N999", # N999: Invalid module name + "PLC1901", # PLC1901: `{}` can be simplified to `{}` as an empty string is falsey + "PLR2004", # PLR2004: Magic value used in comparison + "PLR5501", # PLR5501: Consider using `elif` instead of `else` + "PLW0120", # PLW0120: `else` clause on loop without a `break` statement + "PLW060", # PLW060: Using global for `{name}` but no assignment is done -- DO NOT FIX + "PLW2901", # PLW2901: Redefined loop variable + "RUF00", # RUF00: Ambiguous unicode character -- DO NOT FIX + "RUF100", # RUF100: Unused `noqa` directive + "S101", # S101: Use of `assert` detected -- DO NOT FIX + "S105", # S105: Possible hardcoded password: 'password' + "S113", # S113: Probable use of requests call without timeout + "UP038", # UP038: Use `X | Y` in `{}` call instead of `(X, Y)` -- DO NOT FIX +] +select = [ # https://beta.ruff.rs/docs/rules + "A", # A: builtins + "B", # B: bugbear + "C40", # C40: comprehensions + "C90", # C90: mccabe code complexity + "E", # E: pycodestyle errors + "F", # F: pyflakes + "G", # G: logging format + "I", # I: isort + "N", # N: pep8 naming + "PL", # PL: pylint + "PIE", # PIE: pie + "PYI", # PYI: type hinting stub files + "RUF", # RUF: ruff + "S", # S: bandit + "TID", # TID: tidy imports + "UP", # UP: pyupgrade + "W", # W: pycodestyle warnings + "YTT", # YTT: year 2020 +] +target-version = "py311" + +[tool.ruff.mccabe] # DO NOT INCREASE THIS VALUE +max-complexity = 20 # default: 10 + +[tool.ruff.pylint] # DO NOT INCREASE THESE VALUES +max-args = 10 # default: 5 +max-branches = 20 # default: 12 +max-returns = 8 # default: 6 +max-statements = 88 # default: 50 diff --git a/sorts/external_sort.py b/sorts/external_sort.py index 7af7dc0a6..e6b0d47f7 100644 --- a/sorts/external_sort.py +++ b/sorts/external_sort.py @@ -104,7 +104,7 @@ class FileMerger: files = {} for i in range(len(filenames)): - files[i] = open(filenames[i], "r", buffer_size) + files[i] = open(filenames[i], "r", buffer_size) # noqa: UP015 return files diff --git a/strings/check_anagrams.py b/strings/check_anagrams.py index a364b9821..9dcdffcfb 100644 --- a/strings/check_anagrams.py +++ b/strings/check_anagrams.py @@ -2,7 +2,6 @@ wiki: https://en.wikipedia.org/wiki/Anagram """ from collections import defaultdict -from typing import DefaultDict def check_anagrams(first_str: str, second_str: str) -> bool: @@ -30,7 +29,7 @@ def check_anagrams(first_str: str, second_str: str) -> bool: return False # Default values for count should be 0 - count: DefaultDict[str, int] = defaultdict(int) + count: defaultdict[str, int] = defaultdict(int) # For each character in input strings, # increment count in the corresponding diff --git a/strings/word_occurrence.py b/strings/word_occurrence.py index 8260620c3..5a18ebf77 100644 --- a/strings/word_occurrence.py +++ b/strings/word_occurrence.py @@ -1,7 +1,6 @@ # Created by sarathkaul on 17/11/19 # Modified by Arkadip Bhattacharya(@darkmatter18) on 20/04/2020 from collections import defaultdict -from typing import DefaultDict def word_occurrence(sentence: str) -> dict: @@ -15,7 +14,7 @@ def word_occurrence(sentence: str) -> dict: >>> dict(word_occurrence("Two spaces")) {'Two': 1, 'spaces': 1} """ - occurrence: DefaultDict[str, int] = defaultdict(int) + occurrence: defaultdict[str, int] = defaultdict(int) # Creating a dictionary containing count of each word for word in sentence.split(): occurrence[word] += 1 diff --git a/web_programming/currency_converter.py b/web_programming/currency_converter.py index 6fcc60e8f..69f2a2c4d 100644 --- a/web_programming/currency_converter.py +++ b/web_programming/currency_converter.py @@ -8,7 +8,7 @@ import os import requests URL_BASE = "https://www.amdoren.com/api/currency.php" -TESTING = os.getenv("CI", False) +TESTING = os.getenv("CI", "") API_KEY = os.getenv("AMDOREN_API_KEY", "") if not API_KEY and not TESTING: From 521fbca61c6bdb84746564eb58c2ef2131260187 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 16 Mar 2023 13:31:29 +0100 Subject: [PATCH 602/726] Replace flake8 with ruff (#8184) --- CONTRIBUTING.md | 6 +++--- audio_filters/equal_loudness_filter.py.broken.txt | 2 +- data_structures/binary_tree/red_black_tree.py | 4 ++-- digital_image_processing/change_contrast.py | 4 ++-- maths/is_square_free.py | 4 ++-- maths/mobius_function.py | 4 ++-- other/linear_congruential_generator.py | 8 ++++---- pyproject.toml | 1 + quantum/ripple_adder_classic.py | 6 +++--- 9 files changed, 20 insertions(+), 19 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3ce5bd1ed..6b6e4d21b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -81,11 +81,11 @@ We want your work to be readable by others; therefore, we encourage you to note black . ``` -- All submissions will need to pass the test `flake8 . --ignore=E203,W503 --max-line-length=88` before they will be accepted so if possible, try this test locally on your Python file(s) before submitting your pull request. +- All submissions will need to pass the test `ruff .` before they will be accepted so if possible, try this test locally on your Python file(s) before submitting your pull request. ```bash - python3 -m pip install flake8 # only required the first time - flake8 . --ignore=E203,W503 --max-line-length=88 --show-source + python3 -m pip install ruff # only required the first time + ruff . ``` - Original code submission require docstrings or comments to describe your work. diff --git a/audio_filters/equal_loudness_filter.py.broken.txt b/audio_filters/equal_loudness_filter.py.broken.txt index b9a3c50e1..88cba8533 100644 --- a/audio_filters/equal_loudness_filter.py.broken.txt +++ b/audio_filters/equal_loudness_filter.py.broken.txt @@ -20,7 +20,7 @@ class EqualLoudnessFilter: samplerate, use with caution. Code based on matlab implementation at https://bit.ly/3eqh2HU - (url shortened for flake8) + (url shortened for ruff) Target curve: https://i.imgur.com/3g2VfaM.png Yulewalk response: https://i.imgur.com/J9LnJ4C.png diff --git a/data_structures/binary_tree/red_black_tree.py b/data_structures/binary_tree/red_black_tree.py index b50d75d33..3ebc8d639 100644 --- a/data_structures/binary_tree/red_black_tree.py +++ b/data_structures/binary_tree/red_black_tree.py @@ -1,6 +1,6 @@ """ -python/black : true -flake8 : passed +psf/black : true +ruff : passed """ from __future__ import annotations diff --git a/digital_image_processing/change_contrast.py b/digital_image_processing/change_contrast.py index 6a1504002..7e4969470 100644 --- a/digital_image_processing/change_contrast.py +++ b/digital_image_processing/change_contrast.py @@ -4,8 +4,8 @@ Changing contrast with PIL This algorithm is used in https://noivce.pythonanywhere.com/ Python web app. -python/black: True -flake8 : True +psf/black: True +ruff : True """ from PIL import Image diff --git a/maths/is_square_free.py b/maths/is_square_free.py index 4134398d2..08c70dc32 100644 --- a/maths/is_square_free.py +++ b/maths/is_square_free.py @@ -1,7 +1,7 @@ """ References: wikipedia:square free number -python/black : True -flake8 : True +psf/black : True +ruff : True """ from __future__ import annotations diff --git a/maths/mobius_function.py b/maths/mobius_function.py index 4fcf35f21..8abdc4caf 100644 --- a/maths/mobius_function.py +++ b/maths/mobius_function.py @@ -1,8 +1,8 @@ """ References: https://en.wikipedia.org/wiki/M%C3%B6bius_function References: wikipedia:square free number -python/black : True -flake8 : True +psf/black : True +ruff : True """ from maths.is_square_free import is_square_free diff --git a/other/linear_congruential_generator.py b/other/linear_congruential_generator.py index 777ee6355..c016310f9 100644 --- a/other/linear_congruential_generator.py +++ b/other/linear_congruential_generator.py @@ -9,10 +9,10 @@ class LinearCongruentialGenerator: """ # The default value for **seed** is the result of a function call which is not - # normally recommended and causes flake8-bugbear to raise a B008 error. However, - # in this case, it is accptable because `LinearCongruentialGenerator.__init__()` - # will only be called once per instance and it ensures that each instance will - # generate a unique sequence of numbers. + # normally recommended and causes ruff to raise a B008 error. However, in this case, + # it is accptable because `LinearCongruentialGenerator.__init__()` will only be + # called once per instance and it ensures that each instance will generate a unique + # sequence of numbers. def __init__(self, multiplier, increment, modulo, seed=int(time())): # noqa: B008 """ diff --git a/pyproject.toml b/pyproject.toml index 6552101d2..169c3a71b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,6 +56,7 @@ select = [ # https://beta.ruff.rs/docs/rules "W", # W: pycodestyle warnings "YTT", # YTT: year 2020 ] +show-source = true target-version = "py311" [tool.ruff.mccabe] # DO NOT INCREASE THIS VALUE diff --git a/quantum/ripple_adder_classic.py b/quantum/ripple_adder_classic.py index c07757af7..b604395bc 100644 --- a/quantum/ripple_adder_classic.py +++ b/quantum/ripple_adder_classic.py @@ -54,9 +54,9 @@ def full_adder( # The default value for **backend** is the result of a function call which is not -# normally recommended and causes flake8-bugbear to raise a B008 error. However, -# in this case, this is acceptable because `Aer.get_backend()` is called when the -# function is defined and that same backend is then reused for all function calls. +# normally recommended and causes ruff to raise a B008 error. However, in this case, +# this is acceptable because `Aer.get_backend()` is called when the function is defined +# and that same backend is then reused for all function calls. def ripple_adder( From 3f9150c1b2dd15808a4962e03a1455f8d825512c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 22:16:13 +0100 Subject: [PATCH 603/726] [pre-commit.ci] pre-commit autoupdate (#8294) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/charliermarsh/ruff-pre-commit: v0.0.255 → v0.0.257](https://github.com/charliermarsh/ruff-pre-commit/compare/v0.0.255...v0.0.257) * Fix PLR1711 Useless statement at end of function --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .pre-commit-config.yaml | 2 +- data_structures/binary_tree/avl_tree.py | 4 ---- machine_learning/polymonial_regression.py | 1 - 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 82aad6c65..58cec4ff6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.255 + rev: v0.0.257 hooks: - id: ruff diff --git a/data_structures/binary_tree/avl_tree.py b/data_structures/binary_tree/avl_tree.py index 320e7ed0d..4c1fb17af 100644 --- a/data_structures/binary_tree/avl_tree.py +++ b/data_structures/binary_tree/avl_tree.py @@ -60,19 +60,15 @@ class MyNode: def set_data(self, data: Any) -> None: self.data = data - return def set_left(self, node: MyNode | None) -> None: self.left = node - return def set_right(self, node: MyNode | None) -> None: self.right = node - return def set_height(self, height: int) -> None: self.height = height - return def get_height(node: MyNode | None) -> int: diff --git a/machine_learning/polymonial_regression.py b/machine_learning/polymonial_regression.py index 374c35f7f..487fb8145 100644 --- a/machine_learning/polymonial_regression.py +++ b/machine_learning/polymonial_regression.py @@ -34,7 +34,6 @@ def viz_polymonial(): plt.xlabel("Position level") plt.ylabel("Salary") plt.show() - return if __name__ == "__main__": From 7cdb011ba440a07768179bfaea190bddefc890d8 Mon Sep 17 00:00:00 2001 From: Genesis <128913081+KaixLina@users.noreply.github.com> Date: Sun, 26 Mar 2023 20:49:18 +0530 Subject: [PATCH 604/726] New gitter link added or replaced (#8551) * New gitter link added * ruff==0.0.258 * noqa: S310 * noqa: S310 * Update ruff.yml * Add Ruff rule S311 * Ruff v0.0.259 * return ("{:08x}" * 5).format(*self.h) * pickle.load(f) # noqa: S301 --------- Co-authored-by: Christian Clauss --- .github/stale.yml | 4 ++-- .pre-commit-config.yaml | 2 +- CONTRIBUTING.md | 4 ++-- README.md | 4 ++-- hashes/sha1.py | 2 +- machine_learning/sequential_minimum_optimization.py | 2 +- neural_network/convolution_neural_network.py | 2 +- project_euler/README.md | 2 +- pyproject.toml | 1 + web_programming/download_images_from_google_query.py | 2 +- 10 files changed, 13 insertions(+), 12 deletions(-) diff --git a/.github/stale.yml b/.github/stale.yml index 36ca56266..813f68834 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -45,7 +45,7 @@ pulls: closeComment: > Please reopen this pull request once you commit the changes requested or make improvements on the code. If this is not the case and you need - some help, feel free to seek help from our [Gitter](https://gitter.im/TheAlgorithms) + some help, feel free to seek help from our [Gitter](https://app.gitter.im/#/room/#TheAlgorithms_community:gitter.im) or ping one of the reviewers. Thank you for your contributions! issues: @@ -59,5 +59,5 @@ issues: closeComment: > Please reopen this issue once you add more information and updates here. If this is not the case and you need some help, feel free to seek help - from our [Gitter](https://gitter.im/TheAlgorithms) or ping one of the + from our [Gitter](https://app.gitter.im/#/room/#TheAlgorithms_community:gitter.im) or ping one of the reviewers. Thank you for your contributions! diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 58cec4ff6..72a878387 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.257 + rev: v0.0.259 hooks: - id: ruff diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6b6e4d21b..75e4fb893 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ ## Before contributing -Welcome to [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python)! Before sending your pull requests, make sure that you __read the whole guidelines__. If you have any doubt on the contributing guide, please feel free to [state it clearly in an issue](https://github.com/TheAlgorithms/Python/issues/new) or ask the community in [Gitter](https://gitter.im/TheAlgorithms). +Welcome to [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python)! Before sending your pull requests, make sure that you __read the whole guidelines__. If you have any doubt on the contributing guide, please feel free to [state it clearly in an issue](https://github.com/TheAlgorithms/Python/issues/new) or ask the community in [Gitter](https://app.gitter.im/#/room/#TheAlgorithms_community:gitter.im). ## Contributing @@ -176,7 +176,7 @@ We want your work to be readable by others; therefore, we encourage you to note - Most importantly, - __Be consistent in the use of these guidelines when submitting.__ - - __Join__ us on [Discord](https://discord.com/invite/c7MnfGFGa6) and [Gitter](https://gitter.im/TheAlgorithms) __now!__ + - __Join__ us on [Discord](https://discord.com/invite/c7MnfGFGa6) and [Gitter](https://app.gitter.im/#/room/#TheAlgorithms_community:gitter.im) __now!__ - Happy coding! Writer [@poyea](https://github.com/poyea), Jun 2019. diff --git a/README.md b/README.md index 68a6e5e6f..3d2f1a110 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Discord chat - + Gitter chat @@ -42,7 +42,7 @@ Read through our [Contribution Guidelines](CONTRIBUTING.md) before you contribut ## Community Channels -We are on [Discord](https://discord.gg/c7MnfGFGa6) and [Gitter](https://gitter.im/TheAlgorithms)! Community channels are a great way for you to ask questions and get help. Please join us! +We are on [Discord](https://discord.gg/c7MnfGFGa6) and [Gitter](https://app.gitter.im/#/room/#TheAlgorithms_community:gitter.im)! Community channels are a great way for you to ask questions and get help. Please join us! ## List of Algorithms diff --git a/hashes/sha1.py b/hashes/sha1.py index 9f0437f20..b325ce3e4 100644 --- a/hashes/sha1.py +++ b/hashes/sha1.py @@ -124,7 +124,7 @@ class SHA1Hash: self.h[3] + d & 0xFFFFFFFF, self.h[4] + e & 0xFFFFFFFF, ) - return "%08x%08x%08x%08x%08x" % tuple(self.h) + return ("{:08x}" * 5).format(*self.h) def test_sha1_hash(): diff --git a/machine_learning/sequential_minimum_optimization.py b/machine_learning/sequential_minimum_optimization.py index b68bd52f4..b24f5669e 100644 --- a/machine_learning/sequential_minimum_optimization.py +++ b/machine_learning/sequential_minimum_optimization.py @@ -458,7 +458,7 @@ def test_cancel_data(): CANCER_DATASET_URL, headers={"User-Agent": "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)"}, ) - response = urllib.request.urlopen(request) + response = urllib.request.urlopen(request) # noqa: S310 content = response.read().decode("utf-8") with open(r"cancel_data.csv", "w") as f: f.write(content) diff --git a/neural_network/convolution_neural_network.py b/neural_network/convolution_neural_network.py index bd0550212..f5ec156f3 100644 --- a/neural_network/convolution_neural_network.py +++ b/neural_network/convolution_neural_network.py @@ -77,7 +77,7 @@ class CNN: def read_model(cls, model_path): # read saved model with open(model_path, "rb") as f: - model_dic = pickle.load(f) + model_dic = pickle.load(f) # noqa: S301 conv_get = model_dic.get("conv1") conv_get.append(model_dic.get("step_conv1")) diff --git a/project_euler/README.md b/project_euler/README.md index e3dc035ee..4832d0078 100644 --- a/project_euler/README.md +++ b/project_euler/README.md @@ -10,7 +10,7 @@ The solutions will be checked by our [automated testing on GitHub Actions](https ## Solution Guidelines -Welcome to [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python)! Before reading the solution guidelines, make sure you read the whole [Contributing Guidelines](https://github.com/TheAlgorithms/Python/blob/master/CONTRIBUTING.md) as it won't be repeated in here. If you have any doubt on the guidelines, please feel free to [state it clearly in an issue](https://github.com/TheAlgorithms/Python/issues/new) or ask the community in [Gitter](https://gitter.im/TheAlgorithms). You can use the [template](https://github.com/TheAlgorithms/Python/blob/master/project_euler/README.md#solution-template) we have provided below as your starting point but be sure to read the [Coding Style](https://github.com/TheAlgorithms/Python/blob/master/project_euler/README.md#coding-style) part first. +Welcome to [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python)! Before reading the solution guidelines, make sure you read the whole [Contributing Guidelines](https://github.com/TheAlgorithms/Python/blob/master/CONTRIBUTING.md) as it won't be repeated in here. If you have any doubt on the guidelines, please feel free to [state it clearly in an issue](https://github.com/TheAlgorithms/Python/issues/new) or ask the community in [Gitter](https://app.gitter.im/#/room/#TheAlgorithms_community:gitter.im). You can use the [template](https://github.com/TheAlgorithms/Python/blob/master/project_euler/README.md#solution-template) we have provided below as your starting point but be sure to read the [Coding Style](https://github.com/TheAlgorithms/Python/blob/master/project_euler/README.md#coding-style) part first. ### Coding Style diff --git a/pyproject.toml b/pyproject.toml index 169c3a71b..23fe45e97 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,6 +34,7 @@ ignore = [ # `ruff rule S101` for a description of that rule "S101", # S101: Use of `assert` detected -- DO NOT FIX "S105", # S105: Possible hardcoded password: 'password' "S113", # S113: Probable use of requests call without timeout + "S311", # S311: Standard pseudo-random generators are not suitable for cryptographic purposes "UP038", # UP038: Use `X | Y` in `{}` call instead of `(X, Y)` -- DO NOT FIX ] select = [ # https://beta.ruff.rs/docs/rules diff --git a/web_programming/download_images_from_google_query.py b/web_programming/download_images_from_google_query.py index 9c0c21dc8..441347459 100644 --- a/web_programming/download_images_from_google_query.py +++ b/web_programming/download_images_from_google_query.py @@ -86,7 +86,7 @@ def download_images_from_google_query(query: str = "dhaka", max_images: int = 5) path_name = f"query_{query.replace(' ', '_')}" if not os.path.exists(path_name): os.makedirs(path_name) - urllib.request.urlretrieve( + urllib.request.urlretrieve( # noqa: S310 original_size_img, f"{path_name}/original_size_img_{index}.jpg" ) return index From 86b2ab09aab359ef1b4bea58ed3c1fdf5b989500 Mon Sep 17 00:00:00 2001 From: Christian Veenhuis Date: Sun, 26 Mar 2023 18:20:47 +0200 Subject: [PATCH 605/726] Fix broken links to Gitter Community (Fixes: #8197) (#8546) Co-authored-by: Christian Clauss --- .github/stale.yml | 4 ++-- CONTRIBUTING.md | 4 ++-- README.md | 4 ++-- project_euler/README.md | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/stale.yml b/.github/stale.yml index 813f68834..0939e1f22 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -45,7 +45,7 @@ pulls: closeComment: > Please reopen this pull request once you commit the changes requested or make improvements on the code. If this is not the case and you need - some help, feel free to seek help from our [Gitter](https://app.gitter.im/#/room/#TheAlgorithms_community:gitter.im) + some help, feel free to seek help from our [Gitter](https://gitter.im/TheAlgorithms/community) or ping one of the reviewers. Thank you for your contributions! issues: @@ -59,5 +59,5 @@ issues: closeComment: > Please reopen this issue once you add more information and updates here. If this is not the case and you need some help, feel free to seek help - from our [Gitter](https://app.gitter.im/#/room/#TheAlgorithms_community:gitter.im) or ping one of the + from our [Gitter](https://gitter.im/TheAlgorithms/community) or ping one of the reviewers. Thank you for your contributions! diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 75e4fb893..2bb0c2e39 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ ## Before contributing -Welcome to [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python)! Before sending your pull requests, make sure that you __read the whole guidelines__. If you have any doubt on the contributing guide, please feel free to [state it clearly in an issue](https://github.com/TheAlgorithms/Python/issues/new) or ask the community in [Gitter](https://app.gitter.im/#/room/#TheAlgorithms_community:gitter.im). +Welcome to [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python)! Before sending your pull requests, make sure that you __read the whole guidelines__. If you have any doubt on the contributing guide, please feel free to [state it clearly in an issue](https://github.com/TheAlgorithms/Python/issues/new) or ask the community in [Gitter](https://gitter.im/TheAlgorithms/community). ## Contributing @@ -176,7 +176,7 @@ We want your work to be readable by others; therefore, we encourage you to note - Most importantly, - __Be consistent in the use of these guidelines when submitting.__ - - __Join__ us on [Discord](https://discord.com/invite/c7MnfGFGa6) and [Gitter](https://app.gitter.im/#/room/#TheAlgorithms_community:gitter.im) __now!__ + - __Join__ us on [Discord](https://discord.com/invite/c7MnfGFGa6) and [Gitter](https://gitter.im/TheAlgorithms/community) __now!__ - Happy coding! Writer [@poyea](https://github.com/poyea), Jun 2019. diff --git a/README.md b/README.md index 3d2f1a110..bf6e0ed3c 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Discord chat - + Gitter chat @@ -42,7 +42,7 @@ Read through our [Contribution Guidelines](CONTRIBUTING.md) before you contribut ## Community Channels -We are on [Discord](https://discord.gg/c7MnfGFGa6) and [Gitter](https://app.gitter.im/#/room/#TheAlgorithms_community:gitter.im)! Community channels are a great way for you to ask questions and get help. Please join us! +We are on [Discord](https://discord.gg/c7MnfGFGa6) and [Gitter](https://gitter.im/TheAlgorithms/community)! Community channels are a great way for you to ask questions and get help. Please join us! ## List of Algorithms diff --git a/project_euler/README.md b/project_euler/README.md index 4832d0078..16865edf2 100644 --- a/project_euler/README.md +++ b/project_euler/README.md @@ -10,7 +10,7 @@ The solutions will be checked by our [automated testing on GitHub Actions](https ## Solution Guidelines -Welcome to [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python)! Before reading the solution guidelines, make sure you read the whole [Contributing Guidelines](https://github.com/TheAlgorithms/Python/blob/master/CONTRIBUTING.md) as it won't be repeated in here. If you have any doubt on the guidelines, please feel free to [state it clearly in an issue](https://github.com/TheAlgorithms/Python/issues/new) or ask the community in [Gitter](https://app.gitter.im/#/room/#TheAlgorithms_community:gitter.im). You can use the [template](https://github.com/TheAlgorithms/Python/blob/master/project_euler/README.md#solution-template) we have provided below as your starting point but be sure to read the [Coding Style](https://github.com/TheAlgorithms/Python/blob/master/project_euler/README.md#coding-style) part first. +Welcome to [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python)! Before reading the solution guidelines, make sure you read the whole [Contributing Guidelines](https://github.com/TheAlgorithms/Python/blob/master/CONTRIBUTING.md) as it won't be repeated in here. If you have any doubt on the guidelines, please feel free to [state it clearly in an issue](https://github.com/TheAlgorithms/Python/issues/new) or ask the community in [Gitter](https://gitter.im/TheAlgorithms/community). You can use the [template](https://github.com/TheAlgorithms/Python/blob/master/project_euler/README.md#solution-template) we have provided below as your starting point but be sure to read the [Coding Style](https://github.com/TheAlgorithms/Python/blob/master/project_euler/README.md#coding-style) part first. ### Coding Style From ac111ee463065e372ad148dbafba630045ecf94c Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Wed, 29 Mar 2023 00:41:54 +0300 Subject: [PATCH 606/726] Reduce the complexity of graphs/bi_directional_dijkstra.py (#8165) * Reduce the complexity of graphs/bi_directional_dijkstra.py * Try to lower the --max-complexity threshold in the file .flake8 * Lower the --max-complexity threshold in the file .flake8 * updating DIRECTORY.md * updating DIRECTORY.md * Try to lower max-complexity * Try to lower max-complexity * Try to lower max-complexity --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- graphs/bi_directional_dijkstra.py | 93 +++++++++++++++++-------------- pyproject.toml | 2 +- 2 files changed, 52 insertions(+), 43 deletions(-) diff --git a/graphs/bi_directional_dijkstra.py b/graphs/bi_directional_dijkstra.py index fc53e2f0d..a4489026b 100644 --- a/graphs/bi_directional_dijkstra.py +++ b/graphs/bi_directional_dijkstra.py @@ -17,6 +17,32 @@ from typing import Any import numpy as np +def pass_and_relaxation( + graph: dict, + v: str, + visited_forward: set, + visited_backward: set, + cst_fwd: dict, + cst_bwd: dict, + queue: PriorityQueue, + parent: dict, + shortest_distance: float | int, +) -> float | int: + for nxt, d in graph[v]: + if nxt in visited_forward: + continue + old_cost_f = cst_fwd.get(nxt, np.inf) + new_cost_f = cst_fwd[v] + d + if new_cost_f < old_cost_f: + queue.put((new_cost_f, nxt)) + cst_fwd[nxt] = new_cost_f + parent[nxt] = v + if nxt in visited_backward: + if cst_fwd[v] + d + cst_bwd[nxt] < shortest_distance: + shortest_distance = cst_fwd[v] + d + cst_bwd[nxt] + return shortest_distance + + def bidirectional_dij( source: str, destination: str, graph_forward: dict, graph_backward: dict ) -> int: @@ -51,53 +77,36 @@ def bidirectional_dij( if source == destination: return 0 - while queue_forward and queue_backward: - while not queue_forward.empty(): - _, v_fwd = queue_forward.get() - - if v_fwd not in visited_forward: - break - else: - break + while not queue_forward.empty() and not queue_backward.empty(): + _, v_fwd = queue_forward.get() visited_forward.add(v_fwd) - while not queue_backward.empty(): - _, v_bwd = queue_backward.get() - - if v_bwd not in visited_backward: - break - else: - break + _, v_bwd = queue_backward.get() visited_backward.add(v_bwd) - # forward pass and relaxation - for nxt_fwd, d_forward in graph_forward[v_fwd]: - if nxt_fwd in visited_forward: - continue - old_cost_f = cst_fwd.get(nxt_fwd, np.inf) - new_cost_f = cst_fwd[v_fwd] + d_forward - if new_cost_f < old_cost_f: - queue_forward.put((new_cost_f, nxt_fwd)) - cst_fwd[nxt_fwd] = new_cost_f - parent_forward[nxt_fwd] = v_fwd - if nxt_fwd in visited_backward: - if cst_fwd[v_fwd] + d_forward + cst_bwd[nxt_fwd] < shortest_distance: - shortest_distance = cst_fwd[v_fwd] + d_forward + cst_bwd[nxt_fwd] + shortest_distance = pass_and_relaxation( + graph_forward, + v_fwd, + visited_forward, + visited_backward, + cst_fwd, + cst_bwd, + queue_forward, + parent_forward, + shortest_distance, + ) - # backward pass and relaxation - for nxt_bwd, d_backward in graph_backward[v_bwd]: - if nxt_bwd in visited_backward: - continue - old_cost_b = cst_bwd.get(nxt_bwd, np.inf) - new_cost_b = cst_bwd[v_bwd] + d_backward - if new_cost_b < old_cost_b: - queue_backward.put((new_cost_b, nxt_bwd)) - cst_bwd[nxt_bwd] = new_cost_b - parent_backward[nxt_bwd] = v_bwd - - if nxt_bwd in visited_forward: - if cst_bwd[v_bwd] + d_backward + cst_fwd[nxt_bwd] < shortest_distance: - shortest_distance = cst_bwd[v_bwd] + d_backward + cst_fwd[nxt_bwd] + shortest_distance = pass_and_relaxation( + graph_backward, + v_bwd, + visited_backward, + visited_forward, + cst_bwd, + cst_fwd, + queue_backward, + parent_backward, + shortest_distance, + ) if cst_fwd[v_fwd] + cst_bwd[v_bwd] >= shortest_distance: break diff --git a/pyproject.toml b/pyproject.toml index 23fe45e97..48c3fbd40 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,7 +61,7 @@ show-source = true target-version = "py311" [tool.ruff.mccabe] # DO NOT INCREASE THIS VALUE -max-complexity = 20 # default: 10 +max-complexity = 17 # default: 10 [tool.ruff.pylint] # DO NOT INCREASE THESE VALUES max-args = 10 # default: 5 From a71f22dae54f830dbf68b3bd5e5e8d540e338a4c Mon Sep 17 00:00:00 2001 From: Rohan Anand <96521078+rohan472000@users.noreply.github.com> Date: Thu, 30 Mar 2023 10:39:21 +0530 Subject: [PATCH 607/726] Update cnn_classification.py (#8570) --- computer_vision/cnn_classification.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/computer_vision/cnn_classification.py b/computer_vision/cnn_classification.py index 1c193fcbb..9b5f8c95e 100644 --- a/computer_vision/cnn_classification.py +++ b/computer_vision/cnn_classification.py @@ -93,7 +93,7 @@ if __name__ == "__main__": test_image = tf.keras.preprocessing.image.img_to_array(test_image) test_image = np.expand_dims(test_image, axis=0) result = classifier.predict(test_image) - training_set.class_indices + # training_set.class_indices if result[0][0] == 0: prediction = "Normal" if result[0][0] == 1: From a00492911a949a1e59072367bbabee22cd884106 Mon Sep 17 00:00:00 2001 From: Rohan Anand <96521078+rohan472000@users.noreply.github.com> Date: Fri, 31 Mar 2023 16:47:13 +0530 Subject: [PATCH 608/726] added a problem on kadane's algo and its solution. (#8569) * added kadane's algorithm directory with one problem's solution. * added type hints * Rename kaadne_algorithm/max_product_subarray.py to dynamic_programming/max_product_subarray.py * Update dynamic_programming/max_product_subarray.py Co-authored-by: Christian Clauss * Update max_product_subarray.py * Update max_product_subarray.py * Update dynamic_programming/max_product_subarray.py Co-authored-by: Christian Clauss * Update max_product_subarray.py * Update max_product_subarray.py * Update max_product_subarray.py * Update max_product_subarray.py * Update max_product_subarray.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update max_product_subarray.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update max_product_subarray.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update max_product_subarray.py * Update max_product_subarray.py * Update dynamic_programming/max_product_subarray.py Co-authored-by: Christian Clauss * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update dynamic_programming/max_product_subarray.py Co-authored-by: Christian Clauss * Update max_product_subarray.py --------- Co-authored-by: Christian Clauss Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- dynamic_programming/max_product_subarray.py | 53 +++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 dynamic_programming/max_product_subarray.py diff --git a/dynamic_programming/max_product_subarray.py b/dynamic_programming/max_product_subarray.py new file mode 100644 index 000000000..425859bc0 --- /dev/null +++ b/dynamic_programming/max_product_subarray.py @@ -0,0 +1,53 @@ +def max_product_subarray(numbers: list[int]) -> int: + """ + Returns the maximum product that can be obtained by multiplying a + contiguous subarray of the given integer list `nums`. + + Example: + >>> max_product_subarray([2, 3, -2, 4]) + 6 + >>> max_product_subarray((-2, 0, -1)) + 0 + >>> max_product_subarray([2, 3, -2, 4, -1]) + 48 + >>> max_product_subarray([-1]) + -1 + >>> max_product_subarray([0]) + 0 + >>> max_product_subarray([]) + 0 + >>> max_product_subarray("") + 0 + >>> max_product_subarray(None) + 0 + >>> max_product_subarray([2, 3, -2, 4.5, -1]) + Traceback (most recent call last): + ... + ValueError: numbers must be an iterable of integers + >>> max_product_subarray("ABC") + Traceback (most recent call last): + ... + ValueError: numbers must be an iterable of integers + """ + if not numbers: + return 0 + + if not isinstance(numbers, (list, tuple)) or not all( + isinstance(number, int) for number in numbers + ): + raise ValueError("numbers must be an iterable of integers") + + max_till_now = min_till_now = max_prod = numbers[0] + + for i in range(1, len(numbers)): + # update the maximum and minimum subarray products + number = numbers[i] + if number < 0: + max_till_now, min_till_now = min_till_now, max_till_now + max_till_now = max(number, max_till_now * number) + min_till_now = min(number, min_till_now * number) + + # update the maximum product found till now + max_prod = max(max_prod, max_till_now) + + return max_prod From 238fe8c494ab5be80c96441095d1c8958f95c04d Mon Sep 17 00:00:00 2001 From: NIKITA PANDEY <113332472+nikitapandeyy@users.noreply.github.com> Date: Fri, 31 Mar 2023 19:38:13 +0530 Subject: [PATCH 609/726] Update receive_file.py (#8541) * Update receive_file.py Here are the changes I made: Added the main() function and called it from if __name__ == "__main__" block. This makes it easier to test the code and import it into other programs. Added socket.AF_INET as the first argument to socket.socket(). This specifies the address family to be used, which is necessary when using connect(). Changed print(f"{data = }") to print("Received:", len(data), "bytes"). This makes it clearer what's happening and how much data is being received. Changed the final print statement to "Successfully received the file". This makes it more accurate and descriptive. Moved the import statement to the top of the file. This is a common convention in Python. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- file_transfer/receive_file.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/file_transfer/receive_file.py b/file_transfer/receive_file.py index 37a503036..f50ad9fe1 100644 --- a/file_transfer/receive_file.py +++ b/file_transfer/receive_file.py @@ -1,8 +1,9 @@ -if __name__ == "__main__": - import socket # Import socket module +import socket - sock = socket.socket() # Create a socket object - host = socket.gethostname() # Get local machine name + +def main(): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + host = socket.gethostname() port = 12312 sock.connect((host, port)) @@ -13,11 +14,14 @@ if __name__ == "__main__": print("Receiving data...") while True: data = sock.recv(1024) - print(f"{data = }") if not data: break - out_file.write(data) # Write data to a file + out_file.write(data) - print("Successfully got the file") + print("Successfully received the file") sock.close() print("Connection closed") + + +if __name__ == "__main__": + main() From 5ce63b5966b6ad9c7ce36c449fb31112c3e1d084 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Sat, 1 Apr 2023 01:11:24 -0400 Subject: [PATCH 610/726] Fix `mypy` errors in `lu_decomposition.py` (attempt 2) (#8100) * updating DIRECTORY.md * Fix mypy errors in lu_decomposition.py * Replace for-loops with comprehensions * Add explanation of LU decomposition and extra doctests Add an explanation of LU decomposition with conditions for when an LU decomposition exists Add extra doctests to handle each of the possible conditions for when a decomposition exists/doesn't exist * updating DIRECTORY.md * updating DIRECTORY.md --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- arithmetic_analysis/lu_decomposition.py | 91 ++++++++++++++++++------- 1 file changed, 65 insertions(+), 26 deletions(-) diff --git a/arithmetic_analysis/lu_decomposition.py b/arithmetic_analysis/lu_decomposition.py index 217719cf4..941c1dadf 100644 --- a/arithmetic_analysis/lu_decomposition.py +++ b/arithmetic_analysis/lu_decomposition.py @@ -1,62 +1,101 @@ -"""Lower-Upper (LU) Decomposition. +""" +Lower–upper (LU) decomposition factors a matrix as a product of a lower +triangular matrix and an upper triangular matrix. A square matrix has an LU +decomposition under the following conditions: + - If the matrix is invertible, then it has an LU decomposition if and only + if all of its leading principal minors are non-zero (see + https://en.wikipedia.org/wiki/Minor_(linear_algebra) for an explanation of + leading principal minors of a matrix). + - If the matrix is singular (i.e., not invertible) and it has a rank of k + (i.e., it has k linearly independent columns), then it has an LU + decomposition if its first k leading principal minors are non-zero. -Reference: -- https://en.wikipedia.org/wiki/LU_decomposition +This algorithm will simply attempt to perform LU decomposition on any square +matrix and raise an error if no such decomposition exists. + +Reference: https://en.wikipedia.org/wiki/LU_decomposition """ from __future__ import annotations import numpy as np -from numpy import float64 -from numpy.typing import ArrayLike -def lower_upper_decomposition( - table: ArrayLike[float64], -) -> tuple[ArrayLike[float64], ArrayLike[float64]]: - """Lower-Upper (LU) Decomposition - - Example: - +def lower_upper_decomposition(table: np.ndarray) -> tuple[np.ndarray, np.ndarray]: + """ + Perform LU decomposition on a given matrix and raises an error if the matrix + isn't square or if no such decomposition exists >>> matrix = np.array([[2, -2, 1], [0, 1, 2], [5, 3, 1]]) - >>> outcome = lower_upper_decomposition(matrix) - >>> outcome[0] + >>> lower_mat, upper_mat = lower_upper_decomposition(matrix) + >>> lower_mat array([[1. , 0. , 0. ], [0. , 1. , 0. ], [2.5, 8. , 1. ]]) - >>> outcome[1] + >>> upper_mat array([[ 2. , -2. , 1. ], [ 0. , 1. , 2. ], [ 0. , 0. , -17.5]]) + >>> matrix = np.array([[4, 3], [6, 3]]) + >>> lower_mat, upper_mat = lower_upper_decomposition(matrix) + >>> lower_mat + array([[1. , 0. ], + [1.5, 1. ]]) + >>> upper_mat + array([[ 4. , 3. ], + [ 0. , -1.5]]) + + # Matrix is not square >>> matrix = np.array([[2, -2, 1], [0, 1, 2]]) - >>> lower_upper_decomposition(matrix) + >>> lower_mat, upper_mat = lower_upper_decomposition(matrix) Traceback (most recent call last): ... ValueError: 'table' has to be of square shaped array but got a 2x3 array: [[ 2 -2 1] [ 0 1 2]] + + # Matrix is invertible, but its first leading principal minor is 0 + >>> matrix = np.array([[0, 1], [1, 0]]) + >>> lower_mat, upper_mat = lower_upper_decomposition(matrix) + Traceback (most recent call last): + ... + ArithmeticError: No LU decomposition exists + + # Matrix is singular, but its first leading principal minor is 1 + >>> matrix = np.array([[1, 0], [1, 0]]) + >>> lower_mat, upper_mat = lower_upper_decomposition(matrix) + >>> lower_mat + array([[1., 0.], + [1., 1.]]) + >>> upper_mat + array([[1., 0.], + [0., 0.]]) + + # Matrix is singular, but its first leading principal minor is 0 + >>> matrix = np.array([[0, 1], [0, 1]]) + >>> lower_mat, upper_mat = lower_upper_decomposition(matrix) + Traceback (most recent call last): + ... + ArithmeticError: No LU decomposition exists """ - # Table that contains our data - # Table has to be a square array so we need to check first + # Ensure that table is a square array rows, columns = np.shape(table) if rows != columns: raise ValueError( - f"'table' has to be of square shaped array but got a {rows}x{columns} " - + f"array:\n{table}" + f"'table' has to be of square shaped array but got a " + f"{rows}x{columns} array:\n{table}" ) + lower = np.zeros((rows, columns)) upper = np.zeros((rows, columns)) for i in range(columns): for j in range(i): - total = 0 - for k in range(j): - total += lower[i][k] * upper[k][j] + total = sum(lower[i][k] * upper[k][j] for k in range(j)) + if upper[j][j] == 0: + raise ArithmeticError("No LU decomposition exists") lower[i][j] = (table[i][j] - total) / upper[j][j] lower[i][i] = 1 for j in range(i, columns): - total = 0 - for k in range(i): - total += lower[i][k] * upper[k][j] + total = sum(lower[i][k] * upper[k][j] for k in range(j)) upper[i][j] = table[i][j] - total return lower, upper From dc4f603dad22eab31892855555999b552e97e9d8 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sat, 1 Apr 2023 08:47:24 +0300 Subject: [PATCH 611/726] Add Project Euler problem 187 solution 1 (#8182) Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- DIRECTORY.md | 2 + project_euler/problem_187/__init__.py | 0 project_euler/problem_187/sol1.py | 58 +++++++++++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 project_euler/problem_187/__init__.py create mode 100644 project_euler/problem_187/sol1.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 1d3177801..1a641d8ec 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -990,6 +990,8 @@ * [Sol1](project_euler/problem_174/sol1.py) * Problem 180 * [Sol1](project_euler/problem_180/sol1.py) + * Problem 187 + * [Sol1](project_euler/problem_187/sol1.py) * Problem 188 * [Sol1](project_euler/problem_188/sol1.py) * Problem 191 diff --git a/project_euler/problem_187/__init__.py b/project_euler/problem_187/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_187/sol1.py b/project_euler/problem_187/sol1.py new file mode 100644 index 000000000..12f03e2a7 --- /dev/null +++ b/project_euler/problem_187/sol1.py @@ -0,0 +1,58 @@ +""" +Project Euler Problem 187: https://projecteuler.net/problem=187 + +A composite is a number containing at least two prime factors. +For example, 15 = 3 x 5; 9 = 3 x 3; 12 = 2 x 2 x 3. + +There are ten composites below thirty containing precisely two, +not necessarily distinct, prime factors: 4, 6, 9, 10, 14, 15, 21, 22, 25, 26. + +How many composite integers, n < 10^8, have precisely two, +not necessarily distinct, prime factors? +""" + +from math import isqrt + + +def calculate_prime_numbers(max_number: int) -> list[int]: + """ + Returns prime numbers below max_number + + >>> calculate_prime_numbers(10) + [2, 3, 5, 7] + """ + + is_prime = [True] * max_number + for i in range(2, isqrt(max_number - 1) + 1): + if is_prime[i]: + for j in range(i**2, max_number, i): + is_prime[j] = False + + return [i for i in range(2, max_number) if is_prime[i]] + + +def solution(max_number: int = 10**8) -> int: + """ + Returns the number of composite integers below max_number have precisely two, + not necessarily distinct, prime factors + + >>> solution(30) + 10 + """ + + prime_numbers = calculate_prime_numbers(max_number // 2) + + semiprimes_count = 0 + left = 0 + right = len(prime_numbers) - 1 + while left <= right: + while prime_numbers[left] * prime_numbers[right] >= max_number: + right -= 1 + semiprimes_count += right - left + 1 + left += 1 + + return semiprimes_count + + +if __name__ == "__main__": + print(f"{solution() = }") From e4d90e2d5b92fdcff558f1848843dfbe20d81035 Mon Sep 17 00:00:00 2001 From: amirsoroush <114881632+amirsoroush@users.noreply.github.com> Date: Sat, 1 Apr 2023 09:26:43 +0300 Subject: [PATCH 612/726] change space complexity of linked list's __len__ from O(n) to O(1) (#8183) --- data_structures/linked_list/circular_linked_list.py | 2 +- data_structures/linked_list/doubly_linked_list.py | 2 +- data_structures/linked_list/merge_two_lists.py | 2 +- data_structures/linked_list/singly_linked_list.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/data_structures/linked_list/circular_linked_list.py b/data_structures/linked_list/circular_linked_list.py index 67a63cd55..9092fb29e 100644 --- a/data_structures/linked_list/circular_linked_list.py +++ b/data_structures/linked_list/circular_linked_list.py @@ -24,7 +24,7 @@ class CircularLinkedList: break def __len__(self) -> int: - return len(tuple(iter(self))) + return sum(1 for _ in self) def __repr__(self): return "->".join(str(item) for item in iter(self)) diff --git a/data_structures/linked_list/doubly_linked_list.py b/data_structures/linked_list/doubly_linked_list.py index 6c81493ff..41d07d63e 100644 --- a/data_structures/linked_list/doubly_linked_list.py +++ b/data_structures/linked_list/doubly_linked_list.py @@ -51,7 +51,7 @@ class DoublyLinkedList: >>> len(linked_list) == 5 True """ - return len(tuple(iter(self))) + return sum(1 for _ in self) def insert_at_head(self, data): self.insert_at_nth(0, data) diff --git a/data_structures/linked_list/merge_two_lists.py b/data_structures/linked_list/merge_two_lists.py index 61e2412aa..ca0d3bb48 100644 --- a/data_structures/linked_list/merge_two_lists.py +++ b/data_structures/linked_list/merge_two_lists.py @@ -44,7 +44,7 @@ class SortedLinkedList: >>> len(SortedLinkedList(test_data_odd)) 8 """ - return len(tuple(iter(self))) + return sum(1 for _ in self) def __str__(self) -> str: """ diff --git a/data_structures/linked_list/singly_linked_list.py b/data_structures/linked_list/singly_linked_list.py index bdeb5922a..a8f9e8ebb 100644 --- a/data_structures/linked_list/singly_linked_list.py +++ b/data_structures/linked_list/singly_linked_list.py @@ -72,7 +72,7 @@ class LinkedList: >>> len(linked_list) 0 """ - return len(tuple(iter(self))) + return sum(1 for _ in self) def __repr__(self) -> str: """ From 9e0c357a57f76abc354d704012040f3f5511a941 Mon Sep 17 00:00:00 2001 From: Dhruv Manilawala Date: Sat, 1 Apr 2023 11:59:26 +0530 Subject: [PATCH 613/726] chore: additional Project Euler solution hash (#8593) --- scripts/project_euler_answers.json | 109 ++++++++++++++++++++++++++++- 1 file changed, 108 insertions(+), 1 deletion(-) diff --git a/scripts/project_euler_answers.json b/scripts/project_euler_answers.json index 6d354363e..f2b876934 100644 --- a/scripts/project_euler_answers.json +++ b/scripts/project_euler_answers.json @@ -723,5 +723,112 @@ "722": "9687101dfe209fd65f57a10603baa38ba83c9152e43a8b802b96f1e07f568e0e", "723": "74832787e7d4e0cb7991256c8f6d02775dffec0684de234786f25f898003f2de", "724": "fa05e2b497e7eafa64574017a4c45aadef6b163d907b03d63ba3f4021096d329", - "725": "005c873563f51bbebfdb1f8dbc383259e9a98e506bc87ae8d8c9044b81fc6418" + "725": "005c873563f51bbebfdb1f8dbc383259e9a98e506bc87ae8d8c9044b81fc6418", + "726": "93e41c533136bf4b436e493090fd4e7b277234db2a69c62a871f775ff26681bf", + "727": "c366f7426ca9351dcdde2e3bea01181897cda4d9b44977678ea3828419b84851", + "728": "8de62a644511d27c7c23c7722f56112b3c1ab9b05a078a98a0891f09f92464c6", + "729": "0ae82177174eef99fc80a2ec921295f61a6ac4dfed86a1bf333a50c26d01955c", + "730": "78cd876a176c8fbf7c2155b80dccbdededdbc43c28ef17b5a6e554d649325d38", + "731": "54afb9f829be51d29f90eecbfe40e5ba91f3a3bf538de62f3e34674af15eb542", + "732": "c4dc4610dcafc806b30e5d3f5560b57f462218a04397809843a7110838f0ebac", + "733": "bdde7d98d057d6a6ae360fd2f872d8bccb7e7f2971df37a3c5f20712ea3c618f", + "734": "9a514875bd9af26fcc565337771f852d311cd77033186e4d957e7b6c7b8ce018", + "735": "8bbc5a27c0031d8c44f3f73c99622a202cd6ea9a080049d615a7ae80ce6024f9", + "736": "e0d4c78b9b3dae51940877aff28275d036eccfc641111c8e34227ff6015a0fab", + "737": "a600884bcaa01797310c83b198bad58c98530289305af29b0bf75f679af38d3a", + "738": "c85f15fdaafe7d5525acff960afef7e4b8ffded5a7ee0d1dc2b0e8d0c26b9b46", + "739": "8716e9302f0fb90153e2f522bd88a710361a897480e4ccc0542473c704793518", + "740": "6ff41ee34b263b742cda109aee3be9ad6c95eec2ce31d6a9fc5353bba1b41afd", + "741": "99ac0eb9589b895e5755895206bbad5febd6bc29b2912df1c7544c547e26bca3", + "742": "7d2761a240aa577348df4813ea248088d0d6d8d421142c712ed576cdc90d4df9", + "743": "d93c42a129c0961b4e36738efae3b7e8ffae3a4daeced20e85bb740d3d72522d", + "744": "211f76700a010461486dde6c723720be85e68c192cd8a8ed0a88860b8ae9b0f0", + "745": "2d32dc1fea2f1b8600c0ada927b057b566870ceb5362cce71ac3693dcb7136ae", + "746": "2df1c2a0181f0c25e8d13d2a1eadba55a6b06267a2b22075fcf6867fb2e10c02", + "747": "a8d8f93142e320c6f0dd386c7a3bfb011bbdc15b85291a9be8f0266b3608175e", + "748": "7de937e04c10386b240afb8bb2ff590009946df8b7850a0329ccdb59fca8955f", + "749": "1a55f5484ccf964aeb186faedefa01db05d87180891dc2280b6eb85b6efb4779", + "750": "fa4318c213179e6af1c949be7cf47210f4383e0a44d191e2bad44228d3192f14", + "751": "12fe650fcb3afc214b3d647c655070e8142cfd397441fc7636ad7e6ffcaefde2", + "752": "e416c0123bc6b82df8726b328494db31aa4781d938a0a6e2107b1e44c73c0434", + "753": "0ee3299bc89e1e4c2fc79285fb1cd84c887456358a825e56be92244b7115f5af", + "754": "1370574b16207c41d3dafb62aa898379ec101ac36843634b1633b7b509d4c35a", + "755": "78bb4b18b13f5254cfafe872c0e93791ab5206b2851960dc6aebea8f62b9580c", + "756": "6becaabbda2e9ea22373e62e989b6b70467efa24fbe2f0d124d7a99a53e93f74", + "757": "fbfee0a5c4fa57a1dd6cf0c9bb2423cf7e7bcb130e67114aa360e42234987314", + "758": "8e4dfc259cec9dfd89d4b4ac8c33c75af6e0f5f7926526ee22ad4d45f93d3c18", + "759": "40bac0ed2e4f7861a6d9a2d87191a9034e177c319aa40a43638cc1b69572e5f2", + "760": "7ab50386a211f0815593389ab05b57a1a5eb5cbf5b9a85fe4afc517dcab74e06", + "761": "1cdb0318ac16e11c8d2ae7b1d7ca7138f7b1a461e9d75bd69be0f9cdd3add0c5", + "762": "84c4662267d5809380a540dfc2881665b3019047d74d5ef0a01f86e45f4b5b59", + "763": "f0def5903139447fabe7d106db5fff660d94b45af7b8b48d789596cf65ab2514", + "764": "7b4131f4d1e13d091ca7dd4d32317a14a2a24e6e1abd214df1c14c215287b330", + "765": "7558b775727426bccd945f5aa6b3e131e6034a7b1ff8576332329ef65d6a1663", + "766": "23c309430fa9546adb617457dbfd30fb7432904595c8c000e9b67ea23f32a53b", + "767": "70aef22ac2db8a5bdfcc42ff8dafbd2901e85e268f5f3c45085aa40c590b1d42", + "768": "b69a808dfc654b037e2f47ace16f48fe3bb553b3c8eed3e2b6421942fbf521d0", + "769": "78537a30577e806c6d8d94725e54d2d52e56f7f39f89c133cd5d0a2aad7e46e4", + "770": "c9d80c19c4895d1498bf809fcc37c447fa961fb325e5667eb35d6aa992966b41", + "771": "9803ace30c0d90d422e703fdf25a10a9342d0178a277ebc20c7bd6feac4c7a15", + "772": "f5a1e391af815ea6453db58a1bd71790f433c44ed63e5e93d8f5c045dfd5a464", + "773": "e1b93fc323c4d9c383100603339548e1e56ce9c38bcdcc425024c12b862ea8cb", + "774": "3646cd098b213014fb7bbc9597871585e62ee0cf2770e141f1df771237cc09ab", + "775": "d9d7d515ce7350c9e5696d85f68bbb42daa74b9e171a601dd04c823b18bb7757", + "776": "83286074d3bc86a5b449facb5fe5eafc91eb4c8031e2fb5e716443402cd8ed0f", + "777": "e62616a387d05b619d47cee3d49d5d2db19393736bf54b6cdd20933c0531cb7e", + "778": "d4de958ba44d25353de5b380e04d06c7968794ad50dbf6231ad0049ff53e106b", + "779": "c08ce54a59afc4af62f28b80a9c9a5190822d124eed8d73fd6db3e19c81e2157", + "780": "fc7ba646c16482f0f4f5ce2b06d21183dba2bdeaf9469b36b55bc7bc2d87baf3", + "781": "8fa5733f06838fb61b55b3e9d59c5061d922147e59947fe52e566dd975b2199f", + "782": "9f757d92df401ee049bc066bb2625c6287e5e4bcd38c958396a77a578f036a24", + "783": "270ff37f60c267a673bd4b223e44941f01ae9cfbf6bbdf99ca57af89b1e9a66f", + "784": "388b17c4c7b829cef767f83b4686c903faeec1241edfe5f58ee91d2b0c7f8dfc", + "785": "77cf600204c5265e1d5d3d26bf28ba1e92e6f24def040c16977450bec8b1cb99", + "786": "fb14022b7edbc6c7bfde27f35b49f6acaa4f0fc383af27614cb9d4a1980e626b", + "787": "7516ba0ac1951665723dcc4adcc52764d9497e7b6ed30bdb9937ac9df82b7c4f", + "788": "adede1d30258bb0f353af11f559b67f8b823304c71e967f52db52d002760c24f", + "789": "0c82e744a1f9bc57fd8ae8b2f479998455bc45126de971c59b68541c254e303a", + "790": "319847122251afd20d4d650047c55981a509fa2be78abd7c9c3caa0555e60a05", + "791": "2e0bbdcd0a8460e1e33c55668d0dc9752379a78b9f3561d7a17b922a5541a3fb", + "792": "5f77834c5a509023dd95dd98411eae1dd4bafd125deca590632f409f92fd257b", + "793": "dbfd900a3b31eeec2f14b916f5151611541cb716d80b7b9a1229de12293a02ea", + "794": "d019fe415aba832c4c761140d60c466c9aaad52b504df3167c17f2d3f0b277a7", + "795": "617b259349da44c2af2664acde113673ab3bb03a85d31f1be8f01027d0ebd4d3", + "796": "cba6b30a818d073398e5802211987f0897523e4752987bb445b2bca079670e22", + "797": "61e42cac3d7858b8850111a8c64c56432a18dd058dfb6afd773f07d703703b1a", + "798": "ae8b155d6b77522af79f7e4017fefe92aaa5d45eff132c83dc4d4bcfc9686020", + "799": "a41cb14ddf8f1948a01f590fbe53d9ca4e2faf48375ce1c306f91acf7c94e005", + "800": "c6a47bc6f02cf06be16728fb308c83f2f2ae350325ef7016867f5bdaea849d71", + "801": "d14b358c76b55106613f9c0a2112393338dfd01513b0fd231b79fc8db20e41f0", + "802": "22ae33e67fb48accfaa3b36e70c5a19066b974194c3130680de0c7cdce2d0f2e", + "803": "d95b3f9bbb7054042c1fba4db02f7223a2dad94977a36f08c8aaf92f373f9e78", + "804": "b0b1cf7253593eb2334c75e66dbe22b4b4540347485f1ea24e80226b4b18171c", + "805": "41b1ff5db0e70984ad20c50d1a9ac2b5a53ccd5f42796c8e948ae8880005fbb9", + "806": "b9c813beb39671adb8e1530555cadca44c21ddc7127932274918df2091dbd9ca", + "807": "745fd9ba97970d85a29877942839e41fc192794420e86f3bde39fd26db7a8bff", + "808": "6c73b947eb603602a7e8afadc83eaaa381a46db8b82a6fb89c9c1d93cb023fce", + "809": "eebac7753da4c1230dfce0f15fc124ffff01b0e432f0b74623b60cff71bbc9a9", + "810": "42be7899672a1a0046823603ce60dbeda7250a56fcb8d0913093850c85394307", + "811": "8698cd28ae4d93db36631870c33e4a8a527d970050d994666115f54260b64138", + "812": "dc2495924f37353db8b846323b8085fae9db502e890c513ed2e64ed7281f567f", + "813": "92179dde05aa6557baca65699fda50ca024d33a77078d8e128caa3c5db84064b", + "814": "344ed8cb7684307c00b7f03d751729a7f9d2a5f4a4cb4574594113d69593c0c1", + "815": "f642cf15345af3feab60e26a02aee038f759914906a5b2b469b46fdeee50ff59", + "816": "058178444e85f2aedb2f75d824a469747381f0bd3235d8c72df4385fec86eb07", + "817": "582fdc2233298192b09ceaf1463d6be06a09894075532630aa9d9efcfcb31da4", + "818": "67f6964d6ff114a43371b8375c44db2f1362df4f110b4a7ce8d79cf1b76621a0", + "819": "c7a82513ad48dfc87f2c1e0f2915b71464b7f5a16501c71df4ae4a8741dceef3", + "820": "9b23ae0181f320aadda2637ac2179c8b41b00715630c3acb643c7aee3b81cf90", + "821": "0941e396ff15b98fd7827de8e33ef94996d48ba719a88ba8e2da7f2605df3e5c", + "822": "ed8ef7f568939b9df1b77ae58344940b91c7e154a4367fe2b179bc7b9484d4e6", + "823": "05139328571a86096032b57e3a6a02a61acad4fb0d8f8e1b5d0ffb0d063ba697", + "826": "7f40f14ca65e5c06dd9ec9bbb212adb4d97a503199cb3c30ed921a04373bbe1c", + "827": "80461f02c63654c642382a6ffb7a44d0a3554434dfcfcea00ba91537724c7106", + "828": "520c196175625a0230afb76579ea26033372de3ef4c78aceb146b84322bfa871", + "829": "ed0089e61cf5540dd4a8fef1c468b96cf57f1d2bb79968755ba856d547ddafdf", + "831": "8ec445084427419ca6da405e0ded9814a4b4e11a2be84d88a8dea421f8e49992", + "832": "cfcb9ebef9308823f64798b5e12a59bf77ff6f92b0eae3790a61c0a26f577010", + "833": "e6ff3a5b257eb53366a32bfc8ea410a00a78bafa63650c76ac2bceddfbb42ff5", + "834": "b0d2a7e7d629ef14db9e7352a9a06d6ca66f750429170bb169ca52c172b8cc96", + "835": "bdfa1b1eecbad79f5de48bc6daee4d2b07689d7fb172aa306dd6094172b396f0" } From d66e1e873288bf399559c9ca40310d4b031aec50 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sat, 1 Apr 2023 15:18:13 +0300 Subject: [PATCH 614/726] Add Project Euler problem 800 solution 1 (#8567) Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- DIRECTORY.md | 3 ++ project_euler/problem_800/__init__.py | 0 project_euler/problem_800/sol1.py | 65 +++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 project_euler/problem_800/__init__.py create mode 100644 project_euler/problem_800/sol1.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 1a641d8ec..18c573909 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -317,6 +317,7 @@ * [Longest Sub Array](dynamic_programming/longest_sub_array.py) * [Matrix Chain Order](dynamic_programming/matrix_chain_order.py) * [Max Non Adjacent Sum](dynamic_programming/max_non_adjacent_sum.py) + * [Max Product Subarray](dynamic_programming/max_product_subarray.py) * [Max Sub Array](dynamic_programming/max_sub_array.py) * [Max Sum Contiguous Subsequence](dynamic_programming/max_sum_contiguous_subsequence.py) * [Min Distance Up Bottom](dynamic_programming/min_distance_up_bottom.py) @@ -1016,6 +1017,8 @@ * [Sol1](project_euler/problem_587/sol1.py) * Problem 686 * [Sol1](project_euler/problem_686/sol1.py) + * Problem 800 + * [Sol1](project_euler/problem_800/sol1.py) ## Quantum * [Bb84](quantum/bb84.py) diff --git a/project_euler/problem_800/__init__.py b/project_euler/problem_800/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_800/sol1.py b/project_euler/problem_800/sol1.py new file mode 100644 index 000000000..f887787bc --- /dev/null +++ b/project_euler/problem_800/sol1.py @@ -0,0 +1,65 @@ +""" +Project Euler Problem 800: https://projecteuler.net/problem=800 + +An integer of the form p^q q^p with prime numbers p != q is called a hybrid-integer. +For example, 800 = 2^5 5^2 is a hybrid-integer. + +We define C(n) to be the number of hybrid-integers less than or equal to n. +You are given C(800) = 2 and C(800^800) = 10790 + +Find C(800800^800800) +""" + +from math import isqrt, log2 + + +def calculate_prime_numbers(max_number: int) -> list[int]: + """ + Returns prime numbers below max_number + + >>> calculate_prime_numbers(10) + [2, 3, 5, 7] + """ + + is_prime = [True] * max_number + for i in range(2, isqrt(max_number - 1) + 1): + if is_prime[i]: + for j in range(i**2, max_number, i): + is_prime[j] = False + + return [i for i in range(2, max_number) if is_prime[i]] + + +def solution(base: int = 800800, degree: int = 800800) -> int: + """ + Returns the number of hybrid-integers less than or equal to base^degree + + >>> solution(800, 1) + 2 + + >>> solution(800, 800) + 10790 + """ + + upper_bound = degree * log2(base) + max_prime = int(upper_bound) + prime_numbers = calculate_prime_numbers(max_prime) + + hybrid_integers_count = 0 + left = 0 + right = len(prime_numbers) - 1 + while left < right: + while ( + prime_numbers[right] * log2(prime_numbers[left]) + + prime_numbers[left] * log2(prime_numbers[right]) + > upper_bound + ): + right -= 1 + hybrid_integers_count += right - left + left += 1 + + return hybrid_integers_count + + +if __name__ == "__main__": + print(f"{solution() = }") From 3d2012c4ba3a9d9ddd80e518f0b5b9ba6c52df7d Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sat, 1 Apr 2023 15:20:08 +0300 Subject: [PATCH 615/726] Add Project Euler problem 94 solution 1 (#8599) Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- DIRECTORY.md | 2 ++ project_euler/problem_094/__init__.py | 0 project_euler/problem_094/sol1.py | 44 +++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 project_euler/problem_094/__init__.py create mode 100644 project_euler/problem_094/sol1.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 18c573909..c781b17bf 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -937,6 +937,8 @@ * [Sol1](project_euler/problem_091/sol1.py) * Problem 092 * [Sol1](project_euler/problem_092/sol1.py) + * Problem 094 + * [Sol1](project_euler/problem_094/sol1.py) * Problem 097 * [Sol1](project_euler/problem_097/sol1.py) * Problem 099 diff --git a/project_euler/problem_094/__init__.py b/project_euler/problem_094/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_094/sol1.py b/project_euler/problem_094/sol1.py new file mode 100644 index 000000000..a41292fe2 --- /dev/null +++ b/project_euler/problem_094/sol1.py @@ -0,0 +1,44 @@ +""" +Project Euler Problem 94: https://projecteuler.net/problem=94 + +It is easily proved that no equilateral triangle exists with integral length sides and +integral area. However, the almost equilateral triangle 5-5-6 has an area of 12 square +units. + +We shall define an almost equilateral triangle to be a triangle for which two sides are +equal and the third differs by no more than one unit. + +Find the sum of the perimeters of all almost equilateral triangles with integral side +lengths and area and whose perimeters do not exceed one billion (1,000,000,000). +""" + + +def solution(max_perimeter: int = 10**9) -> int: + """ + Returns the sum of the perimeters of all almost equilateral triangles with integral + side lengths and area and whose perimeters do not exceed max_perimeter + + >>> solution(20) + 16 + """ + + prev_value = 1 + value = 2 + + perimeters_sum = 0 + i = 0 + perimeter = 0 + while perimeter <= max_perimeter: + perimeters_sum += perimeter + + prev_value += 2 * value + value += prev_value + + perimeter = 2 * value + 2 if i % 2 == 0 else 2 * value - 2 + i += 1 + + return perimeters_sum + + +if __name__ == "__main__": + print(f"{solution() = }") From 63710883c8634772fadf0145899cea4a1eadc31d Mon Sep 17 00:00:00 2001 From: amirsoroush <114881632+amirsoroush@users.noreply.github.com> Date: Sat, 1 Apr 2023 15:23:21 +0300 Subject: [PATCH 616/726] Remove extra `len` calls in doubly-linked-list's methods (#8600) --- data_structures/linked_list/doubly_linked_list.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/data_structures/linked_list/doubly_linked_list.py b/data_structures/linked_list/doubly_linked_list.py index 41d07d63e..69763d12d 100644 --- a/data_structures/linked_list/doubly_linked_list.py +++ b/data_structures/linked_list/doubly_linked_list.py @@ -81,7 +81,9 @@ class DoublyLinkedList: .... IndexError: list index out of range """ - if not 0 <= index <= len(self): + length = len(self) + + if not 0 <= index <= length: raise IndexError("list index out of range") new_node = Node(data) if self.head is None: @@ -90,7 +92,7 @@ class DoublyLinkedList: self.head.previous = new_node new_node.next = self.head self.head = new_node - elif index == len(self): + elif index == length: self.tail.next = new_node new_node.previous = self.tail self.tail = new_node @@ -131,15 +133,17 @@ class DoublyLinkedList: .... IndexError: list index out of range """ - if not 0 <= index <= len(self) - 1: + length = len(self) + + if not 0 <= index <= length - 1: raise IndexError("list index out of range") delete_node = self.head # default first node - if len(self) == 1: + if length == 1: self.head = self.tail = None elif index == 0: self.head = self.head.next self.head.previous = None - elif index == len(self) - 1: + elif index == length - 1: delete_node = self.tail self.tail = self.tail.previous self.tail.next = None From 59cae167e0e6b830b7ff5c89f5f2b8c747fb84c2 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sat, 1 Apr 2023 19:22:33 +0300 Subject: [PATCH 617/726] Reduce the complexity of digital_image_processing/edge detection/canny.py (#8167) * Reduce the complexity of digital_image_processing/edge_detection/canny.py * Fix * updating DIRECTORY.md * updating DIRECTORY.md * updating DIRECTORY.md * Fix review issues * Rename dst to destination --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .../edge_detection/canny.py | 127 ++++++++++-------- 1 file changed, 74 insertions(+), 53 deletions(-) diff --git a/digital_image_processing/edge_detection/canny.py b/digital_image_processing/edge_detection/canny.py index a83035526..f8cbeedb3 100644 --- a/digital_image_processing/edge_detection/canny.py +++ b/digital_image_processing/edge_detection/canny.py @@ -18,105 +18,126 @@ def gen_gaussian_kernel(k_size, sigma): return g -def canny(image, threshold_low=15, threshold_high=30, weak=128, strong=255): - image_row, image_col = image.shape[0], image.shape[1] - # gaussian_filter - gaussian_out = img_convolve(image, gen_gaussian_kernel(9, sigma=1.4)) - # get the gradient and degree by sobel_filter - sobel_grad, sobel_theta = sobel_filter(gaussian_out) - gradient_direction = np.rad2deg(sobel_theta) - gradient_direction += PI - - dst = np.zeros((image_row, image_col)) - +def suppress_non_maximum(image_shape, gradient_direction, sobel_grad): """ Non-maximum suppression. If the edge strength of the current pixel is the largest compared to the other pixels in the mask with the same direction, the value will be preserved. Otherwise, the value will be suppressed. """ - for row in range(1, image_row - 1): - for col in range(1, image_col - 1): + destination = np.zeros(image_shape) + + for row in range(1, image_shape[0] - 1): + for col in range(1, image_shape[1] - 1): direction = gradient_direction[row, col] if ( - 0 <= direction < 22.5 + 0 <= direction < PI / 8 or 15 * PI / 8 <= direction <= 2 * PI or 7 * PI / 8 <= direction <= 9 * PI / 8 ): w = sobel_grad[row, col - 1] e = sobel_grad[row, col + 1] if sobel_grad[row, col] >= w and sobel_grad[row, col] >= e: - dst[row, col] = sobel_grad[row, col] + destination[row, col] = sobel_grad[row, col] - elif (PI / 8 <= direction < 3 * PI / 8) or ( - 9 * PI / 8 <= direction < 11 * PI / 8 + elif ( + PI / 8 <= direction < 3 * PI / 8 + or 9 * PI / 8 <= direction < 11 * PI / 8 ): sw = sobel_grad[row + 1, col - 1] ne = sobel_grad[row - 1, col + 1] if sobel_grad[row, col] >= sw and sobel_grad[row, col] >= ne: - dst[row, col] = sobel_grad[row, col] + destination[row, col] = sobel_grad[row, col] - elif (3 * PI / 8 <= direction < 5 * PI / 8) or ( - 11 * PI / 8 <= direction < 13 * PI / 8 + elif ( + 3 * PI / 8 <= direction < 5 * PI / 8 + or 11 * PI / 8 <= direction < 13 * PI / 8 ): n = sobel_grad[row - 1, col] s = sobel_grad[row + 1, col] if sobel_grad[row, col] >= n and sobel_grad[row, col] >= s: - dst[row, col] = sobel_grad[row, col] + destination[row, col] = sobel_grad[row, col] - elif (5 * PI / 8 <= direction < 7 * PI / 8) or ( - 13 * PI / 8 <= direction < 15 * PI / 8 + elif ( + 5 * PI / 8 <= direction < 7 * PI / 8 + or 13 * PI / 8 <= direction < 15 * PI / 8 ): nw = sobel_grad[row - 1, col - 1] se = sobel_grad[row + 1, col + 1] if sobel_grad[row, col] >= nw and sobel_grad[row, col] >= se: - dst[row, col] = sobel_grad[row, col] + destination[row, col] = sobel_grad[row, col] - """ - High-Low threshold detection. If an edge pixel’s gradient value is higher - than the high threshold value, it is marked as a strong edge pixel. If an - edge pixel’s gradient value is smaller than the high threshold value and - larger than the low threshold value, it is marked as a weak edge pixel. If - an edge pixel's value is smaller than the low threshold value, it will be - suppressed. - """ - if dst[row, col] >= threshold_high: - dst[row, col] = strong - elif dst[row, col] <= threshold_low: - dst[row, col] = 0 + return destination + + +def detect_high_low_threshold( + image_shape, destination, threshold_low, threshold_high, weak, strong +): + """ + High-Low threshold detection. If an edge pixel’s gradient value is higher + than the high threshold value, it is marked as a strong edge pixel. If an + edge pixel’s gradient value is smaller than the high threshold value and + larger than the low threshold value, it is marked as a weak edge pixel. If + an edge pixel's value is smaller than the low threshold value, it will be + suppressed. + """ + for row in range(1, image_shape[0] - 1): + for col in range(1, image_shape[1] - 1): + if destination[row, col] >= threshold_high: + destination[row, col] = strong + elif destination[row, col] <= threshold_low: + destination[row, col] = 0 else: - dst[row, col] = weak + destination[row, col] = weak + +def track_edge(image_shape, destination, weak, strong): """ Edge tracking. Usually a weak edge pixel caused from true edges will be connected to a strong edge pixel while noise responses are unconnected. As long as there is one strong edge pixel that is involved in its 8-connected neighborhood, that weak edge point can be identified as one that should be preserved. """ - for row in range(1, image_row): - for col in range(1, image_col): - if dst[row, col] == weak: + for row in range(1, image_shape[0]): + for col in range(1, image_shape[1]): + if destination[row, col] == weak: if 255 in ( - dst[row, col + 1], - dst[row, col - 1], - dst[row - 1, col], - dst[row + 1, col], - dst[row - 1, col - 1], - dst[row + 1, col - 1], - dst[row - 1, col + 1], - dst[row + 1, col + 1], + destination[row, col + 1], + destination[row, col - 1], + destination[row - 1, col], + destination[row + 1, col], + destination[row - 1, col - 1], + destination[row + 1, col - 1], + destination[row - 1, col + 1], + destination[row + 1, col + 1], ): - dst[row, col] = strong + destination[row, col] = strong else: - dst[row, col] = 0 + destination[row, col] = 0 - return dst + +def canny(image, threshold_low=15, threshold_high=30, weak=128, strong=255): + # gaussian_filter + gaussian_out = img_convolve(image, gen_gaussian_kernel(9, sigma=1.4)) + # get the gradient and degree by sobel_filter + sobel_grad, sobel_theta = sobel_filter(gaussian_out) + gradient_direction = PI + np.rad2deg(sobel_theta) + + destination = suppress_non_maximum(image.shape, gradient_direction, sobel_grad) + + detect_high_low_threshold( + image.shape, destination, threshold_low, threshold_high, weak, strong + ) + + track_edge(image.shape, destination, weak, strong) + + return destination if __name__ == "__main__": # read original image in gray mode lena = cv2.imread(r"../image_data/lena.jpg", 0) # canny edge detection - canny_dst = canny(lena) - cv2.imshow("canny", canny_dst) + canny_destination = canny(lena) + cv2.imshow("canny", canny_destination) cv2.waitKey(0) From a213cea5f5a74e0a6b19240526779a3b0b1f270d Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Sat, 1 Apr 2023 12:39:22 -0400 Subject: [PATCH 618/726] Fix `mypy` errors in `dilation_operation.py` (#8595) * updating DIRECTORY.md * Fix mypy errors in dilation_operation.py * Rename functions to use snake case * updating DIRECTORY.md * updating DIRECTORY.md * Replace raw file string with pathlib Path * Update digital_image_processing/morphological_operations/dilation_operation.py Co-authored-by: Christian Clauss --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss --- .../dilation_operation.py | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/digital_image_processing/morphological_operations/dilation_operation.py b/digital_image_processing/morphological_operations/dilation_operation.py index c8380737d..e49b955c1 100644 --- a/digital_image_processing/morphological_operations/dilation_operation.py +++ b/digital_image_processing/morphological_operations/dilation_operation.py @@ -1,33 +1,35 @@ +from pathlib import Path + import numpy as np from PIL import Image -def rgb2gray(rgb: np.array) -> np.array: +def rgb_to_gray(rgb: np.ndarray) -> np.ndarray: """ Return gray image from rgb image - >>> rgb2gray(np.array([[[127, 255, 0]]])) + >>> rgb_to_gray(np.array([[[127, 255, 0]]])) array([[187.6453]]) - >>> rgb2gray(np.array([[[0, 0, 0]]])) + >>> rgb_to_gray(np.array([[[0, 0, 0]]])) array([[0.]]) - >>> rgb2gray(np.array([[[2, 4, 1]]])) + >>> rgb_to_gray(np.array([[[2, 4, 1]]])) array([[3.0598]]) - >>> rgb2gray(np.array([[[26, 255, 14], [5, 147, 20], [1, 200, 0]]])) + >>> rgb_to_gray(np.array([[[26, 255, 14], [5, 147, 20], [1, 200, 0]]])) array([[159.0524, 90.0635, 117.6989]]) """ r, g, b = rgb[:, :, 0], rgb[:, :, 1], rgb[:, :, 2] return 0.2989 * r + 0.5870 * g + 0.1140 * b -def gray2binary(gray: np.array) -> np.array: +def gray_to_binary(gray: np.ndarray) -> np.ndarray: """ Return binary image from gray image - >>> gray2binary(np.array([[127, 255, 0]])) + >>> gray_to_binary(np.array([[127, 255, 0]])) array([[False, True, False]]) - >>> gray2binary(np.array([[0]])) + >>> gray_to_binary(np.array([[0]])) array([[False]]) - >>> gray2binary(np.array([[26.2409, 4.9315, 1.4729]])) + >>> gray_to_binary(np.array([[26.2409, 4.9315, 1.4729]])) array([[False, False, False]]) - >>> gray2binary(np.array([[26, 255, 14], [5, 147, 20], [1, 200, 0]])) + >>> gray_to_binary(np.array([[26, 255, 14], [5, 147, 20], [1, 200, 0]])) array([[False, True, False], [False, True, False], [False, True, False]]) @@ -35,7 +37,7 @@ def gray2binary(gray: np.array) -> np.array: return (gray > 127) & (gray <= 255) -def dilation(image: np.array, kernel: np.array) -> np.array: +def dilation(image: np.ndarray, kernel: np.ndarray) -> np.ndarray: """ Return dilated image >>> dilation(np.array([[True, False, True]]), np.array([[0, 1, 0]])) @@ -61,14 +63,13 @@ def dilation(image: np.array, kernel: np.array) -> np.array: return output -# kernel to be applied -structuring_element = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]]) - - if __name__ == "__main__": # read original image - image = np.array(Image.open(r"..\image_data\lena.jpg")) - output = dilation(gray2binary(rgb2gray(image)), structuring_element) + lena_path = Path(__file__).resolve().parent / "image_data" / "lena.jpg" + lena = np.array(Image.open(lena_path)) + # kernel to be applied + structuring_element = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]]) + output = dilation(gray_to_binary(rgb_to_gray(lena)), structuring_element) # Save the output image pil_img = Image.fromarray(output).convert("RGB") pil_img.save("result_dilation.png") From 84b6852de80bb51c185c30942bff47f9c451c74d Mon Sep 17 00:00:00 2001 From: Blake Reimer Date: Sat, 1 Apr 2023 10:43:07 -0600 Subject: [PATCH 619/726] Graham's Law (#8162) * grahams law * doctest and type hints * doctest formatting * peer review updates --- physics/grahams_law.py | 208 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 physics/grahams_law.py diff --git a/physics/grahams_law.py b/physics/grahams_law.py new file mode 100644 index 000000000..6e5d75127 --- /dev/null +++ b/physics/grahams_law.py @@ -0,0 +1,208 @@ +""" +Title: Graham's Law of Effusion + +Description: Graham's law of effusion states that the rate of effusion of a gas is +inversely proportional to the square root of the molar mass of its particles: + +r1/r2 = sqrt(m2/m1) + +r1 = Rate of effusion for the first gas. +r2 = Rate of effusion for the second gas. +m1 = Molar mass of the first gas. +m2 = Molar mass of the second gas. + +(Description adapted from https://en.wikipedia.org/wiki/Graham%27s_law) +""" + +from math import pow, sqrt + + +def validate(*values: float) -> bool: + """ + Input Parameters: + ----------------- + effusion_rate_1: Effustion rate of first gas (m^2/s, mm^2/s, etc.) + effusion_rate_2: Effustion rate of second gas (m^2/s, mm^2/s, etc.) + molar_mass_1: Molar mass of the first gas (g/mol, kg/kmol, etc.) + molar_mass_2: Molar mass of the second gas (g/mol, kg/kmol, etc.) + + Returns: + -------- + >>> validate(2.016, 4.002) + True + >>> validate(-2.016, 4.002) + False + >>> validate() + False + """ + result = len(values) > 0 and all(value > 0.0 for value in values) + return result + + +def effusion_ratio(molar_mass_1: float, molar_mass_2: float) -> float | ValueError: + """ + Input Parameters: + ----------------- + molar_mass_1: Molar mass of the first gas (g/mol, kg/kmol, etc.) + molar_mass_2: Molar mass of the second gas (g/mol, kg/kmol, etc.) + + Returns: + -------- + >>> effusion_ratio(2.016, 4.002) + 1.408943 + >>> effusion_ratio(-2.016, 4.002) + ValueError('Input Error: Molar mass values must greater than 0.') + >>> effusion_ratio(2.016) + Traceback (most recent call last): + ... + TypeError: effusion_ratio() missing 1 required positional argument: 'molar_mass_2' + """ + return ( + round(sqrt(molar_mass_2 / molar_mass_1), 6) + if validate(molar_mass_1, molar_mass_2) + else ValueError("Input Error: Molar mass values must greater than 0.") + ) + + +def first_effusion_rate( + effusion_rate: float, molar_mass_1: float, molar_mass_2: float +) -> float | ValueError: + """ + Input Parameters: + ----------------- + effusion_rate: Effustion rate of second gas (m^2/s, mm^2/s, etc.) + molar_mass_1: Molar mass of the first gas (g/mol, kg/kmol, etc.) + molar_mass_2: Molar mass of the second gas (g/mol, kg/kmol, etc.) + + Returns: + -------- + >>> first_effusion_rate(1, 2.016, 4.002) + 1.408943 + >>> first_effusion_rate(-1, 2.016, 4.002) + ValueError('Input Error: Molar mass and effusion rate values must greater than 0.') + >>> first_effusion_rate(1) + Traceback (most recent call last): + ... + TypeError: first_effusion_rate() missing 2 required positional arguments: \ +'molar_mass_1' and 'molar_mass_2' + >>> first_effusion_rate(1, 2.016) + Traceback (most recent call last): + ... + TypeError: first_effusion_rate() missing 1 required positional argument: \ +'molar_mass_2' + """ + return ( + round(effusion_rate * sqrt(molar_mass_2 / molar_mass_1), 6) + if validate(effusion_rate, molar_mass_1, molar_mass_2) + else ValueError( + "Input Error: Molar mass and effusion rate values must greater than 0." + ) + ) + + +def second_effusion_rate( + effusion_rate: float, molar_mass_1: float, molar_mass_2: float +) -> float | ValueError: + """ + Input Parameters: + ----------------- + effusion_rate: Effustion rate of second gas (m^2/s, mm^2/s, etc.) + molar_mass_1: Molar mass of the first gas (g/mol, kg/kmol, etc.) + molar_mass_2: Molar mass of the second gas (g/mol, kg/kmol, etc.) + + Returns: + -------- + >>> second_effusion_rate(1, 2.016, 4.002) + 0.709752 + >>> second_effusion_rate(-1, 2.016, 4.002) + ValueError('Input Error: Molar mass and effusion rate values must greater than 0.') + >>> second_effusion_rate(1) + Traceback (most recent call last): + ... + TypeError: second_effusion_rate() missing 2 required positional arguments: \ +'molar_mass_1' and 'molar_mass_2' + >>> second_effusion_rate(1, 2.016) + Traceback (most recent call last): + ... + TypeError: second_effusion_rate() missing 1 required positional argument: \ +'molar_mass_2' + """ + return ( + round(effusion_rate / sqrt(molar_mass_2 / molar_mass_1), 6) + if validate(effusion_rate, molar_mass_1, molar_mass_2) + else ValueError( + "Input Error: Molar mass and effusion rate values must greater than 0." + ) + ) + + +def first_molar_mass( + molar_mass: float, effusion_rate_1: float, effusion_rate_2: float +) -> float | ValueError: + """ + Input Parameters: + ----------------- + molar_mass: Molar mass of the first gas (g/mol, kg/kmol, etc.) + effusion_rate_1: Effustion rate of first gas (m^2/s, mm^2/s, etc.) + effusion_rate_2: Effustion rate of second gas (m^2/s, mm^2/s, etc.) + + Returns: + -------- + >>> first_molar_mass(2, 1.408943, 0.709752) + 0.507524 + >>> first_molar_mass(-1, 2.016, 4.002) + ValueError('Input Error: Molar mass and effusion rate values must greater than 0.') + >>> first_molar_mass(1) + Traceback (most recent call last): + ... + TypeError: first_molar_mass() missing 2 required positional arguments: \ +'effusion_rate_1' and 'effusion_rate_2' + >>> first_molar_mass(1, 2.016) + Traceback (most recent call last): + ... + TypeError: first_molar_mass() missing 1 required positional argument: \ +'effusion_rate_2' + """ + return ( + round(molar_mass / pow(effusion_rate_1 / effusion_rate_2, 2), 6) + if validate(molar_mass, effusion_rate_1, effusion_rate_2) + else ValueError( + "Input Error: Molar mass and effusion rate values must greater than 0." + ) + ) + + +def second_molar_mass( + molar_mass: float, effusion_rate_1: float, effusion_rate_2: float +) -> float | ValueError: + """ + Input Parameters: + ----------------- + molar_mass: Molar mass of the first gas (g/mol, kg/kmol, etc.) + effusion_rate_1: Effustion rate of first gas (m^2/s, mm^2/s, etc.) + effusion_rate_2: Effustion rate of second gas (m^2/s, mm^2/s, etc.) + + Returns: + -------- + >>> second_molar_mass(2, 1.408943, 0.709752) + 1.970351 + >>> second_molar_mass(-2, 1.408943, 0.709752) + ValueError('Input Error: Molar mass and effusion rate values must greater than 0.') + >>> second_molar_mass(1) + Traceback (most recent call last): + ... + TypeError: second_molar_mass() missing 2 required positional arguments: \ +'effusion_rate_1' and 'effusion_rate_2' + >>> second_molar_mass(1, 2.016) + Traceback (most recent call last): + ... + TypeError: second_molar_mass() missing 1 required positional argument: \ +'effusion_rate_2' + """ + return ( + round(pow(effusion_rate_1 / effusion_rate_2, 2) / molar_mass, 6) + if validate(molar_mass, effusion_rate_1, effusion_rate_2) + else ValueError( + "Input Error: Molar mass and effusion rate values must greater than 0." + ) + ) From 56a40eb3ee9aa151defd97597f4e67acf294089f Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sat, 1 Apr 2023 20:43:11 +0300 Subject: [PATCH 620/726] Reenable files when TensorFlow supports the current Python (#8602) * Remove python_version < "3.11" for tensorflow * Reenable neural_network/input_data.py_tf * updating DIRECTORY.md * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Try to fix ruff * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Try to fix ruff * Try to fix ruff * Try to fix ruff * Try to fix pre-commit * Try to fix * Fix * Fix * Reenable dynamic_programming/k_means_clustering_tensorflow.py_tf * updating DIRECTORY.md * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Try to fix ruff --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- DIRECTORY.md | 2 + ...py_tf => k_means_clustering_tensorflow.py} | 9 +- .../{input_data.py_tf => input_data.py} | 96 +++++++++---------- requirements.txt | 2 +- 4 files changed, 54 insertions(+), 55 deletions(-) rename dynamic_programming/{k_means_clustering_tensorflow.py_tf => k_means_clustering_tensorflow.py} (98%) rename neural_network/{input_data.py_tf => input_data.py} (83%) diff --git a/DIRECTORY.md b/DIRECTORY.md index c781b17bf..34967082b 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -309,6 +309,7 @@ * [Floyd Warshall](dynamic_programming/floyd_warshall.py) * [Integer Partition](dynamic_programming/integer_partition.py) * [Iterating Through Submasks](dynamic_programming/iterating_through_submasks.py) + * [K Means Clustering Tensorflow](dynamic_programming/k_means_clustering_tensorflow.py) * [Knapsack](dynamic_programming/knapsack.py) * [Longest Common Subsequence](dynamic_programming/longest_common_subsequence.py) * [Longest Common Substring](dynamic_programming/longest_common_substring.py) @@ -685,6 +686,7 @@ * [2 Hidden Layers Neural Network](neural_network/2_hidden_layers_neural_network.py) * [Back Propagation Neural Network](neural_network/back_propagation_neural_network.py) * [Convolution Neural Network](neural_network/convolution_neural_network.py) + * [Input Data](neural_network/input_data.py) * [Perceptron](neural_network/perceptron.py) * [Simple Neural Network](neural_network/simple_neural_network.py) diff --git a/dynamic_programming/k_means_clustering_tensorflow.py_tf b/dynamic_programming/k_means_clustering_tensorflow.py similarity index 98% rename from dynamic_programming/k_means_clustering_tensorflow.py_tf rename to dynamic_programming/k_means_clustering_tensorflow.py index 4fbcedeaa..8d3f6f0df 100644 --- a/dynamic_programming/k_means_clustering_tensorflow.py_tf +++ b/dynamic_programming/k_means_clustering_tensorflow.py @@ -1,9 +1,10 @@ -import tensorflow as tf from random import shuffle + +import tensorflow as tf from numpy import array -def TFKMeansCluster(vectors, noofclusters): +def tf_k_means_cluster(vectors, noofclusters): """ K-Means Clustering using TensorFlow. 'vectors' should be a n*k 2-D NumPy array, where n is the number @@ -30,7 +31,6 @@ def TFKMeansCluster(vectors, noofclusters): graph = tf.Graph() with graph.as_default(): - # SESSION OF COMPUTATION sess = tf.Session() @@ -95,8 +95,7 @@ def TFKMeansCluster(vectors, noofclusters): # iterations. To keep things simple, we will only do a set number of # iterations, instead of using a Stopping Criterion. noofiterations = 100 - for iteration_n in range(noofiterations): - + for _ in range(noofiterations): ##EXPECTATION STEP ##Based on the centroid locations till last iteration, compute ##the _expected_ centroid assignments. diff --git a/neural_network/input_data.py_tf b/neural_network/input_data.py similarity index 83% rename from neural_network/input_data.py_tf rename to neural_network/input_data.py index 0e22ac0bc..2a32f0b82 100644 --- a/neural_network/input_data.py_tf +++ b/neural_network/input_data.py @@ -21,13 +21,10 @@ This module and all its submodules are deprecated. import collections import gzip import os +import urllib import numpy -from six.moves import urllib -from six.moves import xrange # pylint: disable=redefined-builtin - -from tensorflow.python.framework import dtypes -from tensorflow.python.framework import random_seed +from tensorflow.python.framework import dtypes, random_seed from tensorflow.python.platform import gfile from tensorflow.python.util.deprecation import deprecated @@ -46,16 +43,16 @@ def _read32(bytestream): def _extract_images(f): """Extract the images into a 4D uint8 numpy array [index, y, x, depth]. - Args: - f: A file object that can be passed into a gzip reader. + Args: + f: A file object that can be passed into a gzip reader. - Returns: - data: A 4D uint8 numpy array [index, y, x, depth]. + Returns: + data: A 4D uint8 numpy array [index, y, x, depth]. - Raises: - ValueError: If the bytestream does not start with 2051. + Raises: + ValueError: If the bytestream does not start with 2051. - """ + """ print("Extracting", f.name) with gzip.GzipFile(fileobj=f) as bytestream: magic = _read32(bytestream) @@ -86,17 +83,17 @@ def _dense_to_one_hot(labels_dense, num_classes): def _extract_labels(f, one_hot=False, num_classes=10): """Extract the labels into a 1D uint8 numpy array [index]. - Args: - f: A file object that can be passed into a gzip reader. - one_hot: Does one hot encoding for the result. - num_classes: Number of classes for the one hot encoding. + Args: + f: A file object that can be passed into a gzip reader. + one_hot: Does one hot encoding for the result. + num_classes: Number of classes for the one hot encoding. - Returns: - labels: a 1D uint8 numpy array. + Returns: + labels: a 1D uint8 numpy array. - Raises: - ValueError: If the bystream doesn't start with 2049. - """ + Raises: + ValueError: If the bystream doesn't start with 2049. + """ print("Extracting", f.name) with gzip.GzipFile(fileobj=f) as bytestream: magic = _read32(bytestream) @@ -115,8 +112,8 @@ def _extract_labels(f, one_hot=False, num_classes=10): class _DataSet: """Container class for a _DataSet (deprecated). - THIS CLASS IS DEPRECATED. - """ + THIS CLASS IS DEPRECATED. + """ @deprecated( None, @@ -135,21 +132,21 @@ class _DataSet: ): """Construct a _DataSet. - one_hot arg is used only if fake_data is true. `dtype` can be either - `uint8` to leave the input as `[0, 255]`, or `float32` to rescale into - `[0, 1]`. Seed arg provides for convenient deterministic testing. + one_hot arg is used only if fake_data is true. `dtype` can be either + `uint8` to leave the input as `[0, 255]`, or `float32` to rescale into + `[0, 1]`. Seed arg provides for convenient deterministic testing. - Args: - images: The images - labels: The labels - fake_data: Ignore inages and labels, use fake data. - one_hot: Bool, return the labels as one hot vectors (if True) or ints (if - False). - dtype: Output image dtype. One of [uint8, float32]. `uint8` output has - range [0,255]. float32 output has range [0,1]. - reshape: Bool. If True returned images are returned flattened to vectors. - seed: The random seed to use. - """ + Args: + images: The images + labels: The labels + fake_data: Ignore inages and labels, use fake data. + one_hot: Bool, return the labels as one hot vectors (if True) or ints (if + False). + dtype: Output image dtype. One of [uint8, float32]. `uint8` output has + range [0,255]. float32 output has range [0,1]. + reshape: Bool. If True returned images are returned flattened to vectors. + seed: The random seed to use. + """ seed1, seed2 = random_seed.get_seed(seed) # If op level seed is not set, use whatever graph level seed is returned numpy.random.seed(seed1 if seed is None else seed2) @@ -206,8 +203,8 @@ class _DataSet: else: fake_label = 0 return ( - [fake_image for _ in xrange(batch_size)], - [fake_label for _ in xrange(batch_size)], + [fake_image for _ in range(batch_size)], + [fake_label for _ in range(batch_size)], ) start = self._index_in_epoch # Shuffle for the first epoch @@ -250,19 +247,19 @@ class _DataSet: def _maybe_download(filename, work_directory, source_url): """Download the data from source url, unless it's already here. - Args: - filename: string, name of the file in the directory. - work_directory: string, path to working directory. - source_url: url to download from if file doesn't exist. + Args: + filename: string, name of the file in the directory. + work_directory: string, path to working directory. + source_url: url to download from if file doesn't exist. - Returns: - Path to resulting file. - """ + Returns: + Path to resulting file. + """ if not gfile.Exists(work_directory): gfile.MakeDirs(work_directory) filepath = os.path.join(work_directory, filename) if not gfile.Exists(filepath): - urllib.request.urlretrieve(source_url, filepath) + urllib.request.urlretrieve(source_url, filepath) # noqa: S310 with gfile.GFile(filepath) as f: size = f.size() print("Successfully downloaded", filename, size, "bytes.") @@ -328,7 +325,8 @@ def read_data_sets( if not 0 <= validation_size <= len(train_images): raise ValueError( - f"Validation size should be between 0 and {len(train_images)}. Received: {validation_size}." + f"Validation size should be between 0 and {len(train_images)}. " + f"Received: {validation_size}." ) validation_images = train_images[:validation_size] @@ -336,7 +334,7 @@ def read_data_sets( train_images = train_images[validation_size:] train_labels = train_labels[validation_size:] - options = dict(dtype=dtype, reshape=reshape, seed=seed) + options = {"dtype": dtype, "reshape": reshape, "seed": seed} train = _DataSet(train_images, train_labels, **options) validation = _DataSet(validation_images, validation_labels, **options) diff --git a/requirements.txt b/requirements.txt index a1d607df0..acfbc823e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,7 +15,7 @@ scikit-fuzzy scikit-learn statsmodels sympy -tensorflow; python_version < "3.11" +tensorflow texttable tweepy xgboost From 33114f0272bcc1fafa6ce0f40d92ded908747ce3 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Sat, 1 Apr 2023 16:05:01 -0400 Subject: [PATCH 621/726] Revamp `md5.py` (#8065) * Add type hints to md5.py * Rename some vars to snake case * Specify functions imported from math * Rename vars and functions to be more descriptive * Make tests from test function into doctests * Clarify more var names * Refactor some MD5 code into preprocess function * Simplify loop indices in get_block_words * Add more detailed comments, docs, and doctests * updating DIRECTORY.md * updating DIRECTORY.md * updating DIRECTORY.md * updating DIRECTORY.md * updating DIRECTORY.md * Add type hints to md5.py * Rename some vars to snake case * Specify functions imported from math * Rename vars and functions to be more descriptive * Make tests from test function into doctests * Clarify more var names * Refactor some MD5 code into preprocess function * Simplify loop indices in get_block_words * Add more detailed comments, docs, and doctests * updating DIRECTORY.md * updating DIRECTORY.md * updating DIRECTORY.md * updating DIRECTORY.md * Convert str types to bytes * Add tests comparing md5_me to hashlib's md5 * Replace line-break backslashes with parentheses --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 1 + hashes/md5.py | 376 ++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 292 insertions(+), 85 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 34967082b..b1adc23f6 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -717,6 +717,7 @@ * [Archimedes Principle](physics/archimedes_principle.py) * [Casimir Effect](physics/casimir_effect.py) * [Centripetal Force](physics/centripetal_force.py) + * [Grahams Law](physics/grahams_law.py) * [Horizontal Projectile Motion](physics/horizontal_projectile_motion.py) * [Hubble Parameter](physics/hubble_parameter.py) * [Ideal Gas Law](physics/ideal_gas_law.py) diff --git a/hashes/md5.py b/hashes/md5.py index 2020bf2e5..2187006ec 100644 --- a/hashes/md5.py +++ b/hashes/md5.py @@ -1,91 +1,223 @@ -import math +""" +The MD5 algorithm is a hash function that's commonly used as a checksum to +detect data corruption. The algorithm works by processing a given message in +blocks of 512 bits, padding the message as needed. It uses the blocks to operate +a 128-bit state and performs a total of 64 such operations. Note that all values +are little-endian, so inputs are converted as needed. + +Although MD5 was used as a cryptographic hash function in the past, it's since +been cracked, so it shouldn't be used for security purposes. + +For more info, see https://en.wikipedia.org/wiki/MD5 +""" + +from collections.abc import Generator +from math import sin -def rearrange(bit_string_32): - """[summary] - Regroups the given binary string. +def to_little_endian(string_32: bytes) -> bytes: + """ + Converts the given string to little-endian in groups of 8 chars. Arguments: - bitString32 {[string]} -- [32 bit binary] + string_32 {[string]} -- [32-char string] Raises: - ValueError -- [if the given string not are 32 bit binary string] + ValueError -- [input is not 32 char] Returns: - [string] -- [32 bit binary string] - >>> rearrange('1234567890abcdfghijklmnopqrstuvw') - 'pqrstuvwhijklmno90abcdfg12345678' + 32-char little-endian string + >>> to_little_endian(b'1234567890abcdfghijklmnopqrstuvw') + b'pqrstuvwhijklmno90abcdfg12345678' + >>> to_little_endian(b'1234567890') + Traceback (most recent call last): + ... + ValueError: Input must be of length 32 """ + if len(string_32) != 32: + raise ValueError("Input must be of length 32") - if len(bit_string_32) != 32: - raise ValueError("Need length 32") - new_string = "" + little_endian = b"" for i in [3, 2, 1, 0]: - new_string += bit_string_32[8 * i : 8 * i + 8] - return new_string + little_endian += string_32[8 * i : 8 * i + 8] + return little_endian -def reformat_hex(i): - """[summary] - Converts the given integer into 8-digit hex number. +def reformat_hex(i: int) -> bytes: + """ + Converts the given non-negative integer to hex string. + + Example: Suppose the input is the following: + i = 1234 + + The input is 0x000004d2 in hex, so the little-endian hex string is + "d2040000". Arguments: - i {[int]} -- [integer] + i {[int]} -- [integer] + + Raises: + ValueError -- [input is negative] + + Returns: + 8-char little-endian hex string + + >>> reformat_hex(1234) + b'd2040000' >>> reformat_hex(666) - '9a020000' + b'9a020000' + >>> reformat_hex(0) + b'00000000' + >>> reformat_hex(1234567890) + b'd2029649' + >>> reformat_hex(1234567890987654321) + b'b11c6cb1' + >>> reformat_hex(-1) + Traceback (most recent call last): + ... + ValueError: Input must be non-negative """ + if i < 0: + raise ValueError("Input must be non-negative") - hexrep = format(i, "08x") - thing = "" + hex_rep = format(i, "08x")[-8:] + little_endian_hex = b"" for i in [3, 2, 1, 0]: - thing += hexrep[2 * i : 2 * i + 2] - return thing + little_endian_hex += hex_rep[2 * i : 2 * i + 2].encode("utf-8") + return little_endian_hex -def pad(bit_string): - """[summary] - Fills up the binary string to a 512 bit binary string +def preprocess(message: bytes) -> bytes: + """ + Preprocesses the message string: + - Convert message to bit string + - Pad bit string to a multiple of 512 chars: + - Append a 1 + - Append 0's until length = 448 (mod 512) + - Append length of original message (64 chars) + + Example: Suppose the input is the following: + message = "a" + + The message bit string is "01100001", which is 8 bits long. Thus, the + bit string needs 439 bits of padding so that + (bit_string + "1" + padding) = 448 (mod 512). + The message length is "000010000...0" in 64-bit little-endian binary. + The combined bit string is then 512 bits long. Arguments: - bitString {[string]} -- [binary string] + message {[string]} -- [message string] Returns: - [string] -- [binary string] + processed bit string padded to a multiple of 512 chars + + >>> preprocess(b"a") == (b"01100001" + b"1" + + ... (b"0" * 439) + b"00001000" + (b"0" * 56)) + True + >>> preprocess(b"") == b"1" + (b"0" * 447) + (b"0" * 64) + True """ - start_length = len(bit_string) - bit_string += "1" + bit_string = b"" + for char in message: + bit_string += format(char, "08b").encode("utf-8") + start_len = format(len(bit_string), "064b").encode("utf-8") + + # Pad bit_string to a multiple of 512 chars + bit_string += b"1" while len(bit_string) % 512 != 448: - bit_string += "0" - last_part = format(start_length, "064b") - bit_string += rearrange(last_part[32:]) + rearrange(last_part[:32]) + bit_string += b"0" + bit_string += to_little_endian(start_len[32:]) + to_little_endian(start_len[:32]) + return bit_string -def get_block(bit_string): - """[summary] - Iterator: - Returns by each call a list of length 16 with the 32 bit - integer blocks. +def get_block_words(bit_string: bytes) -> Generator[list[int], None, None]: + """ + Splits bit string into blocks of 512 chars and yields each block as a list + of 32-bit words + + Example: Suppose the input is the following: + bit_string = + "000000000...0" + # 0x00 (32 bits, padded to the right) + "000000010...0" + # 0x01 (32 bits, padded to the right) + "000000100...0" + # 0x02 (32 bits, padded to the right) + "000000110...0" + # 0x03 (32 bits, padded to the right) + ... + "000011110...0" # 0x0a (32 bits, padded to the right) + + Then len(bit_string) == 512, so there'll be 1 block. The block is split + into 32-bit words, and each word is converted to little endian. The + first word is interpreted as 0 in decimal, the second word is + interpreted as 1 in decimal, etc. + + Thus, block_words == [[0, 1, 2, 3, ..., 15]]. Arguments: - bit_string {[string]} -- [binary string >= 512] + bit_string {[string]} -- [bit string with multiple of 512 as length] + + Raises: + ValueError -- [length of bit string isn't multiple of 512] + + Yields: + a list of 16 32-bit words + + >>> test_string = ("".join(format(n << 24, "032b") for n in range(16)) + ... .encode("utf-8")) + >>> list(get_block_words(test_string)) + [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]] + >>> list(get_block_words(test_string * 4)) == [list(range(16))] * 4 + True + >>> list(get_block_words(b"1" * 512)) == [[4294967295] * 16] + True + >>> list(get_block_words(b"")) + [] + >>> list(get_block_words(b"1111")) + Traceback (most recent call last): + ... + ValueError: Input must have length that's a multiple of 512 """ + if len(bit_string) % 512 != 0: + raise ValueError("Input must have length that's a multiple of 512") - curr_pos = 0 - while curr_pos < len(bit_string): - curr_part = bit_string[curr_pos : curr_pos + 512] - my_splits = [] - for i in range(16): - my_splits.append(int(rearrange(curr_part[32 * i : 32 * i + 32]), 2)) - yield my_splits - curr_pos += 512 + for pos in range(0, len(bit_string), 512): + block = bit_string[pos : pos + 512] + block_words = [] + for i in range(0, 512, 32): + block_words.append(int(to_little_endian(block[i : i + 32]), 2)) + yield block_words -def not32(i): +def not_32(i: int) -> int: """ - >>> not32(34) + Perform bitwise NOT on given int. + + Arguments: + i {[int]} -- [given int] + + Raises: + ValueError -- [input is negative] + + Returns: + Result of bitwise NOT on i + + >>> not_32(34) 4294967261 + >>> not_32(1234) + 4294966061 + >>> not_32(4294966061) + 1234 + >>> not_32(0) + 4294967295 + >>> not_32(1) + 4294967294 + >>> not_32(-1) + Traceback (most recent call last): + ... + ValueError: Input must be non-negative """ + if i < 0: + raise ValueError("Input must be non-negative") + i_str = format(i, "032b") new_str = "" for c in i_str: @@ -93,35 +225,114 @@ def not32(i): return int(new_str, 2) -def sum32(a, b): +def sum_32(a: int, b: int) -> int: + """ + Add two numbers as 32-bit ints. + + Arguments: + a {[int]} -- [first given int] + b {[int]} -- [second given int] + + Returns: + (a + b) as an unsigned 32-bit int + + >>> sum_32(1, 1) + 2 + >>> sum_32(2, 3) + 5 + >>> sum_32(0, 0) + 0 + >>> sum_32(-1, -1) + 4294967294 + >>> sum_32(4294967295, 1) + 0 + """ return (a + b) % 2**32 -def leftrot32(i, s): - return (i << s) ^ (i >> (32 - s)) - - -def md5me(test_string): - """[summary] - Returns a 32-bit hash code of the string 'testString' +def left_rotate_32(i: int, shift: int) -> int: + """ + Rotate the bits of a given int left by a given amount. Arguments: - testString {[string]} -- [message] + i {[int]} -- [given int] + shift {[int]} -- [shift amount] + + Raises: + ValueError -- [either given int or shift is negative] + + Returns: + `i` rotated to the left by `shift` bits + + >>> left_rotate_32(1234, 1) + 2468 + >>> left_rotate_32(1111, 4) + 17776 + >>> left_rotate_32(2147483648, 1) + 1 + >>> left_rotate_32(2147483648, 3) + 4 + >>> left_rotate_32(4294967295, 4) + 4294967295 + >>> left_rotate_32(1234, 0) + 1234 + >>> left_rotate_32(0, 0) + 0 + >>> left_rotate_32(-1, 0) + Traceback (most recent call last): + ... + ValueError: Input must be non-negative + >>> left_rotate_32(0, -1) + Traceback (most recent call last): + ... + ValueError: Shift must be non-negative + """ + if i < 0: + raise ValueError("Input must be non-negative") + if shift < 0: + raise ValueError("Shift must be non-negative") + return ((i << shift) ^ (i >> (32 - shift))) % 2**32 + + +def md5_me(message: bytes) -> bytes: + """ + Returns the 32-char MD5 hash of a given message. + + Reference: https://en.wikipedia.org/wiki/MD5#Algorithm + + Arguments: + message {[string]} -- [message] + + Returns: + 32-char MD5 hash string + + >>> md5_me(b"") + b'd41d8cd98f00b204e9800998ecf8427e' + >>> md5_me(b"The quick brown fox jumps over the lazy dog") + b'9e107d9d372bb6826bd81d3542a419d6' + >>> md5_me(b"The quick brown fox jumps over the lazy dog.") + b'e4d909c290d0fb1ca068ffaddf22cbd0' + + >>> import hashlib + >>> from string import ascii_letters + >>> msgs = [b"", ascii_letters.encode("utf-8"), "Üñîçø∂é".encode("utf-8"), + ... b"The quick brown fox jumps over the lazy dog."] + >>> all(md5_me(msg) == hashlib.md5(msg).hexdigest().encode("utf-8") for msg in msgs) + True """ - bs = "" - for i in test_string: - bs += format(ord(i), "08b") - bs = pad(bs) + # Convert to bit string, add padding and append message length + bit_string = preprocess(message) - tvals = [int(2**32 * abs(math.sin(i + 1))) for i in range(64)] + added_consts = [int(2**32 * abs(sin(i + 1))) for i in range(64)] + # Starting states a0 = 0x67452301 b0 = 0xEFCDAB89 c0 = 0x98BADCFE d0 = 0x10325476 - s = [ + shift_amounts = [ 7, 12, 17, @@ -188,51 +399,46 @@ def md5me(test_string): 21, ] - for m in get_block(bs): + # Process bit string in chunks, each with 16 32-char words + for block_words in get_block_words(bit_string): a = a0 b = b0 c = c0 d = d0 + + # Hash current chunk for i in range(64): if i <= 15: - # f = (B & C) | (not32(B) & D) + # f = (b & c) | (not_32(b) & d) # Alternate definition for f f = d ^ (b & (c ^ d)) g = i elif i <= 31: - # f = (D & B) | (not32(D) & C) + # f = (d & b) | (not_32(d) & c) # Alternate definition for f f = c ^ (d & (b ^ c)) g = (5 * i + 1) % 16 elif i <= 47: f = b ^ c ^ d g = (3 * i + 5) % 16 else: - f = c ^ (b | not32(d)) + f = c ^ (b | not_32(d)) g = (7 * i) % 16 - dtemp = d + f = (f + a + added_consts[i] + block_words[g]) % 2**32 + a = d d = c c = b - b = sum32(b, leftrot32((a + f + tvals[i] + m[g]) % 2**32, s[i])) - a = dtemp - a0 = sum32(a0, a) - b0 = sum32(b0, b) - c0 = sum32(c0, c) - d0 = sum32(d0, d) + b = sum_32(b, left_rotate_32(f, shift_amounts[i])) + + # Add hashed chunk to running total + a0 = sum_32(a0, a) + b0 = sum_32(b0, b) + c0 = sum_32(c0, c) + d0 = sum_32(d0, d) digest = reformat_hex(a0) + reformat_hex(b0) + reformat_hex(c0) + reformat_hex(d0) return digest -def test(): - assert md5me("") == "d41d8cd98f00b204e9800998ecf8427e" - assert ( - md5me("The quick brown fox jumps over the lazy dog") - == "9e107d9d372bb6826bd81d3542a419d6" - ) - print("Success.") - - if __name__ == "__main__": - test() import doctest doctest.testmod() From 5ca71895630719cc41f8171aba8be461fb8cc9d2 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sun, 2 Apr 2023 06:48:19 +0200 Subject: [PATCH 622/726] Rename quantum_random.py.DISABLED.txt to quantum_random.py (#8601) Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 1 + quantum/{quantum_random.py.DISABLED.txt => quantum_random.py} | 0 2 files changed, 1 insertion(+) rename quantum/{quantum_random.py.DISABLED.txt => quantum_random.py} (100%) diff --git a/DIRECTORY.md b/DIRECTORY.md index b1adc23f6..8dd3fb5d9 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -1033,6 +1033,7 @@ * [Q Fourier Transform](quantum/q_fourier_transform.py) * [Q Full Adder](quantum/q_full_adder.py) * [Quantum Entanglement](quantum/quantum_entanglement.py) + * [Quantum Random](quantum/quantum_random.py) * [Quantum Teleportation](quantum/quantum_teleportation.py) * [Ripple Adder Classic](quantum/ripple_adder_classic.py) * [Single Qubit Measure](quantum/single_qubit_measure.py) diff --git a/quantum/quantum_random.py.DISABLED.txt b/quantum/quantum_random.py similarity index 100% rename from quantum/quantum_random.py.DISABLED.txt rename to quantum/quantum_random.py From ebc2d5d79f837931e80f7d5e7e1dece9ef48f760 Mon Sep 17 00:00:00 2001 From: Ishab Date: Sun, 2 Apr 2023 13:04:11 +0100 Subject: [PATCH 623/726] Add Project Euler problem 79 solution 1 (#8607) Co-authored-by: Dhruv Manilawala --- project_euler/problem_079/__init__.py | 0 project_euler/problem_079/keylog.txt | 50 ++++++++++++++++ project_euler/problem_079/keylog_test.txt | 16 ++++++ project_euler/problem_079/sol1.py | 69 +++++++++++++++++++++++ 4 files changed, 135 insertions(+) create mode 100644 project_euler/problem_079/__init__.py create mode 100644 project_euler/problem_079/keylog.txt create mode 100644 project_euler/problem_079/keylog_test.txt create mode 100644 project_euler/problem_079/sol1.py diff --git a/project_euler/problem_079/__init__.py b/project_euler/problem_079/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_079/keylog.txt b/project_euler/problem_079/keylog.txt new file mode 100644 index 000000000..41f156732 --- /dev/null +++ b/project_euler/problem_079/keylog.txt @@ -0,0 +1,50 @@ +319 +680 +180 +690 +129 +620 +762 +689 +762 +318 +368 +710 +720 +710 +629 +168 +160 +689 +716 +731 +736 +729 +316 +729 +729 +710 +769 +290 +719 +680 +318 +389 +162 +289 +162 +718 +729 +319 +790 +680 +890 +362 +319 +760 +316 +729 +380 +319 +728 +716 diff --git a/project_euler/problem_079/keylog_test.txt b/project_euler/problem_079/keylog_test.txt new file mode 100644 index 000000000..2c7024bde --- /dev/null +++ b/project_euler/problem_079/keylog_test.txt @@ -0,0 +1,16 @@ +319 +680 +180 +690 +129 +620 +698 +318 +328 +310 +320 +610 +629 +198 +190 +631 diff --git a/project_euler/problem_079/sol1.py b/project_euler/problem_079/sol1.py new file mode 100644 index 000000000..d34adcd24 --- /dev/null +++ b/project_euler/problem_079/sol1.py @@ -0,0 +1,69 @@ +""" +Project Euler Problem 79: https://projecteuler.net/problem=79 + +Passcode derivation + +A common security method used for online banking is to ask the user for three +random characters from a passcode. For example, if the passcode was 531278, +they may ask for the 2nd, 3rd, and 5th characters; the expected reply would +be: 317. + +The text file, keylog.txt, contains fifty successful login attempts. + +Given that the three characters are always asked for in order, analyse the file +so as to determine the shortest possible secret passcode of unknown length. +""" +import itertools +from pathlib import Path + + +def find_secret_passcode(logins: list[str]) -> int: + """ + Returns the shortest possible secret passcode of unknown length. + + >>> find_secret_passcode(["135", "259", "235", "189", "690", "168", "120", + ... "136", "289", "589", "160", "165", "580", "369", "250", "280"]) + 12365890 + + >>> find_secret_passcode(["426", "281", "061", "819" "268", "406", "420", + ... "428", "209", "689", "019", "421", "469", "261", "681", "201"]) + 4206819 + """ + + # Split each login by character e.g. '319' -> ('3', '1', '9') + split_logins = [tuple(login) for login in logins] + + unique_chars = {char for login in split_logins for char in login} + + for permutation in itertools.permutations(unique_chars): + satisfied = True + for login in logins: + if not ( + permutation.index(login[0]) + < permutation.index(login[1]) + < permutation.index(login[2]) + ): + satisfied = False + break + + if satisfied: + return int("".join(permutation)) + + raise Exception("Unable to find the secret passcode") + + +def solution(input_file: str = "keylog.txt") -> int: + """ + Returns the shortest possible secret passcode of unknown length + for successful login attempts given by `input_file` text file. + + >>> solution("keylog_test.txt") + 6312980 + """ + logins = Path(__file__).parent.joinpath(input_file).read_text().splitlines() + + return find_secret_passcode(logins) + + +if __name__ == "__main__": + print(f"{solution() = }") From 740ecfb121009612310ab9e1bc9d6ffe22b62ae4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 4 Apr 2023 07:00:31 +0530 Subject: [PATCH 624/726] [pre-commit.ci] pre-commit autoupdate (#8611) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/charliermarsh/ruff-pre-commit: v0.0.259 → v0.0.260](https://github.com/charliermarsh/ruff-pre-commit/compare/v0.0.259...v0.0.260) - [github.com/psf/black: 23.1.0 → 23.3.0](https://github.com/psf/black/compare/23.1.0...23.3.0) - [github.com/abravalheri/validate-pyproject: v0.12.1 → v0.12.2](https://github.com/abravalheri/validate-pyproject/compare/v0.12.1...v0.12.2) --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- DIRECTORY.md | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 72a878387..d54ce5add 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,12 +16,12 @@ repos: - id: auto-walrus - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.259 + rev: v0.0.260 hooks: - id: ruff - repo: https://github.com/psf/black - rev: 23.1.0 + rev: 23.3.0 hooks: - id: black @@ -46,7 +46,7 @@ repos: pass_filenames: false - repo: https://github.com/abravalheri/validate-pyproject - rev: v0.12.1 + rev: v0.12.2 hooks: - id: validate-pyproject diff --git a/DIRECTORY.md b/DIRECTORY.md index 8dd3fb5d9..3764c471c 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -922,6 +922,8 @@ * [Sol1](project_euler/problem_077/sol1.py) * Problem 078 * [Sol1](project_euler/problem_078/sol1.py) + * Problem 079 + * [Sol1](project_euler/problem_079/sol1.py) * Problem 080 * [Sol1](project_euler/problem_080/sol1.py) * Problem 081 From b2b8585e63664a0c7aa18b95528e345c2738c4ae Mon Sep 17 00:00:00 2001 From: Ishan Dutta Date: Fri, 7 Apr 2023 21:21:25 +0530 Subject: [PATCH 625/726] Add LeNet Implementation in PyTorch (#7070) * add torch to requirements * add lenet architecture in pytorch * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add type hints * remove file * add type hints * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * update variable name * add fail test * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add newline * reformatting --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- computer_vision/lenet_pytorch.py | 82 ++++++++++++++++++++++++++++++++ requirements.txt | 1 + 2 files changed, 83 insertions(+) create mode 100644 computer_vision/lenet_pytorch.py diff --git a/computer_vision/lenet_pytorch.py b/computer_vision/lenet_pytorch.py new file mode 100644 index 000000000..177a5ebfc --- /dev/null +++ b/computer_vision/lenet_pytorch.py @@ -0,0 +1,82 @@ +""" +LeNet Network + +Paper: http://vision.stanford.edu/cs598_spring07/papers/Lecun98.pdf +""" + +import numpy +import torch +import torch.nn as nn + + +class LeNet(nn.Module): + def __init__(self) -> None: + super().__init__() + + self.tanh = nn.Tanh() + self.avgpool = nn.AvgPool2d(kernel_size=2, stride=2) + + self.conv1 = nn.Conv2d( + in_channels=1, + out_channels=6, + kernel_size=(5, 5), + stride=(1, 1), + padding=(0, 0), + ) + self.conv2 = nn.Conv2d( + in_channels=6, + out_channels=16, + kernel_size=(5, 5), + stride=(1, 1), + padding=(0, 0), + ) + self.conv3 = nn.Conv2d( + in_channels=16, + out_channels=120, + kernel_size=(5, 5), + stride=(1, 1), + padding=(0, 0), + ) + + self.linear1 = nn.Linear(120, 84) + self.linear2 = nn.Linear(84, 10) + + def forward(self, image_array: numpy.ndarray) -> numpy.ndarray: + image_array = self.tanh(self.conv1(image_array)) + image_array = self.avgpool(image_array) + image_array = self.tanh(self.conv2(image_array)) + image_array = self.avgpool(image_array) + image_array = self.tanh(self.conv3(image_array)) + + image_array = image_array.reshape(image_array.shape[0], -1) + image_array = self.tanh(self.linear1(image_array)) + image_array = self.linear2(image_array) + return image_array + + +def test_model(image_tensor: torch.tensor) -> bool: + """ + Test the model on an input batch of 64 images + + Args: + image_tensor (torch.tensor): Batch of Images for the model + + >>> test_model(torch.randn(64, 1, 32, 32)) + True + + """ + try: + model = LeNet() + output = model(image_tensor) + except RuntimeError: + return False + + return output.shape == torch.zeros([64, 10]).shape + + +if __name__ == "__main__": + random_image_1 = torch.randn(64, 1, 32, 32) + random_image_2 = torch.randn(1, 32, 32) + + print(f"random_image_1 Model Passed: {test_model(random_image_1)}") + print(f"\nrandom_image_2 Model Passed: {test_model(random_image_2)}") diff --git a/requirements.txt b/requirements.txt index acfbc823e..e159fe010 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,6 +17,7 @@ statsmodels sympy tensorflow texttable +torch tweepy xgboost yulewalker From 179298e3a291470ef30e850f23d98c2fb9055202 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 8 Apr 2023 02:52:26 +0200 Subject: [PATCH 626/726] Revert "Add LeNet Implementation in PyTorch (#7070)" (#8621) This reverts commit b2b8585e63664a0c7aa18b95528e345c2738c4ae. --- computer_vision/lenet_pytorch.py | 82 -------------------------------- requirements.txt | 1 - 2 files changed, 83 deletions(-) delete mode 100644 computer_vision/lenet_pytorch.py diff --git a/computer_vision/lenet_pytorch.py b/computer_vision/lenet_pytorch.py deleted file mode 100644 index 177a5ebfc..000000000 --- a/computer_vision/lenet_pytorch.py +++ /dev/null @@ -1,82 +0,0 @@ -""" -LeNet Network - -Paper: http://vision.stanford.edu/cs598_spring07/papers/Lecun98.pdf -""" - -import numpy -import torch -import torch.nn as nn - - -class LeNet(nn.Module): - def __init__(self) -> None: - super().__init__() - - self.tanh = nn.Tanh() - self.avgpool = nn.AvgPool2d(kernel_size=2, stride=2) - - self.conv1 = nn.Conv2d( - in_channels=1, - out_channels=6, - kernel_size=(5, 5), - stride=(1, 1), - padding=(0, 0), - ) - self.conv2 = nn.Conv2d( - in_channels=6, - out_channels=16, - kernel_size=(5, 5), - stride=(1, 1), - padding=(0, 0), - ) - self.conv3 = nn.Conv2d( - in_channels=16, - out_channels=120, - kernel_size=(5, 5), - stride=(1, 1), - padding=(0, 0), - ) - - self.linear1 = nn.Linear(120, 84) - self.linear2 = nn.Linear(84, 10) - - def forward(self, image_array: numpy.ndarray) -> numpy.ndarray: - image_array = self.tanh(self.conv1(image_array)) - image_array = self.avgpool(image_array) - image_array = self.tanh(self.conv2(image_array)) - image_array = self.avgpool(image_array) - image_array = self.tanh(self.conv3(image_array)) - - image_array = image_array.reshape(image_array.shape[0], -1) - image_array = self.tanh(self.linear1(image_array)) - image_array = self.linear2(image_array) - return image_array - - -def test_model(image_tensor: torch.tensor) -> bool: - """ - Test the model on an input batch of 64 images - - Args: - image_tensor (torch.tensor): Batch of Images for the model - - >>> test_model(torch.randn(64, 1, 32, 32)) - True - - """ - try: - model = LeNet() - output = model(image_tensor) - except RuntimeError: - return False - - return output.shape == torch.zeros([64, 10]).shape - - -if __name__ == "__main__": - random_image_1 = torch.randn(64, 1, 32, 32) - random_image_2 = torch.randn(1, 32, 32) - - print(f"random_image_1 Model Passed: {test_model(random_image_1)}") - print(f"\nrandom_image_2 Model Passed: {test_model(random_image_2)}") diff --git a/requirements.txt b/requirements.txt index e159fe010..acfbc823e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,7 +17,6 @@ statsmodels sympy tensorflow texttable -torch tweepy xgboost yulewalker From 5cb0a000c47398c6d8af1ac43e2f83ae018f7182 Mon Sep 17 00:00:00 2001 From: amirsoroush <114881632+amirsoroush@users.noreply.github.com> Date: Sat, 8 Apr 2023 14:41:08 +0300 Subject: [PATCH 627/726] Queue implementation using two Stacks (#8617) * Queue implementation using two Stacks * fix typo in queue/queue_on_two_stacks.py * add 'iterable' to queue_on_two_stacks initializer * make queue_on_two_stacks.py generic class * fix ruff-UP007 in queue_on_two_stacks.py * enhance readability in queue_on_two_stacks.py * Create queue_by_two_stacks.py --------- Co-authored-by: Christian Clauss --- data_structures/queue/queue_by_two_stacks.py | 115 ++++++++++++++++ data_structures/queue/queue_on_two_stacks.py | 137 +++++++++++++++++++ 2 files changed, 252 insertions(+) create mode 100644 data_structures/queue/queue_by_two_stacks.py create mode 100644 data_structures/queue/queue_on_two_stacks.py diff --git a/data_structures/queue/queue_by_two_stacks.py b/data_structures/queue/queue_by_two_stacks.py new file mode 100644 index 000000000..cd62f155a --- /dev/null +++ b/data_structures/queue/queue_by_two_stacks.py @@ -0,0 +1,115 @@ +"""Queue implementation using two stacks""" + +from collections.abc import Iterable +from typing import Generic, TypeVar + +_T = TypeVar("_T") + + +class QueueByTwoStacks(Generic[_T]): + def __init__(self, iterable: Iterable[_T] | None = None) -> None: + """ + >>> QueueByTwoStacks() + Queue(()) + >>> QueueByTwoStacks([10, 20, 30]) + Queue((10, 20, 30)) + >>> QueueByTwoStacks((i**2 for i in range(1, 4))) + Queue((1, 4, 9)) + """ + self._stack1: list[_T] = list(iterable or []) + self._stack2: list[_T] = [] + + def __len__(self) -> int: + """ + >>> len(QueueByTwoStacks()) + 0 + >>> from string import ascii_lowercase + >>> len(QueueByTwoStacks(ascii_lowercase)) + 26 + >>> queue = QueueByTwoStacks() + >>> for i in range(1, 11): + ... queue.put(i) + ... + >>> len(queue) + 10 + >>> for i in range(2): + ... queue.get() + 1 + 2 + >>> len(queue) + 8 + """ + + return len(self._stack1) + len(self._stack2) + + def __repr__(self) -> str: + """ + >>> queue = QueueByTwoStacks() + >>> queue + Queue(()) + >>> str(queue) + 'Queue(())' + >>> queue.put(10) + >>> queue + Queue((10,)) + >>> queue.put(20) + >>> queue.put(30) + >>> queue + Queue((10, 20, 30)) + """ + return f"Queue({tuple(self._stack2[::-1] + self._stack1)})" + + def put(self, item: _T) -> None: + """ + Put `item` into the Queue + + >>> queue = QueueByTwoStacks() + >>> queue.put(10) + >>> queue.put(20) + >>> len(queue) + 2 + >>> queue + Queue((10, 20)) + """ + + self._stack1.append(item) + + def get(self) -> _T: + """ + Get `item` from the Queue + + >>> queue = QueueByTwoStacks((10, 20, 30)) + >>> queue.get() + 10 + >>> queue.put(40) + >>> queue.get() + 20 + >>> queue.get() + 30 + >>> len(queue) + 1 + >>> queue.get() + 40 + >>> queue.get() + Traceback (most recent call last): + ... + IndexError: Queue is empty + """ + + # To reduce number of attribute look-ups in `while` loop. + stack1_pop = self._stack1.pop + stack2_append = self._stack2.append + + if not self._stack2: + while self._stack1: + stack2_append(stack1_pop()) + + if not self._stack2: + raise IndexError("Queue is empty") + return self._stack2.pop() + + +if __name__ == "__main__": + from doctest import testmod + + testmod() diff --git a/data_structures/queue/queue_on_two_stacks.py b/data_structures/queue/queue_on_two_stacks.py new file mode 100644 index 000000000..61db2b512 --- /dev/null +++ b/data_structures/queue/queue_on_two_stacks.py @@ -0,0 +1,137 @@ +"""Queue implementation using two stacks""" + +from collections.abc import Iterable +from typing import Generic, TypeVar + +_T = TypeVar("_T") + + +class QueueByTwoStacks(Generic[_T]): + def __init__(self, iterable: Iterable[_T] | None = None) -> None: + """ + >>> queue1 = QueueByTwoStacks() + >>> str(queue1) + 'Queue([])' + >>> queue2 = QueueByTwoStacks([10, 20, 30]) + >>> str(queue2) + 'Queue([10, 20, 30])' + >>> queue3 = QueueByTwoStacks((i**2 for i in range(1, 4))) + >>> str(queue3) + 'Queue([1, 4, 9])' + """ + + self._stack1: list[_T] = [] if iterable is None else list(iterable) + self._stack2: list[_T] = [] + + def __len__(self) -> int: + """ + >>> queue = QueueByTwoStacks() + >>> for i in range(1, 11): + ... queue.put(i) + ... + >>> len(queue) == 10 + True + >>> for i in range(2): + ... queue.get() + 1 + 2 + >>> len(queue) == 8 + True + """ + + return len(self._stack1) + len(self._stack2) + + def __repr__(self) -> str: + """ + >>> queue = QueueByTwoStacks() + >>> queue + Queue([]) + >>> str(queue) + 'Queue([])' + >>> queue.put(10) + >>> queue + Queue([10]) + >>> queue.put(20) + >>> queue.put(30) + >>> queue + Queue([10, 20, 30]) + """ + + items = self._stack2[::-1] + self._stack1 + return f"Queue({items})" + + def put(self, item: _T) -> None: + """ + Put `item` into the Queue + + >>> queue = QueueByTwoStacks() + >>> queue.put(10) + >>> queue.put(20) + >>> len(queue) == 2 + True + >>> str(queue) + 'Queue([10, 20])' + """ + + self._stack1.append(item) + + def get(self) -> _T: + """ + Get `item` from the Queue + + >>> queue = QueueByTwoStacks() + >>> for i in (10, 20, 30): + ... queue.put(i) + >>> queue.get() + 10 + >>> queue.put(40) + >>> queue.get() + 20 + >>> queue.get() + 30 + >>> len(queue) == 1 + True + >>> queue.get() + 40 + >>> queue.get() + Traceback (most recent call last): + ... + IndexError: Queue is empty + """ + + # To reduce number of attribute look-ups in `while` loop. + stack1_pop = self._stack1.pop + stack2_append = self._stack2.append + + if not self._stack2: + while self._stack1: + stack2_append(stack1_pop()) + + if not self._stack2: + raise IndexError("Queue is empty") + return self._stack2.pop() + + def size(self) -> int: + """ + Returns the length of the Queue + + >>> queue = QueueByTwoStacks() + >>> queue.size() + 0 + >>> queue.put(10) + >>> queue.put(20) + >>> queue.size() + 2 + >>> queue.get() + 10 + >>> queue.size() == 1 + True + """ + + return len(self) + + +if __name__ == "__main__": + from doctest import testmod + + testmod() From 2f9b03393c75f3ab14b491becae4ac5caf26de17 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 8 Apr 2023 14:16:19 +0200 Subject: [PATCH 628/726] Delete queue_on_two_stacks.py which duplicates queue_by_two_stacks.py (#8624) * Delete queue_on_two_stacks.py which duplicates queue_by_two_stacks.py * updating DIRECTORY.md --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 1 + data_structures/queue/queue_on_two_stacks.py | 137 ------------------- 2 files changed, 1 insertion(+), 137 deletions(-) delete mode 100644 data_structures/queue/queue_on_two_stacks.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 3764c471c..e3e0748ec 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -232,6 +232,7 @@ * [Double Ended Queue](data_structures/queue/double_ended_queue.py) * [Linked Queue](data_structures/queue/linked_queue.py) * [Priority Queue Using List](data_structures/queue/priority_queue_using_list.py) + * [Queue By Two Stacks](data_structures/queue/queue_by_two_stacks.py) * [Queue On List](data_structures/queue/queue_on_list.py) * [Queue On Pseudo Stack](data_structures/queue/queue_on_pseudo_stack.py) * Stacks diff --git a/data_structures/queue/queue_on_two_stacks.py b/data_structures/queue/queue_on_two_stacks.py deleted file mode 100644 index 61db2b512..000000000 --- a/data_structures/queue/queue_on_two_stacks.py +++ /dev/null @@ -1,137 +0,0 @@ -"""Queue implementation using two stacks""" - -from collections.abc import Iterable -from typing import Generic, TypeVar - -_T = TypeVar("_T") - - -class QueueByTwoStacks(Generic[_T]): - def __init__(self, iterable: Iterable[_T] | None = None) -> None: - """ - >>> queue1 = QueueByTwoStacks() - >>> str(queue1) - 'Queue([])' - >>> queue2 = QueueByTwoStacks([10, 20, 30]) - >>> str(queue2) - 'Queue([10, 20, 30])' - >>> queue3 = QueueByTwoStacks((i**2 for i in range(1, 4))) - >>> str(queue3) - 'Queue([1, 4, 9])' - """ - - self._stack1: list[_T] = [] if iterable is None else list(iterable) - self._stack2: list[_T] = [] - - def __len__(self) -> int: - """ - >>> queue = QueueByTwoStacks() - >>> for i in range(1, 11): - ... queue.put(i) - ... - >>> len(queue) == 10 - True - >>> for i in range(2): - ... queue.get() - 1 - 2 - >>> len(queue) == 8 - True - """ - - return len(self._stack1) + len(self._stack2) - - def __repr__(self) -> str: - """ - >>> queue = QueueByTwoStacks() - >>> queue - Queue([]) - >>> str(queue) - 'Queue([])' - >>> queue.put(10) - >>> queue - Queue([10]) - >>> queue.put(20) - >>> queue.put(30) - >>> queue - Queue([10, 20, 30]) - """ - - items = self._stack2[::-1] + self._stack1 - return f"Queue({items})" - - def put(self, item: _T) -> None: - """ - Put `item` into the Queue - - >>> queue = QueueByTwoStacks() - >>> queue.put(10) - >>> queue.put(20) - >>> len(queue) == 2 - True - >>> str(queue) - 'Queue([10, 20])' - """ - - self._stack1.append(item) - - def get(self) -> _T: - """ - Get `item` from the Queue - - >>> queue = QueueByTwoStacks() - >>> for i in (10, 20, 30): - ... queue.put(i) - >>> queue.get() - 10 - >>> queue.put(40) - >>> queue.get() - 20 - >>> queue.get() - 30 - >>> len(queue) == 1 - True - >>> queue.get() - 40 - >>> queue.get() - Traceback (most recent call last): - ... - IndexError: Queue is empty - """ - - # To reduce number of attribute look-ups in `while` loop. - stack1_pop = self._stack1.pop - stack2_append = self._stack2.append - - if not self._stack2: - while self._stack1: - stack2_append(stack1_pop()) - - if not self._stack2: - raise IndexError("Queue is empty") - return self._stack2.pop() - - def size(self) -> int: - """ - Returns the length of the Queue - - >>> queue = QueueByTwoStacks() - >>> queue.size() - 0 - >>> queue.put(10) - >>> queue.put(20) - >>> queue.size() - 2 - >>> queue.get() - 10 - >>> queue.size() == 1 - True - """ - - return len(self) - - -if __name__ == "__main__": - from doctest import testmod - - testmod() From 14bdd174bba7828ac2bf476f3697aa13fa179492 Mon Sep 17 00:00:00 2001 From: isidroas Date: Sat, 8 Apr 2023 19:39:24 +0200 Subject: [PATCH 629/726] Bloom Filter (#8615) * Bloom filter with tests * has functions constant * fix type * isort * passing ruff * type hints * type hints * from fail to erro * captital leter * type hints requested by boot * descriptive name for m * more descriptibe arguments II * moved movies_test to doctest * commented doctest * removed test_probability * estimated error * added types * again hash_ * Update data_structures/hashing/bloom_filter.py Co-authored-by: Christian Clauss * from b to bloom * Update data_structures/hashing/bloom_filter.py Co-authored-by: Christian Clauss * Update data_structures/hashing/bloom_filter.py Co-authored-by: Christian Clauss * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * syntax error in dict comprehension * from goodfather to godfather * removed Interestellar * forgot the last Godfather * Revert "removed Interestellar" This reverts commit 35fa5f5c4bf101d073aad43c37b0a423d8975071. * pretty dict * Apply suggestions from code review * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update bloom_filter.py --------- Co-authored-by: Christian Clauss Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- data_structures/hashing/bloom_filter.py | 105 ++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 data_structures/hashing/bloom_filter.py diff --git a/data_structures/hashing/bloom_filter.py b/data_structures/hashing/bloom_filter.py new file mode 100644 index 000000000..7fd0985bd --- /dev/null +++ b/data_structures/hashing/bloom_filter.py @@ -0,0 +1,105 @@ +""" +See https://en.wikipedia.org/wiki/Bloom_filter + +The use of this data structure is to test membership in a set. +Compared to Python's built-in set() it is more space-efficient. +In the following example, only 8 bits of memory will be used: +>>> bloom = Bloom(size=8) + +Initially, the filter contains all zeros: +>>> bloom.bitstring +'00000000' + +When an element is added, two bits are set to 1 +since there are 2 hash functions in this implementation: +>>> "Titanic" in bloom +False +>>> bloom.add("Titanic") +>>> bloom.bitstring +'01100000' +>>> "Titanic" in bloom +True + +However, sometimes only one bit is added +because both hash functions return the same value +>>> bloom.add("Avatar") +>>> "Avatar" in bloom +True +>>> bloom.format_hash("Avatar") +'00000100' +>>> bloom.bitstring +'01100100' + +Not added elements should return False ... +>>> not_present_films = ("The Godfather", "Interstellar", "Parasite", "Pulp Fiction") +>>> { +... film: bloom.format_hash(film) for film in not_present_films +... } # doctest: +NORMALIZE_WHITESPACE +{'The Godfather': '00000101', + 'Interstellar': '00000011', + 'Parasite': '00010010', + 'Pulp Fiction': '10000100'} +>>> any(film in bloom for film in not_present_films) +False + +but sometimes there are false positives: +>>> "Ratatouille" in bloom +True +>>> bloom.format_hash("Ratatouille") +'01100000' + +The probability increases with the number of elements added. +The probability decreases with the number of bits in the bitarray. +>>> bloom.estimated_error_rate +0.140625 +>>> bloom.add("The Godfather") +>>> bloom.estimated_error_rate +0.25 +>>> bloom.bitstring +'01100101' +""" +from hashlib import md5, sha256 + +HASH_FUNCTIONS = (sha256, md5) + + +class Bloom: + def __init__(self, size: int = 8) -> None: + self.bitarray = 0b0 + self.size = size + + def add(self, value: str) -> None: + h = self.hash_(value) + self.bitarray |= h + + def exists(self, value: str) -> bool: + h = self.hash_(value) + return (h & self.bitarray) == h + + def __contains__(self, other: str) -> bool: + return self.exists(other) + + def format_bin(self, bitarray: int) -> str: + res = bin(bitarray)[2:] + return res.zfill(self.size) + + @property + def bitstring(self) -> str: + return self.format_bin(self.bitarray) + + def hash_(self, value: str) -> int: + res = 0b0 + for func in HASH_FUNCTIONS: + position = ( + int.from_bytes(func(value.encode()).digest(), "little") % self.size + ) + res |= 2**position + return res + + def format_hash(self, value: str) -> str: + return self.format_bin(self.hash_(value)) + + @property + def estimated_error_rate(self) -> float: + n_ones = bin(self.bitarray).count("1") + return (n_ones / self.size) ** len(HASH_FUNCTIONS) From d182f95646aa7c515afe0912a34e8c2a11a34ca3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 10 Apr 2023 23:43:17 +0200 Subject: [PATCH 630/726] [pre-commit.ci] pre-commit autoupdate (#8634) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/charliermarsh/ruff-pre-commit: v0.0.260 → v0.0.261](https://github.com/charliermarsh/ruff-pre-commit/compare/v0.0.260...v0.0.261) - [github.com/pre-commit/mirrors-mypy: v1.1.1 → v1.2.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.1.1...v1.2.0) * updating DIRECTORY.md --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- DIRECTORY.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d54ce5add..55345a574 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.260 + rev: v0.0.261 hooks: - id: ruff @@ -51,7 +51,7 @@ repos: - id: validate-pyproject - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.1.1 + rev: v1.2.0 hooks: - id: mypy args: diff --git a/DIRECTORY.md b/DIRECTORY.md index e3e0748ec..36f5a752c 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -195,6 +195,7 @@ * [Alternate Disjoint Set](data_structures/disjoint_set/alternate_disjoint_set.py) * [Disjoint Set](data_structures/disjoint_set/disjoint_set.py) * Hashing + * [Bloom Filter](data_structures/hashing/bloom_filter.py) * [Double Hash](data_structures/hashing/double_hash.py) * [Hash Map](data_structures/hashing/hash_map.py) * [Hash Table](data_structures/hashing/hash_table.py) From 54dedf844a30d39bd42c66ebf9cd67ec186f47bb Mon Sep 17 00:00:00 2001 From: Diego Gasco <62801631+Diegomangasco@users.noreply.github.com> Date: Mon, 17 Apr 2023 00:34:22 +0200 Subject: [PATCH 631/726] Dimensionality reduction (#8590) --- machine_learning/dimensionality_reduction.py | 198 +++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 machine_learning/dimensionality_reduction.py diff --git a/machine_learning/dimensionality_reduction.py b/machine_learning/dimensionality_reduction.py new file mode 100644 index 000000000..d2046f81a --- /dev/null +++ b/machine_learning/dimensionality_reduction.py @@ -0,0 +1,198 @@ +# Copyright (c) 2023 Diego Gasco (diego.gasco99@gmail.com), Diegomangasco on GitHub + +""" +Requirements: + - numpy version 1.21 + - scipy version 1.3.3 +Notes: + - Each column of the features matrix corresponds to a class item +""" + +import logging + +import numpy as np +import pytest +from scipy.linalg import eigh + +logging.basicConfig(level=logging.INFO, format="%(message)s") + + +def column_reshape(input_array: np.ndarray) -> np.ndarray: + """Function to reshape a row Numpy array into a column Numpy array + >>> input_array = np.array([1, 2, 3]) + >>> column_reshape(input_array) + array([[1], + [2], + [3]]) + """ + + return input_array.reshape((input_array.size, 1)) + + +def covariance_within_classes( + features: np.ndarray, labels: np.ndarray, classes: int +) -> np.ndarray: + """Function to compute the covariance matrix inside each class. + >>> features = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + >>> labels = np.array([0, 1, 0]) + >>> covariance_within_classes(features, labels, 2) + array([[0.66666667, 0.66666667, 0.66666667], + [0.66666667, 0.66666667, 0.66666667], + [0.66666667, 0.66666667, 0.66666667]]) + """ + + covariance_sum = np.nan + for i in range(classes): + data = features[:, labels == i] + data_mean = data.mean(1) + # Centralize the data of class i + centered_data = data - column_reshape(data_mean) + if i > 0: + # If covariance_sum is not None + covariance_sum += np.dot(centered_data, centered_data.T) + else: + # If covariance_sum is np.nan (i.e. first loop) + covariance_sum = np.dot(centered_data, centered_data.T) + + return covariance_sum / features.shape[1] + + +def covariance_between_classes( + features: np.ndarray, labels: np.ndarray, classes: int +) -> np.ndarray: + """Function to compute the covariance matrix between multiple classes + >>> features = np.array([[9, 2, 3], [4, 3, 6], [1, 8, 9]]) + >>> labels = np.array([0, 1, 0]) + >>> covariance_between_classes(features, labels, 2) + array([[ 3.55555556, 1.77777778, -2.66666667], + [ 1.77777778, 0.88888889, -1.33333333], + [-2.66666667, -1.33333333, 2. ]]) + """ + + general_data_mean = features.mean(1) + covariance_sum = np.nan + for i in range(classes): + data = features[:, labels == i] + device_data = data.shape[1] + data_mean = data.mean(1) + if i > 0: + # If covariance_sum is not None + covariance_sum += device_data * np.dot( + column_reshape(data_mean) - column_reshape(general_data_mean), + (column_reshape(data_mean) - column_reshape(general_data_mean)).T, + ) + else: + # If covariance_sum is np.nan (i.e. first loop) + covariance_sum = device_data * np.dot( + column_reshape(data_mean) - column_reshape(general_data_mean), + (column_reshape(data_mean) - column_reshape(general_data_mean)).T, + ) + + return covariance_sum / features.shape[1] + + +def principal_component_analysis(features: np.ndarray, dimensions: int) -> np.ndarray: + """ + Principal Component Analysis. + + For more details, see: https://en.wikipedia.org/wiki/Principal_component_analysis. + Parameters: + * features: the features extracted from the dataset + * dimensions: to filter the projected data for the desired dimension + + >>> test_principal_component_analysis() + """ + + # Check if the features have been loaded + if features.any(): + data_mean = features.mean(1) + # Center the dataset + centered_data = features - np.reshape(data_mean, (data_mean.size, 1)) + covariance_matrix = np.dot(centered_data, centered_data.T) / features.shape[1] + _, eigenvectors = np.linalg.eigh(covariance_matrix) + # Take all the columns in the reverse order (-1), and then takes only the first + filtered_eigenvectors = eigenvectors[:, ::-1][:, 0:dimensions] + # Project the database on the new space + projected_data = np.dot(filtered_eigenvectors.T, features) + logging.info("Principal Component Analysis computed") + + return projected_data + else: + logging.basicConfig(level=logging.ERROR, format="%(message)s", force=True) + logging.error("Dataset empty") + raise AssertionError + + +def linear_discriminant_analysis( + features: np.ndarray, labels: np.ndarray, classes: int, dimensions: int +) -> np.ndarray: + """ + Linear Discriminant Analysis. + + For more details, see: https://en.wikipedia.org/wiki/Linear_discriminant_analysis. + Parameters: + * features: the features extracted from the dataset + * labels: the class labels of the features + * classes: the number of classes present in the dataset + * dimensions: to filter the projected data for the desired dimension + + >>> test_linear_discriminant_analysis() + """ + + # Check if the dimension desired is less than the number of classes + assert classes > dimensions + + # Check if features have been already loaded + if features.any: + _, eigenvectors = eigh( + covariance_between_classes(features, labels, classes), + covariance_within_classes(features, labels, classes), + ) + filtered_eigenvectors = eigenvectors[:, ::-1][:, :dimensions] + svd_matrix, _, _ = np.linalg.svd(filtered_eigenvectors) + filtered_svd_matrix = svd_matrix[:, 0:dimensions] + projected_data = np.dot(filtered_svd_matrix.T, features) + logging.info("Linear Discriminant Analysis computed") + + return projected_data + else: + logging.basicConfig(level=logging.ERROR, format="%(message)s", force=True) + logging.error("Dataset empty") + raise AssertionError + + +def test_linear_discriminant_analysis() -> None: + # Create dummy dataset with 2 classes and 3 features + features = np.array([[1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [3, 4, 5, 6, 7]]) + labels = np.array([0, 0, 0, 1, 1]) + classes = 2 + dimensions = 2 + + # Assert that the function raises an AssertionError if dimensions > classes + with pytest.raises(AssertionError) as error_info: + projected_data = linear_discriminant_analysis( + features, labels, classes, dimensions + ) + if isinstance(projected_data, np.ndarray): + raise AssertionError( + "Did not raise AssertionError for dimensions > classes" + ) + assert error_info.type is AssertionError + + +def test_principal_component_analysis() -> None: + features = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + dimensions = 2 + expected_output = np.array([[6.92820323, 8.66025404, 10.39230485], [3.0, 3.0, 3.0]]) + + with pytest.raises(AssertionError) as error_info: + output = principal_component_analysis(features, dimensions) + if not np.allclose(expected_output, output): + raise AssertionError + assert error_info.type is AssertionError + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 2b051a2de4adf711857f5453286dff47d1d87636 Mon Sep 17 00:00:00 2001 From: Rohan Anand <96521078+rohan472000@users.noreply.github.com> Date: Tue, 18 Apr 2023 03:47:48 +0530 Subject: [PATCH 632/726] Create real_and_reactive_power.py (#8665) --- electronics/real_and_reactive_power.py | 49 ++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 electronics/real_and_reactive_power.py diff --git a/electronics/real_and_reactive_power.py b/electronics/real_and_reactive_power.py new file mode 100644 index 000000000..81dcba800 --- /dev/null +++ b/electronics/real_and_reactive_power.py @@ -0,0 +1,49 @@ +import math + + +def real_power(apparent_power: float, power_factor: float) -> float: + """ + Calculate real power from apparent power and power factor. + + Examples: + >>> real_power(100, 0.9) + 90.0 + >>> real_power(0, 0.8) + 0.0 + >>> real_power(100, -0.9) + -90.0 + """ + if ( + not isinstance(power_factor, (int, float)) + or power_factor < -1 + or power_factor > 1 + ): + raise ValueError("power_factor must be a valid float value between -1 and 1.") + return apparent_power * power_factor + + +def reactive_power(apparent_power: float, power_factor: float) -> float: + """ + Calculate reactive power from apparent power and power factor. + + Examples: + >>> reactive_power(100, 0.9) + 43.58898943540673 + >>> reactive_power(0, 0.8) + 0.0 + >>> reactive_power(100, -0.9) + 43.58898943540673 + """ + if ( + not isinstance(power_factor, (int, float)) + or power_factor < -1 + or power_factor > 1 + ): + raise ValueError("power_factor must be a valid float value between -1 and 1.") + return apparent_power * math.sqrt(1 - power_factor**2) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From b5047cfa114c6343b92370419772b9cf0f13e634 Mon Sep 17 00:00:00 2001 From: Rohan Anand <96521078+rohan472000@users.noreply.github.com> Date: Tue, 18 Apr 2023 13:00:01 +0530 Subject: [PATCH 633/726] Create apparent_power.py (#8664) * Create apparent_power.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update apparent_power.py * Update apparent_power.py * Update apparent_power.py * Update electronics/apparent_power.py Co-authored-by: Christian Clauss * Update electronics/apparent_power.py Co-authored-by: Christian Clauss * Update apparent_power.py * Update electronics/apparent_power.py Co-authored-by: Christian Clauss * Update apparent_power.py * Update apparent_power.py * Update apparent_power.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update apparent_power.py * Update apparent_power.py * Update apparent_power.py --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- electronics/apparent_power.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 electronics/apparent_power.py diff --git a/electronics/apparent_power.py b/electronics/apparent_power.py new file mode 100644 index 000000000..a6f1a5082 --- /dev/null +++ b/electronics/apparent_power.py @@ -0,0 +1,35 @@ +import cmath +import math + + +def apparent_power( + voltage: float, current: float, voltage_angle: float, current_angle: float +) -> complex: + """ + Calculate the apparent power in a single-phase AC circuit. + + >>> apparent_power(100, 5, 0, 0) + (500+0j) + >>> apparent_power(100, 5, 90, 0) + (3.061616997868383e-14+500j) + >>> apparent_power(100, 5, -45, -60) + (-129.40952255126027-482.9629131445341j) + >>> apparent_power(200, 10, -30, -90) + (-999.9999999999998-1732.0508075688776j) + """ + # Convert angles from degrees to radians + voltage_angle_rad = math.radians(voltage_angle) + current_angle_rad = math.radians(current_angle) + + # Convert voltage and current to rectangular form + voltage_rect = cmath.rect(voltage, voltage_angle_rad) + current_rect = cmath.rect(current, current_angle_rad) + + # Calculate apparent power + return voltage_rect * current_rect + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 93ce8cb75da2740089df8db23fa493ce104a011b Mon Sep 17 00:00:00 2001 From: Rohan Anand <96521078+rohan472000@users.noreply.github.com> Date: Tue, 18 Apr 2023 13:14:06 +0530 Subject: [PATCH 634/726] added reference link. (#8667) * added reference link. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- electronics/apparent_power.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/electronics/apparent_power.py b/electronics/apparent_power.py index a6f1a5082..0ce1c2aa9 100644 --- a/electronics/apparent_power.py +++ b/electronics/apparent_power.py @@ -8,6 +8,8 @@ def apparent_power( """ Calculate the apparent power in a single-phase AC circuit. + Reference: https://en.wikipedia.org/wiki/AC_power#Apparent_power + >>> apparent_power(100, 5, 0, 0) (500+0j) >>> apparent_power(100, 5, 90, 0) From 458debc237d41752c6c4223264a4bb23efb2ecec Mon Sep 17 00:00:00 2001 From: Rohan Anand <96521078+rohan472000@users.noreply.github.com> Date: Tue, 18 Apr 2023 13:32:20 +0530 Subject: [PATCH 635/726] added a problem with solution on sliding window. (#8566) * added a problem with solution on sliding window. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * added hint for return type and parameter * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update minimum_size_subarray_sum.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update minimum_size_subarray_sum.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update minimum_size_subarray_sum.py * Update minimum_size_subarray_sum.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update minimum_size_subarray_sum.py * removed un-necessary docs and added 2 test cases * Rename sliding_window/minimum_size_subarray_sum.py to dynamic_programming/minimum_size_subarray_sum.py * Update minimum_size_subarray_sum.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update minimum_size_subarray_sum.py * Update minimum_size_subarray_sum.py * Update minimum_size_subarray_sum.py * Update minimum_size_subarray_sum.py * Update minimum_size_subarray_sum.py * Update minimum_size_subarray_sum.py * Update dynamic_programming/minimum_size_subarray_sum.py Co-authored-by: Christian Clauss * Update dynamic_programming/minimum_size_subarray_sum.py Co-authored-by: Christian Clauss * Update dynamic_programming/minimum_size_subarray_sum.py Co-authored-by: Christian Clauss * Update dynamic_programming/minimum_size_subarray_sum.py Co-authored-by: Christian Clauss * Update dynamic_programming/minimum_size_subarray_sum.py Co-authored-by: Christian Clauss * Update dynamic_programming/minimum_size_subarray_sum.py Co-authored-by: Christian Clauss * Update dynamic_programming/minimum_size_subarray_sum.py Co-authored-by: Christian Clauss * Update minimum_size_subarray_sum.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update minimum_size_subarray_sum.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update minimum_size_subarray_sum.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update minimum_size_subarray_sum.py * Update minimum_size_subarray_sum.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .../minimum_size_subarray_sum.py | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 dynamic_programming/minimum_size_subarray_sum.py diff --git a/dynamic_programming/minimum_size_subarray_sum.py b/dynamic_programming/minimum_size_subarray_sum.py new file mode 100644 index 000000000..3868d7353 --- /dev/null +++ b/dynamic_programming/minimum_size_subarray_sum.py @@ -0,0 +1,62 @@ +import sys + + +def minimum_subarray_sum(target: int, numbers: list[int]) -> int: + """ + Return the length of the shortest contiguous subarray in a list of numbers whose sum + is at least target. Reference: https://stackoverflow.com/questions/8269916 + + >>> minimum_subarray_sum(7, [2, 3, 1, 2, 4, 3]) + 2 + >>> minimum_subarray_sum(7, [2, 3, -1, 2, 4, -3]) + 4 + >>> minimum_subarray_sum(11, [1, 1, 1, 1, 1, 1, 1, 1]) + 0 + >>> minimum_subarray_sum(10, [1, 2, 3, 4, 5, 6, 7]) + 2 + >>> minimum_subarray_sum(5, [1, 1, 1, 1, 1, 5]) + 1 + >>> minimum_subarray_sum(0, []) + 0 + >>> minimum_subarray_sum(0, [1, 2, 3]) + 1 + >>> minimum_subarray_sum(10, [10, 20, 30]) + 1 + >>> minimum_subarray_sum(7, [1, 1, 1, 1, 1, 1, 10]) + 1 + >>> minimum_subarray_sum(6, []) + 0 + >>> minimum_subarray_sum(2, [1, 2, 3]) + 1 + >>> minimum_subarray_sum(-6, []) + 0 + >>> minimum_subarray_sum(-6, [3, 4, 5]) + 1 + >>> minimum_subarray_sum(8, None) + 0 + >>> minimum_subarray_sum(2, "ABC") + Traceback (most recent call last): + ... + ValueError: numbers must be an iterable of integers + """ + if not numbers: + return 0 + if target == 0 and target in numbers: + return 0 + if not isinstance(numbers, (list, tuple)) or not all( + isinstance(number, int) for number in numbers + ): + raise ValueError("numbers must be an iterable of integers") + + left = right = curr_sum = 0 + min_len = sys.maxsize + + while right < len(numbers): + curr_sum += numbers[right] + while curr_sum >= target and left <= right: + min_len = min(min_len, right - left + 1) + curr_sum -= numbers[left] + left += 1 + right += 1 + + return 0 if min_len == sys.maxsize else min_len From 11582943a555ae3b6a22938df6d3645b0327562e Mon Sep 17 00:00:00 2001 From: JulianStiebler <68881884+JulianStiebler@users.noreply.github.com> Date: Tue, 18 Apr 2023 11:57:48 +0200 Subject: [PATCH 636/726] Create maths/pi_generator.py (#8666) * Create pi_generator.py * Update pi_generator.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update pi_generator.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update pi_generator.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update pi_generator.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update pi_generator.py * Update pi_generator.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Updated commentary on line 28, added math.pi comparison & math.isclose() test * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Removed # noqa: E501 * printf() added as recommended by cclaus --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- maths/pi_generator.py | 94 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 maths/pi_generator.py diff --git a/maths/pi_generator.py b/maths/pi_generator.py new file mode 100644 index 000000000..dcd218aae --- /dev/null +++ b/maths/pi_generator.py @@ -0,0 +1,94 @@ +def calculate_pi(limit: int) -> str: + """ + https://en.wikipedia.org/wiki/Leibniz_formula_for_%CF%80 + Leibniz Formula for Pi + + The Leibniz formula is the special case arctan 1 = 1/4 Pi . + Leibniz's formula converges extremely slowly: it exhibits sublinear convergence. + + Convergence (https://en.wikipedia.org/wiki/Leibniz_formula_for_%CF%80#Convergence) + + We cannot try to prove against an interrupted, uncompleted generation. + https://en.wikipedia.org/wiki/Leibniz_formula_for_%CF%80#Unusual_behaviour + The errors can in fact be predicted; + but those calculations also approach infinity for accuracy. + + Our output will always be a string since we can defintely store all digits in there. + For simplicity' sake, let's just compare against known values and since our outpit + is a string, we need to convert to float. + + >>> import math + >>> float(calculate_pi(15)) == math.pi + True + + Since we cannot predict errors or interrupt any infinite alternating + series generation since they approach infinity, + or interrupt any alternating series, we are going to need math.isclose() + + >>> math.isclose(float(calculate_pi(50)), math.pi) + True + + >>> math.isclose(float(calculate_pi(100)), math.pi) + True + + Since math.pi-constant contains only 16 digits, here some test with preknown values: + + >>> calculate_pi(50) + '3.14159265358979323846264338327950288419716939937510' + >>> calculate_pi(80) + '3.14159265358979323846264338327950288419716939937510582097494459230781640628620899' + + To apply the Leibniz formula for calculating pi, + the variables q, r, t, k, n, and l are used for the iteration process. + """ + q = 1 + r = 0 + t = 1 + k = 1 + n = 3 + l = 3 + decimal = limit + counter = 0 + + result = "" + + """ + We will avoid using yield since we otherwise get a Generator-Object, + which we can't just compare against anything. We would have to make a list out of it + after the generation, so we will just stick to plain return logic: + """ + while counter != decimal + 1: + if 4 * q + r - t < n * t: + result += str(n) + if counter == 0: + result += "." + + if decimal == counter: + break + + counter += 1 + nr = 10 * (r - n * t) + n = ((10 * (3 * q + r)) // t) - 10 * n + q *= 10 + r = nr + else: + nr = (2 * q + r) * l + nn = (q * (7 * k) + 2 + (r * l)) // (t * l) + q *= k + t *= l + l += 2 + k += 1 + n = nn + r = nr + return result + + +def main() -> None: + print(f"{calculate_pi(50) = }") + import doctest + + doctest.testmod() + + +if __name__ == "__main__": + main() From bf30b18192dd7ff9a43523ee6efe5c015ae6b99c Mon Sep 17 00:00:00 2001 From: Rohan Anand <96521078+rohan472000@users.noreply.github.com> Date: Mon, 24 Apr 2023 10:58:30 +0530 Subject: [PATCH 637/726] Update linear_discriminant_analysis.py and rsa_cipher.py (#8680) * Update rsa_cipher.py by replacing %s with {} * Update rsa_cipher.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update linear_discriminant_analysis.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update linear_discriminant_analysis.py * Update linear_discriminant_analysis.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update linear_discriminant_analysis.py * Update linear_discriminant_analysis.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update linear_discriminant_analysis.py * Update machine_learning/linear_discriminant_analysis.py Co-authored-by: Christian Clauss * Update linear_discriminant_analysis.py * updated --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- ciphers/rsa_cipher.py | 14 ++++++++------ machine_learning/linear_discriminant_analysis.py | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/ciphers/rsa_cipher.py b/ciphers/rsa_cipher.py index de26992f5..9c41cdc5d 100644 --- a/ciphers/rsa_cipher.py +++ b/ciphers/rsa_cipher.py @@ -76,10 +76,11 @@ def encrypt_and_write_to_file( key_size, n, e = read_key_file(key_filename) if key_size < block_size * 8: sys.exit( - "ERROR: Block size is %s bits and key size is %s bits. The RSA cipher " + "ERROR: Block size is {} bits and key size is {} bits. The RSA cipher " "requires the block size to be equal to or greater than the key size. " - "Either decrease the block size or use different keys." - % (block_size * 8, key_size) + "Either decrease the block size or use different keys.".format( + block_size * 8, key_size + ) ) encrypted_blocks = [str(i) for i in encrypt_message(message, (n, e), block_size)] @@ -101,10 +102,11 @@ def read_from_file_and_decrypt(message_filename: str, key_filename: str) -> str: if key_size < block_size * 8: sys.exit( - "ERROR: Block size is %s bits and key size is %s bits. The RSA cipher " + "ERROR: Block size is {} bits and key size is {} bits. The RSA cipher " "requires the block size to be equal to or greater than the key size. " - "Did you specify the correct key file and encrypted file?" - % (block_size * 8, key_size) + "Did you specify the correct key file and encrypted file?".format( + block_size * 8, key_size + ) ) encrypted_blocks = [] diff --git a/machine_learning/linear_discriminant_analysis.py b/machine_learning/linear_discriminant_analysis.py index f4fb5ba76..c0a477be1 100644 --- a/machine_learning/linear_discriminant_analysis.py +++ b/machine_learning/linear_discriminant_analysis.py @@ -399,7 +399,7 @@ def main(): if input("Press any key to restart or 'q' for quit: ").strip().lower() == "q": print("\n" + "GoodBye!".center(100, "-") + "\n") break - system("cls" if name == "nt" else "clear") + system("clear" if name == "posix" else "cls") # noqa: S605 if __name__ == "__main__": From a650426350dc7833ff1110bc2e434763caed631e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 25 Apr 2023 06:05:45 +0200 Subject: [PATCH 638/726] [pre-commit.ci] pre-commit autoupdate (#8691) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/charliermarsh/ruff-pre-commit: v0.0.261 → v0.0.262](https://github.com/charliermarsh/ruff-pre-commit/compare/v0.0.261...v0.0.262) - [github.com/tox-dev/pyproject-fmt: 0.9.2 → 0.10.0](https://github.com/tox-dev/pyproject-fmt/compare/0.9.2...0.10.0) * updating DIRECTORY.md --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- DIRECTORY.md | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 55345a574..288473ca3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.261 + rev: v0.0.262 hooks: - id: ruff @@ -33,7 +33,7 @@ repos: - tomli - repo: https://github.com/tox-dev/pyproject-fmt - rev: "0.9.2" + rev: "0.10.0" hooks: - id: pyproject-fmt diff --git a/DIRECTORY.md b/DIRECTORY.md index 36f5a752c..8e67c85c6 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -327,6 +327,7 @@ * [Minimum Coin Change](dynamic_programming/minimum_coin_change.py) * [Minimum Cost Path](dynamic_programming/minimum_cost_path.py) * [Minimum Partition](dynamic_programming/minimum_partition.py) + * [Minimum Size Subarray Sum](dynamic_programming/minimum_size_subarray_sum.py) * [Minimum Squares To Represent A Number](dynamic_programming/minimum_squares_to_represent_a_number.py) * [Minimum Steps To One](dynamic_programming/minimum_steps_to_one.py) * [Minimum Tickets Cost](dynamic_programming/minimum_tickets_cost.py) @@ -339,6 +340,7 @@ * [Word Break](dynamic_programming/word_break.py) ## Electronics + * [Apparent Power](electronics/apparent_power.py) * [Builtin Voltage](electronics/builtin_voltage.py) * [Carrier Concentration](electronics/carrier_concentration.py) * [Circular Convolution](electronics/circular_convolution.py) @@ -348,6 +350,7 @@ * [Electrical Impedance](electronics/electrical_impedance.py) * [Ind Reactance](electronics/ind_reactance.py) * [Ohms Law](electronics/ohms_law.py) + * [Real And Reactive Power](electronics/real_and_reactive_power.py) * [Resistor Equivalence](electronics/resistor_equivalence.py) * [Resonant Frequency](electronics/resonant_frequency.py) @@ -483,6 +486,7 @@ * [Astar](machine_learning/astar.py) * [Data Transformations](machine_learning/data_transformations.py) * [Decision Tree](machine_learning/decision_tree.py) + * [Dimensionality Reduction](machine_learning/dimensionality_reduction.py) * Forecasting * [Run](machine_learning/forecasting/run.py) * [Gradient Descent](machine_learning/gradient_descent.py) @@ -604,6 +608,7 @@ * [Perfect Number](maths/perfect_number.py) * [Perfect Square](maths/perfect_square.py) * [Persistence](maths/persistence.py) + * [Pi Generator](maths/pi_generator.py) * [Pi Monte Carlo Estimation](maths/pi_monte_carlo_estimation.py) * [Points Are Collinear 3D](maths/points_are_collinear_3d.py) * [Pollard Rho](maths/pollard_rho.py) From c1b3ea5355266bb47daba378ca10200c4d359453 Mon Sep 17 00:00:00 2001 From: Dipankar Mitra <50228537+Mitra-babu@users.noreply.github.com> Date: Tue, 25 Apr 2023 21:36:14 +0530 Subject: [PATCH 639/726] The tanh activation function is added (#8689) * tanh function been added * tanh function been added * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * tanh function is added * tanh function is added * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * tanh function added * tanh function added * tanh function is added * Apply suggestions from code review --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- maths/tanh.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 maths/tanh.py diff --git a/maths/tanh.py b/maths/tanh.py new file mode 100644 index 000000000..ddab3e1ab --- /dev/null +++ b/maths/tanh.py @@ -0,0 +1,42 @@ +""" +This script demonstrates the implementation of the tangent hyperbolic +or tanh function. + +The function takes a vector of K real numbers as input and +then (e^x - e^(-x))/(e^x + e^(-x)). After through tanh, the +element of the vector mostly -1 between 1. + +Script inspired from its corresponding Wikipedia article +https://en.wikipedia.org/wiki/Activation_function +""" +import numpy as np + + +def tangent_hyperbolic(vector: np.array) -> np.array: + """ + Implements the tanh function + + Parameters: + vector: np.array + + Returns: + tanh (np.array): The input numpy array after applying tanh. + + mathematically (e^x - e^(-x))/(e^x + e^(-x)) can be written as (2/(1+e^(-2x))-1 + + Examples: + >>> tangent_hyperbolic(np.array([1,5,6,-0.67])) + array([ 0.76159416, 0.9999092 , 0.99998771, -0.58497988]) + + >>> tangent_hyperbolic(np.array([8,10,2,-0.98,13])) + array([ 0.99999977, 1. , 0.96402758, -0.7530659 , 1. ]) + + """ + + return (2 / (1 + np.exp(-2 * vector))) - 1 + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 4c1f876567673db0934ba65d662ea221465ec921 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 27 Apr 2023 19:32:07 +0200 Subject: [PATCH 640/726] Solving the `Top k most frequent words` problem using a max-heap (#8685) * Solving the `Top k most frequent words` problem using a max-heap * Mentioning Python standard library solution in `Top k most frequent words` docstring * ruff --fix . * updating DIRECTORY.md --------- Co-authored-by: Amos Paribocci Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 1 + data_structures/heap/heap.py | 31 ++++-- .../linear_discriminant_analysis.py | 2 +- strings/top_k_frequent_words.py | 101 ++++++++++++++++++ 4 files changed, 128 insertions(+), 7 deletions(-) create mode 100644 strings/top_k_frequent_words.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 8e67c85c6..681d252b2 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -1167,6 +1167,7 @@ * [Snake Case To Camel Pascal Case](strings/snake_case_to_camel_pascal_case.py) * [Split](strings/split.py) * [Text Justification](strings/text_justification.py) + * [Top K Frequent Words](strings/top_k_frequent_words.py) * [Upper](strings/upper.py) * [Wave](strings/wave.py) * [Wildcard Pattern Matching](strings/wildcard_pattern_matching.py) diff --git a/data_structures/heap/heap.py b/data_structures/heap/heap.py index b14c55d9d..c1004f349 100644 --- a/data_structures/heap/heap.py +++ b/data_structures/heap/heap.py @@ -1,9 +1,28 @@ from __future__ import annotations +from abc import abstractmethod from collections.abc import Iterable +from typing import Generic, Protocol, TypeVar -class Heap: +class Comparable(Protocol): + @abstractmethod + def __lt__(self: T, other: T) -> bool: + pass + + @abstractmethod + def __gt__(self: T, other: T) -> bool: + pass + + @abstractmethod + def __eq__(self: T, other: object) -> bool: + pass + + +T = TypeVar("T", bound=Comparable) + + +class Heap(Generic[T]): """A Max Heap Implementation >>> unsorted = [103, 9, 1, 7, 11, 15, 25, 201, 209, 107, 5] @@ -27,7 +46,7 @@ class Heap: """ def __init__(self) -> None: - self.h: list[float] = [] + self.h: list[T] = [] self.heap_size: int = 0 def __repr__(self) -> str: @@ -79,7 +98,7 @@ class Heap: # fix the subsequent violation recursively if any self.max_heapify(violation) - def build_max_heap(self, collection: Iterable[float]) -> None: + def build_max_heap(self, collection: Iterable[T]) -> None: """build max heap from an unsorted array""" self.h = list(collection) self.heap_size = len(self.h) @@ -88,7 +107,7 @@ class Heap: for i in range(self.heap_size // 2 - 1, -1, -1): self.max_heapify(i) - def extract_max(self) -> float: + def extract_max(self) -> T: """get and remove max from heap""" if self.heap_size >= 2: me = self.h[0] @@ -102,7 +121,7 @@ class Heap: else: raise Exception("Empty heap") - def insert(self, value: float) -> None: + def insert(self, value: T) -> None: """insert a new value into the max heap""" self.h.append(value) idx = (self.heap_size - 1) // 2 @@ -144,7 +163,7 @@ if __name__ == "__main__": ]: print(f"unsorted array: {unsorted}") - heap = Heap() + heap: Heap[int] = Heap() heap.build_max_heap(unsorted) print(f"after build heap: {heap}") diff --git a/machine_learning/linear_discriminant_analysis.py b/machine_learning/linear_discriminant_analysis.py index c0a477be1..88c047157 100644 --- a/machine_learning/linear_discriminant_analysis.py +++ b/machine_learning/linear_discriminant_analysis.py @@ -399,7 +399,7 @@ def main(): if input("Press any key to restart or 'q' for quit: ").strip().lower() == "q": print("\n" + "GoodBye!".center(100, "-") + "\n") break - system("clear" if name == "posix" else "cls") # noqa: S605 + system("cls" if name == "nt" else "clear") # noqa: S605 if __name__ == "__main__": diff --git a/strings/top_k_frequent_words.py b/strings/top_k_frequent_words.py new file mode 100644 index 000000000..f3d1e0cd5 --- /dev/null +++ b/strings/top_k_frequent_words.py @@ -0,0 +1,101 @@ +""" +Finds the top K most frequent words from the provided word list. + +This implementation aims to show how to solve the problem using the Heap class +already present in this repository. +Computing order statistics is, in fact, a typical usage of heaps. + +This is mostly shown for educational purposes, since the problem can be solved +in a few lines using collections.Counter from the Python standard library: + +from collections import Counter +def top_k_frequent_words(words, k_value): + return [x[0] for x in Counter(words).most_common(k_value)] +""" + + +from collections import Counter +from functools import total_ordering + +from data_structures.heap.heap import Heap + + +@total_ordering +class WordCount: + def __init__(self, word: str, count: int) -> None: + self.word = word + self.count = count + + def __eq__(self, other: object) -> bool: + """ + >>> WordCount('a', 1).__eq__(WordCount('b', 1)) + True + >>> WordCount('a', 1).__eq__(WordCount('a', 1)) + True + >>> WordCount('a', 1).__eq__(WordCount('a', 2)) + False + >>> WordCount('a', 1).__eq__(WordCount('b', 2)) + False + >>> WordCount('a', 1).__eq__(1) + NotImplemented + """ + if not isinstance(other, WordCount): + return NotImplemented + return self.count == other.count + + def __lt__(self, other: object) -> bool: + """ + >>> WordCount('a', 1).__lt__(WordCount('b', 1)) + False + >>> WordCount('a', 1).__lt__(WordCount('a', 1)) + False + >>> WordCount('a', 1).__lt__(WordCount('a', 2)) + True + >>> WordCount('a', 1).__lt__(WordCount('b', 2)) + True + >>> WordCount('a', 2).__lt__(WordCount('a', 1)) + False + >>> WordCount('a', 2).__lt__(WordCount('b', 1)) + False + >>> WordCount('a', 1).__lt__(1) + NotImplemented + """ + if not isinstance(other, WordCount): + return NotImplemented + return self.count < other.count + + +def top_k_frequent_words(words: list[str], k_value: int) -> list[str]: + """ + Returns the `k_value` most frequently occurring words, + in non-increasing order of occurrence. + In this context, a word is defined as an element in the provided list. + + In case `k_value` is greater than the number of distinct words, a value of k equal + to the number of distinct words will be considered, instead. + + >>> top_k_frequent_words(['a', 'b', 'c', 'a', 'c', 'c'], 3) + ['c', 'a', 'b'] + >>> top_k_frequent_words(['a', 'b', 'c', 'a', 'c', 'c'], 2) + ['c', 'a'] + >>> top_k_frequent_words(['a', 'b', 'c', 'a', 'c', 'c'], 1) + ['c'] + >>> top_k_frequent_words(['a', 'b', 'c', 'a', 'c', 'c'], 0) + [] + >>> top_k_frequent_words([], 1) + [] + >>> top_k_frequent_words(['a', 'a'], 2) + ['a'] + """ + heap: Heap[WordCount] = Heap() + count_by_word = Counter(words) + heap.build_max_heap( + [WordCount(word, count) for word, count in count_by_word.items()] + ) + return [heap.extract_max().word for _ in range(min(k_value, len(count_by_word)))] + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From c4dcc44dd44f7e3e7c65debc8e173080fc693150 Mon Sep 17 00:00:00 2001 From: Sahil Goel <55365655+sahilg13@users.noreply.github.com> Date: Sun, 30 Apr 2023 13:33:22 -0400 Subject: [PATCH 641/726] Added an algorithm to calculate the present value of cash flows (#8700) * Added an algorithm to calculate the present value of cash flows * added doctest and reference * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Resolving deprecation issues with typing module * Fixing argument type checks and adding doctest case * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixing failing doctest case by requiring less precision due to floating point inprecision * Updating return type * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Added test cases for more coverage * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Make improvements based on Rohan's suggestions * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update financial/present_value.py Committed first suggestion Co-authored-by: Christian Clauss * Update financial/present_value.py Committed second suggestion Co-authored-by: Christian Clauss * Update financial/present_value.py Committed third suggestion Co-authored-by: Christian Clauss * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- financial/present_value.py | 41 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 financial/present_value.py diff --git a/financial/present_value.py b/financial/present_value.py new file mode 100644 index 000000000..dc8191a6e --- /dev/null +++ b/financial/present_value.py @@ -0,0 +1,41 @@ +""" +Reference: https://www.investopedia.com/terms/p/presentvalue.asp + +An algorithm that calculates the present value of a stream of yearly cash flows given... +1. The discount rate (as a decimal, not a percent) +2. An array of cash flows, with the index of the cash flow being the associated year + +Note: This algorithm assumes that cash flows are paid at the end of the specified year + + +def present_value(discount_rate: float, cash_flows: list[float]) -> float: + """ + >>> present_value(0.13, [10, 20.70, -293, 297]) + 4.69 + >>> present_value(0.07, [-109129.39, 30923.23, 15098.93, 29734,39]) + -42739.63 + >>> present_value(0.07, [109129.39, 30923.23, 15098.93, 29734,39]) + 175519.15 + >>> present_value(-1, [109129.39, 30923.23, 15098.93, 29734,39]) + Traceback (most recent call last): + ... + ValueError: Discount rate cannot be negative + >>> present_value(0.03, []) + Traceback (most recent call last): + ... + ValueError: Cash flows list cannot be empty + """ + if discount_rate < 0: + raise ValueError("Discount rate cannot be negative") + if not cash_flows: + raise ValueError("Cash flows list cannot be empty") + present_value = sum( + cash_flow / ((1 + discount_rate) ** i) for i, cash_flow in enumerate(cash_flows) + ) + return round(present_value, ndigits=2) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From f6df26bf0f5c05d53b6fd24552de9e3eec2334aa Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 1 May 2023 02:59:42 +0200 Subject: [PATCH 642/726] Fix docstring in present_value.py (#8702) Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 2 ++ financial/present_value.py | 1 + 2 files changed, 3 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 681d252b2..167d062b4 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -363,6 +363,7 @@ ## Financial * [Equated Monthly Installments](financial/equated_monthly_installments.py) * [Interest](financial/interest.py) + * [Present Value](financial/present_value.py) * [Price Plus Tax](financial/price_plus_tax.py) ## Fractals @@ -655,6 +656,7 @@ * [Sum Of Harmonic Series](maths/sum_of_harmonic_series.py) * [Sumset](maths/sumset.py) * [Sylvester Sequence](maths/sylvester_sequence.py) + * [Tanh](maths/tanh.py) * [Test Prime Check](maths/test_prime_check.py) * [Trapezoidal Rule](maths/trapezoidal_rule.py) * [Triplet Sum](maths/triplet_sum.py) diff --git a/financial/present_value.py b/financial/present_value.py index dc8191a6e..f74612b92 100644 --- a/financial/present_value.py +++ b/financial/present_value.py @@ -6,6 +6,7 @@ An algorithm that calculates the present value of a stream of yearly cash flows 2. An array of cash flows, with the index of the cash flow being the associated year Note: This algorithm assumes that cash flows are paid at the end of the specified year +""" def present_value(discount_rate: float, cash_flows: list[float]) -> float: From e966c5cc0f856afab11a8bb150ef3b48f0c63112 Mon Sep 17 00:00:00 2001 From: Himanshu Tomar Date: Mon, 1 May 2023 15:53:03 +0530 Subject: [PATCH 643/726] Added minimum waiting time problem solution using greedy algorithm (#8701) * Added minimum waiting time problem solution using greedy algorithm * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * ruff --fix * Add type hints * Added two more doc test * Removed unnecessary comments * updated type hints * Updated the code as per the code review --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- DIRECTORY.md | 1 + greedy_methods/minimum_waiting_time.py | 48 ++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 greedy_methods/minimum_waiting_time.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 167d062b4..021669d13 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -450,6 +450,7 @@ * [Fractional Knapsack](greedy_methods/fractional_knapsack.py) * [Fractional Knapsack 2](greedy_methods/fractional_knapsack_2.py) * [Optimal Merge Pattern](greedy_methods/optimal_merge_pattern.py) + * [Minimum Waiting Time ](greedy_methods/minimum_waiting_time.py) ## Hashes * [Adler32](hashes/adler32.py) diff --git a/greedy_methods/minimum_waiting_time.py b/greedy_methods/minimum_waiting_time.py new file mode 100644 index 000000000..aaae8cf8f --- /dev/null +++ b/greedy_methods/minimum_waiting_time.py @@ -0,0 +1,48 @@ +""" +Calculate the minimum waiting time using a greedy algorithm. +reference: https://www.youtube.com/watch?v=Sf3eiO12eJs + +For doctests run following command: +python -m doctest -v minimum_waiting_time.py + +The minimum_waiting_time function uses a greedy algorithm to calculate the minimum +time for queries to complete. It sorts the list in non-decreasing order, calculates +the waiting time for each query by multiplying its position in the list with the +sum of all remaining query times, and returns the total waiting time. A doctest +ensures that the function produces the correct output. +""" + + +def minimum_waiting_time(queries: list[int]) -> int: + """ + This function takes a list of query times and returns the minimum waiting time + for all queries to be completed. + + Args: + queries: A list of queries measured in picoseconds + + Returns: + total_waiting_time: Minimum waiting time measured in picoseconds + + Examples: + >>> minimum_waiting_time([3, 2, 1, 2, 6]) + 17 + >>> minimum_waiting_time([3, 2, 1]) + 4 + >>> minimum_waiting_time([1, 2, 3, 4]) + 10 + >>> minimum_waiting_time([5, 5, 5, 5]) + 30 + >>> minimum_waiting_time([]) + 0 + """ + n = len(queries) + if n in (0, 1): + return 0 + return sum(query * (n - i - 1) for i, query in enumerate(sorted(queries))) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 777f966893d7042d350b44b05ce7f8431f561509 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 1 May 2023 23:48:56 +0200 Subject: [PATCH 644/726] [pre-commit.ci] pre-commit autoupdate (#8704) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/charliermarsh/ruff-pre-commit: v0.0.262 → v0.0.263](https://github.com/charliermarsh/ruff-pre-commit/compare/v0.0.262...v0.0.263) - [github.com/tox-dev/pyproject-fmt: 0.10.0 → 0.11.1](https://github.com/tox-dev/pyproject-fmt/compare/0.10.0...0.11.1) * updating DIRECTORY.md --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- DIRECTORY.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 288473ca3..accb57da3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.262 + rev: v0.0.263 hooks: - id: ruff @@ -33,7 +33,7 @@ repos: - tomli - repo: https://github.com/tox-dev/pyproject-fmt - rev: "0.10.0" + rev: "0.11.1" hooks: - id: pyproject-fmt diff --git a/DIRECTORY.md b/DIRECTORY.md index 021669d13..826bd6fd3 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -449,8 +449,8 @@ ## Greedy Methods * [Fractional Knapsack](greedy_methods/fractional_knapsack.py) * [Fractional Knapsack 2](greedy_methods/fractional_knapsack_2.py) + * [Minimum Waiting Time](greedy_methods/minimum_waiting_time.py) * [Optimal Merge Pattern](greedy_methods/optimal_merge_pattern.py) - * [Minimum Waiting Time ](greedy_methods/minimum_waiting_time.py) ## Hashes * [Adler32](hashes/adler32.py) From 73105145090f0ce972f6fa29cc5d71f012dd8c92 Mon Sep 17 00:00:00 2001 From: Dipankar Mitra <50228537+Mitra-babu@users.noreply.github.com> Date: Tue, 2 May 2023 20:06:28 +0530 Subject: [PATCH 645/726] The ELU activation is added (#8699) * tanh function been added * tanh function been added * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * tanh function is added * tanh function is added * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * tanh function added * tanh function added * tanh function is added * Apply suggestions from code review * ELU activation function is added * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * elu activation is added * ELU activation is added * Update maths/elu_activation.py Co-authored-by: Christian Clauss * Exponential_linear_unit activation is added * Exponential_linear_unit activation is added --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .../exponential_linear_unit.py | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 neural_network/activation_functions/exponential_linear_unit.py diff --git a/neural_network/activation_functions/exponential_linear_unit.py b/neural_network/activation_functions/exponential_linear_unit.py new file mode 100644 index 000000000..7a3cf1d84 --- /dev/null +++ b/neural_network/activation_functions/exponential_linear_unit.py @@ -0,0 +1,40 @@ +""" +Implements the Exponential Linear Unit or ELU function. + +The function takes a vector of K real numbers and a real number alpha as +input and then applies the ELU function to each element of the vector. + +Script inspired from its corresponding Wikipedia article +https://en.wikipedia.org/wiki/Rectifier_(neural_networks) +""" + +import numpy as np + + +def exponential_linear_unit(vector: np.ndarray, alpha: float) -> np.ndarray: + """ + Implements the ELU activation function. + Parameters: + vector: the array containing input of elu activation + alpha: hyper-parameter + return: + elu (np.array): The input numpy array after applying elu. + + Mathematically, f(x) = x, x>0 else (alpha * (e^x -1)), x<=0, alpha >=0 + + Examples: + >>> exponential_linear_unit(vector=np.array([2.3,0.6,-2,-3.8]), alpha=0.3) + array([ 2.3 , 0.6 , -0.25939942, -0.29328877]) + + >>> exponential_linear_unit(vector=np.array([-9.2,-0.3,0.45,-4.56]), alpha=0.067) + array([-0.06699323, -0.01736518, 0.45 , -0.06629904]) + + + """ + return np.where(vector > 0, vector, (alpha * (np.exp(vector) - 1))) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 91cc3a240f05922024d4c5523422138857c48ae0 Mon Sep 17 00:00:00 2001 From: Pronoy Mandal Date: Wed, 10 May 2023 15:04:36 +0530 Subject: [PATCH 646/726] Update game_of_life.py (#8703) Rectify spelling in docstring --- cellular_automata/game_of_life.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cellular_automata/game_of_life.py b/cellular_automata/game_of_life.py index 8e5470251..3382af7b5 100644 --- a/cellular_automata/game_of_life.py +++ b/cellular_automata/game_of_life.py @@ -34,7 +34,7 @@ import numpy as np from matplotlib import pyplot as plt from matplotlib.colors import ListedColormap -usage_doc = "Usage of script: script_nama " +usage_doc = "Usage of script: script_name " choice = [0] * 100 + [1] * 10 random.shuffle(choice) From 209a59ee562dd4b0358d8d1a12b112ec3f3e68ed Mon Sep 17 00:00:00 2001 From: Rohan Anand <96521078+rohan472000@users.noreply.github.com> Date: Wed, 10 May 2023 15:08:52 +0530 Subject: [PATCH 647/726] Update and_gate.py (#8690) * Update and_gate.py addressing issue #8656 by calling `test_and_gate()` , ensuring that all the assertions are verified before the actual output is printed. * Update and_gate.py addressing issue #8632 --- boolean_algebra/and_gate.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boolean_algebra/and_gate.py b/boolean_algebra/and_gate.py index cbbcfde79..834116772 100644 --- a/boolean_algebra/and_gate.py +++ b/boolean_algebra/and_gate.py @@ -43,6 +43,8 @@ def test_and_gate() -> None: if __name__ == "__main__": + test_and_gate() + print(and_gate(1, 0)) print(and_gate(0, 0)) print(and_gate(0, 1)) print(and_gate(1, 1)) From 44aa17fb86b0c04508580425b588c0f8a0cf4ce9 Mon Sep 17 00:00:00 2001 From: shricubed Date: Wed, 10 May 2023 14:50:32 -0400 Subject: [PATCH 648/726] Working binary insertion sort in Python (#8024) --- sorts/binary_insertion_sort.py | 61 ++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 sorts/binary_insertion_sort.py diff --git a/sorts/binary_insertion_sort.py b/sorts/binary_insertion_sort.py new file mode 100644 index 000000000..8d4102558 --- /dev/null +++ b/sorts/binary_insertion_sort.py @@ -0,0 +1,61 @@ +""" +This is a pure Python implementation of the binary insertion sort algorithm + +For doctests run following command: +python -m doctest -v binary_insertion_sort.py +or +python3 -m doctest -v binary_insertion_sort.py + +For manual testing run: +python binary_insertion_sort.py +""" + + +def binary_insertion_sort(collection: list) -> list: + """Pure implementation of the binary insertion sort algorithm in Python + :param collection: some mutable ordered collection with heterogeneous + comparable items inside + :return: the same collection ordered by ascending + + Examples: + >>> binary_insertion_sort([0, 4, 1234, 4, 1]) + [0, 1, 4, 4, 1234] + >>> binary_insertion_sort([]) == sorted([]) + True + >>> binary_insertion_sort([-1, -2, -3]) == sorted([-1, -2, -3]) + True + >>> lst = ['d', 'a', 'b', 'e', 'c'] + >>> binary_insertion_sort(lst) == sorted(lst) + True + >>> import random + >>> collection = random.sample(range(-50, 50), 100) + >>> binary_insertion_sort(collection) == sorted(collection) + True + >>> import string + >>> collection = random.choices(string.ascii_letters + string.digits, k=100) + >>> binary_insertion_sort(collection) == sorted(collection) + True + """ + + n = len(collection) + for i in range(1, n): + val = collection[i] + low = 0 + high = i - 1 + + while low <= high: + mid = (low + high) // 2 + if val < collection[mid]: + high = mid - 1 + else: + low = mid + 1 + for j in range(i, low, -1): + collection[j] = collection[j - 1] + collection[low] = val + return collection + + +if __name__ == "__main__": + user_input = input("Enter numbers separated by a comma:\n").strip() + unsorted = [int(item) for item in user_input.split(",")] + print(binary_insertion_sort(unsorted)) From 997d56fb633e3bd726c1fac32a2d37277361d5e9 Mon Sep 17 00:00:00 2001 From: Margaret <62753112+meg-1@users.noreply.github.com> Date: Wed, 10 May 2023 21:53:47 +0300 Subject: [PATCH 649/726] Switch case (#7995) --- strings/string_switch_case.py | 108 ++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 strings/string_switch_case.py diff --git a/strings/string_switch_case.py b/strings/string_switch_case.py new file mode 100644 index 000000000..9a07472df --- /dev/null +++ b/strings/string_switch_case.py @@ -0,0 +1,108 @@ +import re + +""" +general info: +https://en.wikipedia.org/wiki/Naming_convention_(programming)#Python_and_Ruby + +pascal case [ an upper Camel Case ]: https://en.wikipedia.org/wiki/Camel_case + +camel case: https://en.wikipedia.org/wiki/Camel_case + +kebab case [ can be found in general info ]: +https://en.wikipedia.org/wiki/Naming_convention_(programming)#Python_and_Ruby + +snake case: https://en.wikipedia.org/wiki/Snake_case +""" + + +# assistant functions +def split_input(str_: str) -> list: + """ + >>> split_input("one two 31235three4four") + [['one', 'two', '31235three4four']] + """ + return [char.split() for char in re.split(r"[^ a-z A-Z 0-9 \s]", str_)] + + +def to_simple_case(str_: str) -> str: + """ + >>> to_simple_case("one two 31235three4four") + 'OneTwo31235three4four' + """ + string_split = split_input(str_) + return "".join( + ["".join([char.capitalize() for char in sub_str]) for sub_str in string_split] + ) + + +def to_complex_case(text: str, upper: bool, separator: str) -> str: + """ + >>> to_complex_case("one two 31235three4four", True, "_") + 'ONE_TWO_31235THREE4FOUR' + >>> to_complex_case("one two 31235three4four", False, "-") + 'one-two-31235three4four' + """ + try: + string_split = split_input(text) + if upper: + res_str = "".join( + [ + separator.join([char.upper() for char in sub_str]) + for sub_str in string_split + ] + ) + else: + res_str = "".join( + [ + separator.join([char.lower() for char in sub_str]) + for sub_str in string_split + ] + ) + return res_str + except IndexError: + return "not valid string" + + +# main content +def to_pascal_case(text: str) -> str: + """ + >>> to_pascal_case("one two 31235three4four") + 'OneTwo31235three4four' + """ + return to_simple_case(text) + + +def to_camel_case(text: str) -> str: + """ + >>> to_camel_case("one two 31235three4four") + 'oneTwo31235three4four' + """ + try: + res_str = to_simple_case(text) + return res_str[0].lower() + res_str[1:] + except IndexError: + return "not valid string" + + +def to_snake_case(text: str, upper: bool) -> str: + """ + >>> to_snake_case("one two 31235three4four", True) + 'ONE_TWO_31235THREE4FOUR' + >>> to_snake_case("one two 31235three4four", False) + 'one_two_31235three4four' + """ + return to_complex_case(text, upper, "_") + + +def to_kebab_case(text: str, upper: bool) -> str: + """ + >>> to_kebab_case("one two 31235three4four", True) + 'ONE-TWO-31235THREE4FOUR' + >>> to_kebab_case("one two 31235three4four", False) + 'one-two-31235three4four' + """ + return to_complex_case(text, upper, "-") + + +if __name__ == "__main__": + __import__("doctest").testmod() From 6939538a41202bf05f958c9c2d7c1c20e2f87430 Mon Sep 17 00:00:00 2001 From: Margaret <62753112+meg-1@users.noreply.github.com> Date: Wed, 10 May 2023 21:55:48 +0300 Subject: [PATCH 650/726] adding the remove digit algorithm (#6708) --- maths/remove_digit.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 maths/remove_digit.py diff --git a/maths/remove_digit.py b/maths/remove_digit.py new file mode 100644 index 000000000..db14ac902 --- /dev/null +++ b/maths/remove_digit.py @@ -0,0 +1,37 @@ +def remove_digit(num: int) -> int: + """ + + returns the biggest possible result + that can be achieved by removing + one digit from the given number + + >>> remove_digit(152) + 52 + >>> remove_digit(6385) + 685 + >>> remove_digit(-11) + 1 + >>> remove_digit(2222222) + 222222 + >>> remove_digit("2222222") + Traceback (most recent call last): + TypeError: only integers accepted as input + >>> remove_digit("string input") + Traceback (most recent call last): + TypeError: only integers accepted as input + """ + + if not isinstance(num, int): + raise TypeError("only integers accepted as input") + else: + num_str = str(abs(num)) + num_transpositions = [list(num_str) for char in range(len(num_str))] + for index in range(len(num_str)): + num_transpositions[index].pop(index) + return max( + int("".join(list(transposition))) for transposition in num_transpositions + ) + + +if __name__ == "__main__": + __import__("doctest").testmod() From 793e564e1d4bd6e00b6e2f80869c5fd1fd2872b3 Mon Sep 17 00:00:00 2001 From: Pronoy Mandal Date: Thu, 11 May 2023 00:30:59 +0530 Subject: [PATCH 651/726] Create maximum_subsequence.py (#7811) --- DIRECTORY.md | 1 + other/maximum_subsequence.py | 42 ++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 other/maximum_subsequence.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 826bd6fd3..a70ad6861 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -716,6 +716,7 @@ * [Lru Cache](other/lru_cache.py) * [Magicdiamondpattern](other/magicdiamondpattern.py) * [Maximum Subarray](other/maximum_subarray.py) + * [Maximum Subsequence](other/maximum_subsequence.py) * [Nested Brackets](other/nested_brackets.py) * [Password](other/password.py) * [Quine](other/quine.py) diff --git a/other/maximum_subsequence.py b/other/maximum_subsequence.py new file mode 100644 index 000000000..f81717596 --- /dev/null +++ b/other/maximum_subsequence.py @@ -0,0 +1,42 @@ +from collections.abc import Sequence + + +def max_subsequence_sum(nums: Sequence[int] | None = None) -> int: + """Return the maximum possible sum amongst all non - empty subsequences. + + Raises: + ValueError: when nums is empty. + + >>> max_subsequence_sum([1,2,3,4,-2]) + 10 + >>> max_subsequence_sum([-2, -3, -1, -4, -6]) + -1 + >>> max_subsequence_sum([]) + Traceback (most recent call last): + . . . + ValueError: Input sequence should not be empty + >>> max_subsequence_sum() + Traceback (most recent call last): + . . . + ValueError: Input sequence should not be empty + """ + if nums is None or not nums: + raise ValueError("Input sequence should not be empty") + + ans = nums[0] + for i in range(1, len(nums)): + num = nums[i] + ans = max(ans, ans + num, num) + + return ans + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + + # Try on a sample input from the user + n = int(input("Enter number of elements : ").strip()) + array = list(map(int, input("\nEnter the numbers : ").strip().split()))[:n] + print(max_subsequence_sum(array)) From 1faf10b5c2dff8cef3f5d59f60a126bd19bb1c44 Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Sun, 14 May 2023 22:03:13 +0100 Subject: [PATCH 652/726] Correct ruff failures (#8732) * fix: Correct ruff problems * updating DIRECTORY.md * fix: Fix pre-commit errors * updating DIRECTORY.md --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 6 +++++- conversions/prefix_conversions_string.py | 4 ++-- conversions/rgb_hsv_conversion.py | 4 ++-- .../test_digital_image_processing.py | 2 +- ...ion.py => strassen_matrix_multiplication.py.BROKEN} | 2 +- dynamic_programming/fibonacci.py | 2 +- maths/euclidean_distance.py | 6 +++--- physics/horizontal_projectile_motion.py | 6 +++--- searches/binary_tree_traversal.py | 10 ++++------ 9 files changed, 22 insertions(+), 20 deletions(-) rename divide_and_conquer/{strassen_matrix_multiplication.py => strassen_matrix_multiplication.py.BROKEN} (99%) diff --git a/DIRECTORY.md b/DIRECTORY.md index a70ad6861..fc6cbaf7f 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -294,7 +294,6 @@ * [Mergesort](divide_and_conquer/mergesort.py) * [Peak](divide_and_conquer/peak.py) * [Power](divide_and_conquer/power.py) - * [Strassen Matrix Multiplication](divide_and_conquer/strassen_matrix_multiplication.py) ## Dynamic Programming * [Abbreviation](dynamic_programming/abbreviation.py) @@ -632,6 +631,7 @@ * [Radians](maths/radians.py) * [Radix2 Fft](maths/radix2_fft.py) * [Relu](maths/relu.py) + * [Remove Digit](maths/remove_digit.py) * [Runge Kutta](maths/runge_kutta.py) * [Segmented Sieve](maths/segmented_sieve.py) * Series @@ -694,6 +694,8 @@ ## Neural Network * [2 Hidden Layers Neural Network](neural_network/2_hidden_layers_neural_network.py) + * Activation Functions + * [Exponential Linear Unit](neural_network/activation_functions/exponential_linear_unit.py) * [Back Propagation Neural Network](neural_network/back_propagation_neural_network.py) * [Convolution Neural Network](neural_network/convolution_neural_network.py) * [Input Data](neural_network/input_data.py) @@ -1080,6 +1082,7 @@ ## Sorts * [Bead Sort](sorts/bead_sort.py) + * [Binary Insertion Sort](sorts/binary_insertion_sort.py) * [Bitonic Sort](sorts/bitonic_sort.py) * [Bogo Sort](sorts/bogo_sort.py) * [Bubble Sort](sorts/bubble_sort.py) @@ -1170,6 +1173,7 @@ * [Reverse Words](strings/reverse_words.py) * [Snake Case To Camel Pascal Case](strings/snake_case_to_camel_pascal_case.py) * [Split](strings/split.py) + * [String Switch Case](strings/string_switch_case.py) * [Text Justification](strings/text_justification.py) * [Top K Frequent Words](strings/top_k_frequent_words.py) * [Upper](strings/upper.py) diff --git a/conversions/prefix_conversions_string.py b/conversions/prefix_conversions_string.py index 3851d7c8b..9344c9672 100644 --- a/conversions/prefix_conversions_string.py +++ b/conversions/prefix_conversions_string.py @@ -96,7 +96,7 @@ def add_si_prefix(value: float) -> str: for name_prefix, value_prefix in prefixes.items(): numerical_part = value / (10**value_prefix) if numerical_part > 1: - return f"{str(numerical_part)} {name_prefix}" + return f"{numerical_part!s} {name_prefix}" return str(value) @@ -111,7 +111,7 @@ def add_binary_prefix(value: float) -> str: for prefix in BinaryUnit: numerical_part = value / (2**prefix.value) if numerical_part > 1: - return f"{str(numerical_part)} {prefix.name}" + return f"{numerical_part!s} {prefix.name}" return str(value) diff --git a/conversions/rgb_hsv_conversion.py b/conversions/rgb_hsv_conversion.py index 081cfe1d7..74b3d33e4 100644 --- a/conversions/rgb_hsv_conversion.py +++ b/conversions/rgb_hsv_conversion.py @@ -121,8 +121,8 @@ def rgb_to_hsv(red: int, green: int, blue: int) -> list[float]: float_red = red / 255 float_green = green / 255 float_blue = blue / 255 - value = max(max(float_red, float_green), float_blue) - chroma = value - min(min(float_red, float_green), float_blue) + value = max(float_red, float_green, float_blue) + chroma = value - min(float_red, float_green, float_blue) saturation = 0 if value == 0 else chroma / value if chroma == 0: diff --git a/digital_image_processing/test_digital_image_processing.py b/digital_image_processing/test_digital_image_processing.py index c999464ce..fee7ab247 100644 --- a/digital_image_processing/test_digital_image_processing.py +++ b/digital_image_processing/test_digital_image_processing.py @@ -96,7 +96,7 @@ def test_nearest_neighbour( def test_local_binary_pattern(): - file_path: str = "digital_image_processing/image_data/lena.jpg" + file_path = "digital_image_processing/image_data/lena.jpg" # Reading the image and converting it to grayscale. image = imread(file_path, 0) diff --git a/divide_and_conquer/strassen_matrix_multiplication.py b/divide_and_conquer/strassen_matrix_multiplication.py.BROKEN similarity index 99% rename from divide_and_conquer/strassen_matrix_multiplication.py rename to divide_and_conquer/strassen_matrix_multiplication.py.BROKEN index 371605d6d..2ca91c63b 100644 --- a/divide_and_conquer/strassen_matrix_multiplication.py +++ b/divide_and_conquer/strassen_matrix_multiplication.py.BROKEN @@ -122,7 +122,7 @@ def strassen(matrix1: list, matrix2: list) -> list: if dimension1[0] == dimension1[1] and dimension2[0] == dimension2[1]: return [matrix1, matrix2] - maximum = max(max(dimension1), max(dimension2)) + maximum = max(dimension1, dimension2) maxim = int(math.pow(2, math.ceil(math.log2(maximum)))) new_matrix1 = matrix1 new_matrix2 = matrix2 diff --git a/dynamic_programming/fibonacci.py b/dynamic_programming/fibonacci.py index 7ec5993ef..c102493aa 100644 --- a/dynamic_programming/fibonacci.py +++ b/dynamic_programming/fibonacci.py @@ -24,7 +24,7 @@ class Fibonacci: return self.sequence[:index] -def main(): +def main() -> None: print( "Fibonacci Series Using Dynamic Programming\n", "Enter the index of the Fibonacci number you want to calculate ", diff --git a/maths/euclidean_distance.py b/maths/euclidean_distance.py index 22012e92c..9b29b37b0 100644 --- a/maths/euclidean_distance.py +++ b/maths/euclidean_distance.py @@ -1,12 +1,12 @@ from __future__ import annotations +import typing from collections.abc import Iterable -from typing import Union import numpy as np -Vector = Union[Iterable[float], Iterable[int], np.ndarray] -VectorOut = Union[np.float64, int, float] +Vector = typing.Union[Iterable[float], Iterable[int], np.ndarray] # noqa: UP007 +VectorOut = typing.Union[np.float64, int, float] # noqa: UP007 def euclidean_distance(vector_1: Vector, vector_2: Vector) -> VectorOut: diff --git a/physics/horizontal_projectile_motion.py b/physics/horizontal_projectile_motion.py index dbde3660f..80f85a1b7 100644 --- a/physics/horizontal_projectile_motion.py +++ b/physics/horizontal_projectile_motion.py @@ -147,6 +147,6 @@ if __name__ == "__main__": # Print results print() print("Results: ") - print(f"Horizontal Distance: {str(horizontal_distance(init_vel, angle))} [m]") - print(f"Maximum Height: {str(max_height(init_vel, angle))} [m]") - print(f"Total Time: {str(total_time(init_vel, angle))} [s]") + print(f"Horizontal Distance: {horizontal_distance(init_vel, angle)!s} [m]") + print(f"Maximum Height: {max_height(init_vel, angle)!s} [m]") + print(f"Total Time: {total_time(init_vel, angle)!s} [s]") diff --git a/searches/binary_tree_traversal.py b/searches/binary_tree_traversal.py index 76e80df25..6fb841af4 100644 --- a/searches/binary_tree_traversal.py +++ b/searches/binary_tree_traversal.py @@ -13,11 +13,9 @@ class TreeNode: self.left = None -def build_tree(): +def build_tree() -> TreeNode: print("\n********Press N to stop entering at any point of time********\n") - check = input("Enter the value of the root node: ").strip().lower() or "n" - if check == "n": - return None + check = input("Enter the value of the root node: ").strip().lower() q: queue.Queue = queue.Queue() tree_node = TreeNode(int(check)) q.put(tree_node) @@ -37,7 +35,7 @@ def build_tree(): right_node = TreeNode(int(check)) node_found.right = right_node q.put(right_node) - return None + raise def pre_order(node: TreeNode) -> None: @@ -272,7 +270,7 @@ if __name__ == "__main__": doctest.testmod() print(prompt("Binary Tree Traversals")) - node = build_tree() + node: TreeNode = build_tree() print(prompt("Pre Order Traversal")) pre_order(node) print(prompt() + "\n") From 2a57dafce096b51b4b28d1495116e79472c8a3f4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 22:27:59 +0100 Subject: [PATCH 653/726] [pre-commit.ci] pre-commit autoupdate (#8716) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/charliermarsh/ruff-pre-commit: v0.0.263 → v0.0.267](https://github.com/charliermarsh/ruff-pre-commit/compare/v0.0.263...v0.0.267) - [github.com/tox-dev/pyproject-fmt: 0.11.1 → 0.11.2](https://github.com/tox-dev/pyproject-fmt/compare/0.11.1...0.11.2) - [github.com/pre-commit/mirrors-mypy: v1.2.0 → v1.3.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.2.0...v1.3.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index accb57da3..6bdbc7370 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.263 + rev: v0.0.267 hooks: - id: ruff @@ -33,7 +33,7 @@ repos: - tomli - repo: https://github.com/tox-dev/pyproject-fmt - rev: "0.11.1" + rev: "0.11.2" hooks: - id: pyproject-fmt @@ -51,7 +51,7 @@ repos: - id: validate-pyproject - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.2.0 + rev: v1.3.0 hooks: - id: mypy args: From c0892a06515b8ea5030db2e8344dee2292bb10ad Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Tue, 16 May 2023 00:47:50 +0300 Subject: [PATCH 654/726] Reduce the complexity of genetic_algorithm/basic_string.py (#8606) --- genetic_algorithm/basic_string.py | 95 ++++++++++++++++--------------- 1 file changed, 50 insertions(+), 45 deletions(-) diff --git a/genetic_algorithm/basic_string.py b/genetic_algorithm/basic_string.py index 45b8be651..388e7219f 100644 --- a/genetic_algorithm/basic_string.py +++ b/genetic_algorithm/basic_string.py @@ -21,6 +21,54 @@ MUTATION_PROBABILITY = 0.4 random.seed(random.randint(0, 1000)) +def evaluate(item: str, main_target: str) -> tuple[str, float]: + """ + Evaluate how similar the item is with the target by just + counting each char in the right position + >>> evaluate("Helxo Worlx", "Hello World") + ('Helxo Worlx', 9.0) + """ + score = len([g for position, g in enumerate(item) if g == main_target[position]]) + return (item, float(score)) + + +def crossover(parent_1: str, parent_2: str) -> tuple[str, str]: + """Slice and combine two string at a random point.""" + random_slice = random.randint(0, len(parent_1) - 1) + child_1 = parent_1[:random_slice] + parent_2[random_slice:] + child_2 = parent_2[:random_slice] + parent_1[random_slice:] + return (child_1, child_2) + + +def mutate(child: str, genes: list[str]) -> str: + """Mutate a random gene of a child with another one from the list.""" + child_list = list(child) + if random.uniform(0, 1) < MUTATION_PROBABILITY: + child_list[random.randint(0, len(child)) - 1] = random.choice(genes) + return "".join(child_list) + + +# Select, crossover and mutate a new population. +def select( + parent_1: tuple[str, float], + population_score: list[tuple[str, float]], + genes: list[str], +) -> list[str]: + """Select the second parent and generate new population""" + pop = [] + # Generate more children proportionally to the fitness score. + child_n = int(parent_1[1] * 100) + 1 + child_n = 10 if child_n >= 10 else child_n + for _ in range(child_n): + parent_2 = population_score[random.randint(0, N_SELECTED)][0] + + child_1, child_2 = crossover(parent_1[0], parent_2) + # Append new string to the population list. + pop.append(mutate(child_1, genes)) + pop.append(mutate(child_2, genes)) + return pop + + def basic(target: str, genes: list[str], debug: bool = True) -> tuple[int, int, str]: """ Verify that the target contains no genes besides the ones inside genes variable. @@ -70,17 +118,6 @@ def basic(target: str, genes: list[str], debug: bool = True) -> tuple[int, int, total_population += len(population) # Random population created. Now it's time to evaluate. - def evaluate(item: str, main_target: str = target) -> tuple[str, float]: - """ - Evaluate how similar the item is with the target by just - counting each char in the right position - >>> evaluate("Helxo Worlx", Hello World) - ["Helxo Worlx", 9] - """ - score = len( - [g for position, g in enumerate(item) if g == main_target[position]] - ) - return (item, float(score)) # Adding a bit of concurrency can make everything faster, # @@ -94,7 +131,7 @@ def basic(target: str, genes: list[str], debug: bool = True) -> tuple[int, int, # # but with a simple algorithm like this, it will probably be slower. # We just need to call evaluate for every item inside the population. - population_score = [evaluate(item) for item in population] + population_score = [evaluate(item, target) for item in population] # Check if there is a matching evolution. population_score = sorted(population_score, key=lambda x: x[1], reverse=True) @@ -121,41 +158,9 @@ def basic(target: str, genes: list[str], debug: bool = True) -> tuple[int, int, (item, score / len(target)) for item, score in population_score ] - # Select, crossover and mutate a new population. - def select(parent_1: tuple[str, float]) -> list[str]: - """Select the second parent and generate new population""" - pop = [] - # Generate more children proportionally to the fitness score. - child_n = int(parent_1[1] * 100) + 1 - child_n = 10 if child_n >= 10 else child_n - for _ in range(child_n): - parent_2 = population_score[ # noqa: B023 - random.randint(0, N_SELECTED) - ][0] - - child_1, child_2 = crossover(parent_1[0], parent_2) - # Append new string to the population list. - pop.append(mutate(child_1)) - pop.append(mutate(child_2)) - return pop - - def crossover(parent_1: str, parent_2: str) -> tuple[str, str]: - """Slice and combine two string at a random point.""" - random_slice = random.randint(0, len(parent_1) - 1) - child_1 = parent_1[:random_slice] + parent_2[random_slice:] - child_2 = parent_2[:random_slice] + parent_1[random_slice:] - return (child_1, child_2) - - def mutate(child: str) -> str: - """Mutate a random gene of a child with another one from the list.""" - child_list = list(child) - if random.uniform(0, 1) < MUTATION_PROBABILITY: - child_list[random.randint(0, len(child)) - 1] = random.choice(genes) - return "".join(child_list) - # This is selection for i in range(N_SELECTED): - population.extend(select(population_score[int(i)])) + population.extend(select(population_score[int(i)], population_score, genes)) # Check if the population has already reached the maximum value and if so, # break the cycle. If this check is disabled, the algorithm will take # forever to compute large strings, but will also calculate small strings in From 8102424950f2d3801eda7817d7f69288fd984a63 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Tue, 16 May 2023 17:05:55 -0700 Subject: [PATCH 655/726] `local_weighted_learning.py`: fix `mypy` errors and more (#8073) --- .../local_weighted_learning.py | 188 +++++++++++------- 1 file changed, 112 insertions(+), 76 deletions(-) diff --git a/machine_learning/local_weighted_learning/local_weighted_learning.py b/machine_learning/local_weighted_learning/local_weighted_learning.py index 6260e9ac6..8dd0e55d4 100644 --- a/machine_learning/local_weighted_learning/local_weighted_learning.py +++ b/machine_learning/local_weighted_learning/local_weighted_learning.py @@ -1,14 +1,55 @@ +""" +Locally weighted linear regression, also called local regression, is a type of +non-parametric linear regression that prioritizes data closest to a given +prediction point. The algorithm estimates the vector of model coefficients β +using weighted least squares regression: + +β = (XᵀWX)⁻¹(XᵀWy), + +where X is the design matrix, y is the response vector, and W is the diagonal +weight matrix. + +This implementation calculates wᵢ, the weight of the ith training sample, using +the Gaussian weight: + +wᵢ = exp(-‖xᵢ - x‖²/(2τ²)), + +where xᵢ is the ith training sample, x is the prediction point, τ is the +"bandwidth", and ‖x‖ is the Euclidean norm (also called the 2-norm or the L² +norm). The bandwidth τ controls how quickly the weight of a training sample +decreases as its distance from the prediction point increases. One can think of +the Gaussian weight as a bell curve centered around the prediction point: a +training sample is weighted lower if it's farther from the center, and τ +controls the spread of the bell curve. + +Other types of locally weighted regression such as locally estimated scatterplot +smoothing (LOESS) typically use different weight functions. + +References: + - https://en.wikipedia.org/wiki/Local_regression + - https://en.wikipedia.org/wiki/Weighted_least_squares + - https://cs229.stanford.edu/notes2022fall/main_notes.pdf +""" + import matplotlib.pyplot as plt import numpy as np -def weighted_matrix( - point: np.array, training_data_x: np.array, bandwidth: float -) -> np.array: +def weight_matrix(point: np.ndarray, x_train: np.ndarray, tau: float) -> np.ndarray: """ - Calculate the weight for every point in the data set. - point --> the x value at which we want to make predictions - >>> weighted_matrix( + Calculate the weight of every point in the training data around a given + prediction point + + Args: + point: x-value at which the prediction is being made + x_train: ndarray of x-values for training + tau: bandwidth value, controls how quickly the weight of training values + decreases as the distance from the prediction point increases + + Returns: + m x m weight matrix around the prediction point, where m is the size of + the training set + >>> weight_matrix( ... np.array([1., 1.]), ... np.array([[16.99, 10.34], [21.01,23.68], [24.59,25.69]]), ... 0.6 @@ -17,25 +58,30 @@ def weighted_matrix( [0.00000000e+000, 0.00000000e+000, 0.00000000e+000], [0.00000000e+000, 0.00000000e+000, 0.00000000e+000]]) """ - m, _ = np.shape(training_data_x) # m is the number of training samples - weights = np.eye(m) # Initializing weights as identity matrix - - # calculating weights for all training examples [x(i)'s] + m = len(x_train) # Number of training samples + weights = np.eye(m) # Initialize weights as identity matrix for j in range(m): - diff = point - training_data_x[j] - weights[j, j] = np.exp(diff @ diff.T / (-2.0 * bandwidth**2)) + diff = point - x_train[j] + weights[j, j] = np.exp(diff @ diff.T / (-2.0 * tau**2)) + return weights def local_weight( - point: np.array, - training_data_x: np.array, - training_data_y: np.array, - bandwidth: float, -) -> np.array: + point: np.ndarray, x_train: np.ndarray, y_train: np.ndarray, tau: float +) -> np.ndarray: """ - Calculate the local weights using the weight_matrix function on training data. - Return the weighted matrix. + Calculate the local weights at a given prediction point using the weight + matrix for that point + + Args: + point: x-value at which the prediction is being made + x_train: ndarray of x-values for training + y_train: ndarray of y-values for training + tau: bandwidth value, controls how quickly the weight of training values + decreases as the distance from the prediction point increases + Returns: + ndarray of local weights >>> local_weight( ... np.array([1., 1.]), ... np.array([[16.99, 10.34], [21.01,23.68], [24.59,25.69]]), @@ -45,19 +91,28 @@ def local_weight( array([[0.00873174], [0.08272556]]) """ - weight = weighted_matrix(point, training_data_x, bandwidth) - w = np.linalg.inv(training_data_x.T @ (weight @ training_data_x)) @ ( - training_data_x.T @ weight @ training_data_y.T + weight_mat = weight_matrix(point, x_train, tau) + weight = np.linalg.inv(x_train.T @ weight_mat @ x_train) @ ( + x_train.T @ weight_mat @ y_train.T ) - return w + return weight def local_weight_regression( - training_data_x: np.array, training_data_y: np.array, bandwidth: float -) -> np.array: + x_train: np.ndarray, y_train: np.ndarray, tau: float +) -> np.ndarray: """ - Calculate predictions for each data point on axis + Calculate predictions for each point in the training data + + Args: + x_train: ndarray of x-values for training + y_train: ndarray of y-values for training + tau: bandwidth value, controls how quickly the weight of training values + decreases as the distance from the prediction point increases + + Returns: + ndarray of predictions >>> local_weight_regression( ... np.array([[16.99, 10.34], [21.01, 23.68], [24.59, 25.69]]), ... np.array([[1.01, 1.66, 3.5]]), @@ -65,77 +120,57 @@ def local_weight_regression( ... ) array([1.07173261, 1.65970737, 3.50160179]) """ - m, _ = np.shape(training_data_x) - ypred = np.zeros(m) + y_pred = np.zeros(len(x_train)) # Initialize array of predictions + for i, item in enumerate(x_train): + y_pred[i] = item @ local_weight(item, x_train, y_train, tau) - for i, item in enumerate(training_data_x): - ypred[i] = item @ local_weight( - item, training_data_x, training_data_y, bandwidth - ) - - return ypred + return y_pred def load_data( - dataset_name: str, cola_name: str, colb_name: str -) -> tuple[np.array, np.array, np.array, np.array]: + dataset_name: str, x_name: str, y_name: str +) -> tuple[np.ndarray, np.ndarray, np.ndarray]: """ Load data from seaborn and split it into x and y points + >>> pass # No doctests, function is for demo purposes only """ import seaborn as sns data = sns.load_dataset(dataset_name) - col_a = np.array(data[cola_name]) # total_bill - col_b = np.array(data[colb_name]) # tip + x_data = np.array(data[x_name]) + y_data = np.array(data[y_name]) - mcol_a = col_a.copy() - mcol_b = col_b.copy() + one = np.ones(len(y_data)) - one = np.ones(np.shape(mcol_b)[0], dtype=int) + # pairing elements of one and x_data + x_train = np.column_stack((one, x_data)) - # pairing elements of one and mcol_a - training_data_x = np.column_stack((one, mcol_a)) - - return training_data_x, mcol_b, col_a, col_b - - -def get_preds(training_data_x: np.array, mcol_b: np.array, tau: float) -> np.array: - """ - Get predictions with minimum error for each training data - >>> get_preds( - ... np.array([[16.99, 10.34], [21.01, 23.68], [24.59, 25.69]]), - ... np.array([[1.01, 1.66, 3.5]]), - ... 0.6 - ... ) - array([1.07173261, 1.65970737, 3.50160179]) - """ - ypred = local_weight_regression(training_data_x, mcol_b, tau) - return ypred + return x_train, x_data, y_data def plot_preds( - training_data_x: np.array, - predictions: np.array, - col_x: np.array, - col_y: np.array, - cola_name: str, - colb_name: str, -) -> plt.plot: + x_train: np.ndarray, + preds: np.ndarray, + x_data: np.ndarray, + y_data: np.ndarray, + x_name: str, + y_name: str, +) -> None: """ Plot predictions and display the graph + >>> pass # No doctests, function is for demo purposes only """ - xsort = training_data_x.copy() - xsort.sort(axis=0) - plt.scatter(col_x, col_y, color="blue") + x_train_sorted = np.sort(x_train, axis=0) + plt.scatter(x_data, y_data, color="blue") plt.plot( - xsort[:, 1], - predictions[training_data_x[:, 1].argsort(0)], + x_train_sorted[:, 1], + preds[x_train[:, 1].argsort(0)], color="yellow", linewidth=5, ) plt.title("Local Weighted Regression") - plt.xlabel(cola_name) - plt.ylabel(colb_name) + plt.xlabel(x_name) + plt.ylabel(y_name) plt.show() @@ -144,6 +179,7 @@ if __name__ == "__main__": doctest.testmod() - training_data_x, mcol_b, col_a, col_b = load_data("tips", "total_bill", "tip") - predictions = get_preds(training_data_x, mcol_b, 0.5) - plot_preds(training_data_x, predictions, col_a, col_b, "total_bill", "tip") + # Demo with a dataset from the seaborn module + training_data_x, total_bill, tip = load_data("tips", "total_bill", "tip") + predictions = local_weight_regression(training_data_x, tip, 5) + plot_preds(training_data_x, predictions, total_bill, tip, "total_bill", "tip") From 3dc143f7218a1221f346c0fccb516d1199850e18 Mon Sep 17 00:00:00 2001 From: Rohan Saraogi <62804340+r0sa2@users.noreply.github.com> Date: Wed, 17 May 2023 05:38:56 +0530 Subject: [PATCH 656/726] Added odd_sieve.py (#8740) --- maths/odd_sieve.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 maths/odd_sieve.py diff --git a/maths/odd_sieve.py b/maths/odd_sieve.py new file mode 100644 index 000000000..60e92921a --- /dev/null +++ b/maths/odd_sieve.py @@ -0,0 +1,42 @@ +from itertools import compress, repeat +from math import ceil, sqrt + + +def odd_sieve(num: int) -> list[int]: + """ + Returns the prime numbers < `num`. The prime numbers are calculated using an + odd sieve implementation of the Sieve of Eratosthenes algorithm + (see for reference https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes). + + >>> odd_sieve(2) + [] + >>> odd_sieve(3) + [2] + >>> odd_sieve(10) + [2, 3, 5, 7] + >>> odd_sieve(20) + [2, 3, 5, 7, 11, 13, 17, 19] + """ + + if num <= 2: + return [] + if num == 3: + return [2] + + # Odd sieve for numbers in range [3, num - 1] + sieve = bytearray(b"\x01") * ((num >> 1) - 1) + + for i in range(3, int(sqrt(num)) + 1, 2): + if sieve[(i >> 1) - 1]: + i_squared = i**2 + sieve[(i_squared >> 1) - 1 :: i] = repeat( + 0, ceil((num - i_squared) / (i << 1)) + ) + + return [2] + list(compress(range(3, num, 2), sieve)) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 61cfb43d2b9246d1e2019ce7f03cb91f452ed2ba Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Wed, 17 May 2023 04:21:16 +0400 Subject: [PATCH 657/726] Add h index (#8036) --- DIRECTORY.md | 1 + other/h_index.py | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 other/h_index.py diff --git a/DIRECTORY.md b/DIRECTORY.md index fc6cbaf7f..46bd51ce9 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -712,6 +712,7 @@ * [Gauss Easter](other/gauss_easter.py) * [Graham Scan](other/graham_scan.py) * [Greedy](other/greedy.py) + * [H Index](other/h_index.py) * [Least Recently Used](other/least_recently_used.py) * [Lfu Cache](other/lfu_cache.py) * [Linear Congruential Generator](other/linear_congruential_generator.py) diff --git a/other/h_index.py b/other/h_index.py new file mode 100644 index 000000000..e91389675 --- /dev/null +++ b/other/h_index.py @@ -0,0 +1,71 @@ +""" +Task: +Given an array of integers citations where citations[i] is the number of +citations a researcher received for their ith paper, return compute the +researcher's h-index. + +According to the definition of h-index on Wikipedia: A scientist has an +index h if h of their n papers have at least h citations each, and the other +n - h papers have no more than h citations each. + +If there are several possible values for h, the maximum one is taken as the +h-index. + +H-Index link: https://en.wikipedia.org/wiki/H-index + +Implementation notes: +Use sorting of array + +Leetcode link: https://leetcode.com/problems/h-index/description/ + +n = len(citations) +Runtime Complexity: O(n * log(n)) +Space Complexity: O(1) + +""" + + +def h_index(citations: list[int]) -> int: + """ + Return H-index of citations + + >>> h_index([3, 0, 6, 1, 5]) + 3 + >>> h_index([1, 3, 1]) + 1 + >>> h_index([1, 2, 3]) + 2 + >>> h_index('test') + Traceback (most recent call last): + ... + ValueError: The citations should be a list of non negative integers. + >>> h_index([1,2,'3']) + Traceback (most recent call last): + ... + ValueError: The citations should be a list of non negative integers. + >>> h_index([1,2,-3]) + Traceback (most recent call last): + ... + ValueError: The citations should be a list of non negative integers. + """ + + # validate: + if not isinstance(citations, list) or not all( + isinstance(item, int) and item >= 0 for item in citations + ): + raise ValueError("The citations should be a list of non negative integers.") + + citations.sort() + len_citations = len(citations) + + for i in range(len_citations): + if citations[len_citations - 1 - i] <= i: + return i + + return len_citations + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From a2783c6597a154a87f60bb5878770d2f152a1d09 Mon Sep 17 00:00:00 2001 From: Harkishan Khuva <78949167+hakiKhuva@users.noreply.github.com> Date: Wed, 17 May 2023 05:52:24 +0530 Subject: [PATCH 658/726] Create guess_the_number_search.py (#7937) --- other/guess_the_number_search.py | 165 +++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 other/guess_the_number_search.py diff --git a/other/guess_the_number_search.py b/other/guess_the_number_search.py new file mode 100644 index 000000000..0439223f2 --- /dev/null +++ b/other/guess_the_number_search.py @@ -0,0 +1,165 @@ +""" +guess the number using lower,higher and the value to find or guess + +solution works by dividing lower and higher of number guessed + +suppose lower is 0, higher is 1000 and the number to guess is 355 + +>>> guess_the_number(10, 1000, 17) +started... +guess the number : 17 +details : [505, 257, 133, 71, 40, 25, 17] + +""" + + +def temp_input_value( + min_val: int = 10, max_val: int = 1000, option: bool = True +) -> int: + """ + Temporary input values for tests + + >>> temp_input_value(option=True) + 10 + + >>> temp_input_value(option=False) + 1000 + + >>> temp_input_value(min_val=100, option=True) + 100 + + >>> temp_input_value(min_val=100, max_val=50) + Traceback (most recent call last): + ... + ValueError: Invalid value for min_val or max_val (min_value < max_value) + + >>> temp_input_value("ten","fifty",1) + Traceback (most recent call last): + ... + AssertionError: Invalid type of value(s) specified to function! + + >>> temp_input_value(min_val=-100, max_val=500) + -100 + + >>> temp_input_value(min_val=-5100, max_val=-100) + -5100 + """ + assert ( + isinstance(min_val, int) + and isinstance(max_val, int) + and isinstance(option, bool) + ), "Invalid type of value(s) specified to function!" + + if min_val > max_val: + raise ValueError("Invalid value for min_val or max_val (min_value < max_value)") + return min_val if option else max_val + + +def get_avg(number_1: int, number_2: int) -> int: + """ + Return the mid-number(whole) of two integers a and b + + >>> get_avg(10, 15) + 12 + + >>> get_avg(20, 300) + 160 + + >>> get_avg("abcd", 300) + Traceback (most recent call last): + ... + TypeError: can only concatenate str (not "int") to str + + >>> get_avg(10.5,50.25) + 30 + """ + return int((number_1 + number_2) / 2) + + +def guess_the_number(lower: int, higher: int, to_guess: int) -> None: + """ + The `guess_the_number` function that guess the number by some operations + and using inner functions + + >>> guess_the_number(10, 1000, 17) + started... + guess the number : 17 + details : [505, 257, 133, 71, 40, 25, 17] + + >>> guess_the_number(-10000, 10000, 7) + started... + guess the number : 7 + details : [0, 5000, 2500, 1250, 625, 312, 156, 78, 39, 19, 9, 4, 6, 7] + + >>> guess_the_number(10, 1000, "a") + Traceback (most recent call last): + ... + AssertionError: argument values must be type of "int" + + >>> guess_the_number(10, 1000, 5) + Traceback (most recent call last): + ... + ValueError: guess value must be within the range of lower and higher value + + >>> guess_the_number(10000, 100, 5) + Traceback (most recent call last): + ... + ValueError: argument value for lower and higher must be(lower > higher) + """ + assert ( + isinstance(lower, int) and isinstance(higher, int) and isinstance(to_guess, int) + ), 'argument values must be type of "int"' + + if lower > higher: + raise ValueError("argument value for lower and higher must be(lower > higher)") + + if not lower < to_guess < higher: + raise ValueError( + "guess value must be within the range of lower and higher value" + ) + + def answer(number: int) -> str: + """ + Returns value by comparing with entered `to_guess` number + """ + if number > to_guess: + return "high" + elif number < to_guess: + return "low" + else: + return "same" + + print("started...") + + last_lowest = lower + last_highest = higher + + last_numbers = [] + + while True: + number = get_avg(last_lowest, last_highest) + last_numbers.append(number) + + if answer(number) == "low": + last_lowest = number + elif answer(number) == "high": + last_highest = number + else: + break + + print(f"guess the number : {last_numbers[-1]}") + print(f"details : {str(last_numbers)}") + + +def main() -> None: + """ + starting point or function of script + """ + lower = int(input("Enter lower value : ").strip()) + higher = int(input("Enter high value : ").strip()) + guess = int(input("Enter value to guess : ").strip()) + guess_the_number(lower, higher, guess) + + +if __name__ == "__main__": + main() From 9b3e4028c6927a17656e590e878c2a101bc4e951 Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Wed, 17 May 2023 07:47:23 +0100 Subject: [PATCH 659/726] Fixes broken "Create guess_the_number_search.py" (#8746) --- DIRECTORY.md | 2 ++ other/guess_the_number_search.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 46bd51ce9..82791cde1 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -605,6 +605,7 @@ * [Newton Raphson](maths/newton_raphson.py) * [Number Of Digits](maths/number_of_digits.py) * [Numerical Integration](maths/numerical_integration.py) + * [Odd Sieve](maths/odd_sieve.py) * [Perfect Cube](maths/perfect_cube.py) * [Perfect Number](maths/perfect_number.py) * [Perfect Square](maths/perfect_square.py) @@ -712,6 +713,7 @@ * [Gauss Easter](other/gauss_easter.py) * [Graham Scan](other/graham_scan.py) * [Greedy](other/greedy.py) + * [Guess The Number Search](other/guess_the_number_search.py) * [H Index](other/h_index.py) * [Least Recently Used](other/least_recently_used.py) * [Lfu Cache](other/lfu_cache.py) diff --git a/other/guess_the_number_search.py b/other/guess_the_number_search.py index 0439223f2..01e8898bb 100644 --- a/other/guess_the_number_search.py +++ b/other/guess_the_number_search.py @@ -148,7 +148,7 @@ def guess_the_number(lower: int, higher: int, to_guess: int) -> None: break print(f"guess the number : {last_numbers[-1]}") - print(f"details : {str(last_numbers)}") + print(f"details : {last_numbers!s}") def main() -> None: From cf5e34d4794fbba04d18c98d5d09854029c83466 Mon Sep 17 00:00:00 2001 From: Rohan Saraogi <62804340+r0sa2@users.noreply.github.com> Date: Fri, 19 May 2023 05:18:22 +0530 Subject: [PATCH 660/726] Added is_palindrome.py (#8748) --- maths/is_palindrome.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 maths/is_palindrome.py diff --git a/maths/is_palindrome.py b/maths/is_palindrome.py new file mode 100644 index 000000000..ba60573ab --- /dev/null +++ b/maths/is_palindrome.py @@ -0,0 +1,34 @@ +def is_palindrome(num: int) -> bool: + """ + Returns whether `num` is a palindrome or not + (see for reference https://en.wikipedia.org/wiki/Palindromic_number). + + >>> is_palindrome(-121) + False + >>> is_palindrome(0) + True + >>> is_palindrome(10) + False + >>> is_palindrome(11) + True + >>> is_palindrome(101) + True + >>> is_palindrome(120) + False + """ + if num < 0: + return False + + num_copy: int = num + rev_num: int = 0 + while num > 0: + rev_num = rev_num * 10 + (num % 10) + num //= 10 + + return num_copy == rev_num + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From edc17b60e00e704cb4109a0e6b18c6ad43234c26 Mon Sep 17 00:00:00 2001 From: Daniel Luo <103051750+DanielLuo7@users.noreply.github.com> Date: Thu, 18 May 2023 20:40:52 -0400 Subject: [PATCH 661/726] add __main__ around print (#8747) --- ciphers/mixed_keyword_cypher.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ciphers/mixed_keyword_cypher.py b/ciphers/mixed_keyword_cypher.py index 806004faa..93a0e3acb 100644 --- a/ciphers/mixed_keyword_cypher.py +++ b/ciphers/mixed_keyword_cypher.py @@ -65,4 +65,5 @@ def mixed_keyword(key: str = "college", pt: str = "UNIVERSITY") -> str: return cypher -print(mixed_keyword("college", "UNIVERSITY")) +if __name__ == "__main__": + print(mixed_keyword("college", "UNIVERSITY")) From ce43a8ac4ad14e1639014d374b1137906218cfe3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 23 May 2023 05:54:30 +0200 Subject: [PATCH 662/726] [pre-commit.ci] pre-commit autoupdate (#8759) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/charliermarsh/ruff-pre-commit: v0.0.267 → v0.0.269](https://github.com/charliermarsh/ruff-pre-commit/compare/v0.0.267...v0.0.269) - [github.com/abravalheri/validate-pyproject: v0.12.2 → v0.13](https://github.com/abravalheri/validate-pyproject/compare/v0.12.2...v0.13) * updating DIRECTORY.md --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- DIRECTORY.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6bdbc7370..bd5bca8f0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.267 + rev: v0.0.269 hooks: - id: ruff @@ -46,7 +46,7 @@ repos: pass_filenames: false - repo: https://github.com/abravalheri/validate-pyproject - rev: v0.12.2 + rev: v0.13 hooks: - id: validate-pyproject diff --git a/DIRECTORY.md b/DIRECTORY.md index 82791cde1..3181a93f3 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -577,6 +577,7 @@ * [Hexagonal Number](maths/hexagonal_number.py) * [Integration By Simpson Approx](maths/integration_by_simpson_approx.py) * [Is Ip V4 Address Valid](maths/is_ip_v4_address_valid.py) + * [Is Palindrome](maths/is_palindrome.py) * [Is Square Free](maths/is_square_free.py) * [Jaccard Similarity](maths/jaccard_similarity.py) * [Juggler Sequence](maths/juggler_sequence.py) From df88771905e68c0639069a92144d6b7af1d491ce Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Thu, 25 May 2023 06:59:15 +0100 Subject: [PATCH 663/726] Mark fetch anime and play as broken (#8763) * updating DIRECTORY.md * updating DIRECTORY.md * fix: Correct ruff errors * fix: Mark anime algorithm as broken * updating DIRECTORY.md --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 1 - .../{fetch_anime_and_play.py => fetch_anime_and_play.py.BROKEN} | 0 2 files changed, 1 deletion(-) rename web_programming/{fetch_anime_and_play.py => fetch_anime_and_play.py.BROKEN} (100%) diff --git a/DIRECTORY.md b/DIRECTORY.md index 3181a93f3..71bdf30b2 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -1199,7 +1199,6 @@ * [Daily Horoscope](web_programming/daily_horoscope.py) * [Download Images From Google Query](web_programming/download_images_from_google_query.py) * [Emails From Url](web_programming/emails_from_url.py) - * [Fetch Anime And Play](web_programming/fetch_anime_and_play.py) * [Fetch Bbc News](web_programming/fetch_bbc_news.py) * [Fetch Github Info](web_programming/fetch_github_info.py) * [Fetch Jobs](web_programming/fetch_jobs.py) diff --git a/web_programming/fetch_anime_and_play.py b/web_programming/fetch_anime_and_play.py.BROKEN similarity index 100% rename from web_programming/fetch_anime_and_play.py rename to web_programming/fetch_anime_and_play.py.BROKEN From 200429fc4739c3757180635016614b984cfd2206 Mon Sep 17 00:00:00 2001 From: Chris O <46587501+ChrisO345@users.noreply.github.com> Date: Thu, 25 May 2023 18:04:42 +1200 Subject: [PATCH 664/726] Dual Number Automatic Differentiation (#8760) * Added dual_number_automatic_differentiation.py * updating DIRECTORY.md * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update maths/dual_number_automatic_differentiation.py --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- DIRECTORY.md | 1 + .../dual_number_automatic_differentiation.py | 141 ++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 maths/dual_number_automatic_differentiation.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 71bdf30b2..a75723369 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -549,6 +549,7 @@ * [Dodecahedron](maths/dodecahedron.py) * [Double Factorial Iterative](maths/double_factorial_iterative.py) * [Double Factorial Recursive](maths/double_factorial_recursive.py) + * [Dual Number Automatic Differentiation](maths/dual_number_automatic_differentiation.py) * [Entropy](maths/entropy.py) * [Euclidean Distance](maths/euclidean_distance.py) * [Euclidean Gcd](maths/euclidean_gcd.py) diff --git a/maths/dual_number_automatic_differentiation.py b/maths/dual_number_automatic_differentiation.py new file mode 100644 index 000000000..9aa75830c --- /dev/null +++ b/maths/dual_number_automatic_differentiation.py @@ -0,0 +1,141 @@ +from math import factorial + +""" +https://en.wikipedia.org/wiki/Automatic_differentiation#Automatic_differentiation_using_dual_numbers +https://blog.jliszka.org/2013/10/24/exact-numeric-nth-derivatives.html + +Note this only works for basic functions, f(x) where the power of x is positive. +""" + + +class Dual: + def __init__(self, real, rank): + self.real = real + if isinstance(rank, int): + self.duals = [1] * rank + else: + self.duals = rank + + def __repr__(self): + return ( + f"{self.real}+" + f"{'+'.join(str(dual)+'E'+str(n+1)for n,dual in enumerate(self.duals))}" + ) + + def reduce(self): + cur = self.duals.copy() + while cur[-1] == 0: + cur.pop(-1) + return Dual(self.real, cur) + + def __add__(self, other): + if not isinstance(other, Dual): + return Dual(self.real + other, self.duals) + s_dual = self.duals.copy() + o_dual = other.duals.copy() + if len(s_dual) > len(o_dual): + o_dual.extend([1] * (len(s_dual) - len(o_dual))) + elif len(s_dual) < len(o_dual): + s_dual.extend([1] * (len(o_dual) - len(s_dual))) + new_duals = [] + for i in range(len(s_dual)): + new_duals.append(s_dual[i] + o_dual[i]) + return Dual(self.real + other.real, new_duals) + + __radd__ = __add__ + + def __sub__(self, other): + return self + other * -1 + + def __mul__(self, other): + if not isinstance(other, Dual): + new_duals = [] + for i in self.duals: + new_duals.append(i * other) + return Dual(self.real * other, new_duals) + new_duals = [0] * (len(self.duals) + len(other.duals) + 1) + for i, item in enumerate(self.duals): + for j, jtem in enumerate(other.duals): + new_duals[i + j + 1] += item * jtem + for k in range(len(self.duals)): + new_duals[k] += self.duals[k] * other.real + for index in range(len(other.duals)): + new_duals[index] += other.duals[index] * self.real + return Dual(self.real * other.real, new_duals) + + __rmul__ = __mul__ + + def __truediv__(self, other): + if not isinstance(other, Dual): + new_duals = [] + for i in self.duals: + new_duals.append(i / other) + return Dual(self.real / other, new_duals) + raise ValueError() + + def __floordiv__(self, other): + if not isinstance(other, Dual): + new_duals = [] + for i in self.duals: + new_duals.append(i // other) + return Dual(self.real // other, new_duals) + raise ValueError() + + def __pow__(self, n): + if n < 0 or isinstance(n, float): + raise ValueError("power must be a positive integer") + if n == 0: + return 1 + if n == 1: + return self + x = self + for _ in range(n - 1): + x *= self + return x + + +def differentiate(func, position, order): + """ + >>> differentiate(lambda x: x**2, 2, 2) + 2 + >>> differentiate(lambda x: x**2 * x**4, 9, 2) + 196830 + >>> differentiate(lambda y: 0.5 * (y + 3) ** 6, 3.5, 4) + 7605.0 + >>> differentiate(lambda y: y ** 2, 4, 3) + 0 + >>> differentiate(8, 8, 8) + Traceback (most recent call last): + ... + ValueError: differentiate() requires a function as input for func + >>> differentiate(lambda x: x **2, "", 1) + Traceback (most recent call last): + ... + ValueError: differentiate() requires a float as input for position + >>> differentiate(lambda x: x**2, 3, "") + Traceback (most recent call last): + ... + ValueError: differentiate() requires an int as input for order + """ + if not callable(func): + raise ValueError("differentiate() requires a function as input for func") + if not isinstance(position, (float, int)): + raise ValueError("differentiate() requires a float as input for position") + if not isinstance(order, int): + raise ValueError("differentiate() requires an int as input for order") + d = Dual(position, 1) + result = func(d) + if order == 0: + return result.real + return result.duals[order - 1] * factorial(order) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + + def f(y): + return y**2 * y**4 + + print(differentiate(f, 9, 2)) From cfbbfd9896cc96379f7374a68ff04b245bb3527c Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Thu, 25 May 2023 11:56:23 +0100 Subject: [PATCH 666/726] Merge and add benchmarks to palindrome algorithms in the strings/ directory (#8749) * refactor: Merge and add benchmarks to palindrome * updating DIRECTORY.md * chore: Fix failing tests * Update strings/palindrome.py Co-authored-by: Christian Clauss * Update palindrome.py --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss --- DIRECTORY.md | 1 - strings/is_palindrome.py | 41 ---------------------------------------- strings/palindrome.py | 40 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 39 insertions(+), 43 deletions(-) delete mode 100644 strings/is_palindrome.py diff --git a/DIRECTORY.md b/DIRECTORY.md index a75723369..fe4baac86 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -1156,7 +1156,6 @@ * [Indian Phone Validator](strings/indian_phone_validator.py) * [Is Contains Unique Chars](strings/is_contains_unique_chars.py) * [Is Isogram](strings/is_isogram.py) - * [Is Palindrome](strings/is_palindrome.py) * [Is Pangram](strings/is_pangram.py) * [Is Spain National Id](strings/is_spain_national_id.py) * [Is Srilankan Phone Number](strings/is_srilankan_phone_number.py) diff --git a/strings/is_palindrome.py b/strings/is_palindrome.py deleted file mode 100644 index 406aa2e8d..000000000 --- a/strings/is_palindrome.py +++ /dev/null @@ -1,41 +0,0 @@ -def is_palindrome(s: str) -> bool: - """ - Determine if the string s is a palindrome. - - >>> is_palindrome("A man, A plan, A canal -- Panama!") - True - >>> is_palindrome("Hello") - False - >>> is_palindrome("Able was I ere I saw Elba") - True - >>> is_palindrome("racecar") - True - >>> is_palindrome("Mr. Owl ate my metal worm?") - True - """ - # Since punctuation, capitalization, and spaces are often ignored while checking - # palindromes, we first remove them from our string. - s = "".join(character for character in s.lower() if character.isalnum()) - # return s == s[::-1] the slicing method - # uses extra spaces we can - # better with iteration method. - - end = len(s) // 2 - n = len(s) - - # We need to traverse till half of the length of string - # as we can get access of the i'th last element from - # i'th index. - # eg: [0,1,2,3,4,5] => 4th index can be accessed - # with the help of 1st index (i==n-i-1) - # where n is length of string - - return all(s[i] == s[n - i - 1] for i in range(end)) - - -if __name__ == "__main__": - s = input("Please enter a string to see if it is a palindrome: ") - if is_palindrome(s): - print(f"'{s}' is a palindrome.") - else: - print(f"'{s}' is not a palindrome.") diff --git a/strings/palindrome.py b/strings/palindrome.py index dd1fe316f..bfdb3ddcf 100644 --- a/strings/palindrome.py +++ b/strings/palindrome.py @@ -1,5 +1,7 @@ # Algorithms to determine if a string is palindrome +from timeit import timeit + test_data = { "MALAYALAM": True, "String": False, @@ -33,6 +35,25 @@ def is_palindrome(s: str) -> bool: return True +def is_palindrome_traversal(s: str) -> bool: + """ + Return True if s is a palindrome otherwise return False. + + >>> all(is_palindrome_traversal(key) is value for key, value in test_data.items()) + True + """ + end = len(s) // 2 + n = len(s) + + # We need to traverse till half of the length of string + # as we can get access of the i'th last element from + # i'th index. + # eg: [0,1,2,3,4,5] => 4th index can be accessed + # with the help of 1st index (i==n-i-1) + # where n is length of string + return all(s[i] == s[n - i - 1] for i in range(end)) + + def is_palindrome_recursive(s: str) -> bool: """ Return True if s is a palindrome otherwise return False. @@ -40,7 +61,7 @@ def is_palindrome_recursive(s: str) -> bool: >>> all(is_palindrome_recursive(key) is value for key, value in test_data.items()) True """ - if len(s) <= 1: + if len(s) <= 2: return True if s[0] == s[len(s) - 1]: return is_palindrome_recursive(s[1:-1]) @@ -58,9 +79,26 @@ def is_palindrome_slice(s: str) -> bool: return s == s[::-1] +def benchmark_function(name: str) -> None: + stmt = f"all({name}(key) is value for key, value in test_data.items())" + setup = f"from __main__ import test_data, {name}" + number = 500000 + result = timeit(stmt=stmt, setup=setup, number=number) + print(f"{name:<35} finished {number:,} runs in {result:.5f} seconds") + + if __name__ == "__main__": for key, value in test_data.items(): assert is_palindrome(key) is is_palindrome_recursive(key) assert is_palindrome(key) is is_palindrome_slice(key) print(f"{key:21} {value}") print("a man a plan a canal panama") + + # finished 500,000 runs in 0.46793 seconds + benchmark_function("is_palindrome_slice") + # finished 500,000 runs in 0.85234 seconds + benchmark_function("is_palindrome") + # finished 500,000 runs in 1.32028 seconds + benchmark_function("is_palindrome_recursive") + # finished 500,000 runs in 2.08679 seconds + benchmark_function("is_palindrome_traversal") From a17791d022bdc942c8badabc52307c354069a7ae Mon Sep 17 00:00:00 2001 From: Juyoung Kim <61103343+JadeKim042386@users.noreply.github.com> Date: Thu, 25 May 2023 21:54:18 +0900 Subject: [PATCH 667/726] fix: graphs/greedy_best_first typo (#8766) #8764 --- graphs/greedy_best_first.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graphs/greedy_best_first.py b/graphs/greedy_best_first.py index d49e65b9d..35f7ca9fe 100644 --- a/graphs/greedy_best_first.py +++ b/graphs/greedy_best_first.py @@ -58,8 +58,8 @@ class Node: The heuristic here is the Manhattan Distance Could elaborate to offer more than one choice """ - dy = abs(self.pos_x - self.goal_x) - dx = abs(self.pos_y - self.goal_y) + dx = abs(self.pos_x - self.goal_x) + dy = abs(self.pos_y - self.goal_y) return dx + dy def __lt__(self, other) -> bool: From dd3b499bfa972507759d0705b77e2e1946f42596 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Fri, 26 May 2023 08:50:33 +0200 Subject: [PATCH 668/726] Rename is_palindrome.py to is_int_palindrome.py (#8768) * Rename is_palindrome.py to is_int_palindrome.py * updating DIRECTORY.md --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 2 +- maths/{is_palindrome.py => is_int_palindrome.py} | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) rename maths/{is_palindrome.py => is_int_palindrome.py} (67%) diff --git a/DIRECTORY.md b/DIRECTORY.md index fe4baac86..11ff93c91 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -577,8 +577,8 @@ * [Hardy Ramanujanalgo](maths/hardy_ramanujanalgo.py) * [Hexagonal Number](maths/hexagonal_number.py) * [Integration By Simpson Approx](maths/integration_by_simpson_approx.py) + * [Is Int Palindrome](maths/is_int_palindrome.py) * [Is Ip V4 Address Valid](maths/is_ip_v4_address_valid.py) - * [Is Palindrome](maths/is_palindrome.py) * [Is Square Free](maths/is_square_free.py) * [Jaccard Similarity](maths/jaccard_similarity.py) * [Juggler Sequence](maths/juggler_sequence.py) diff --git a/maths/is_palindrome.py b/maths/is_int_palindrome.py similarity index 67% rename from maths/is_palindrome.py rename to maths/is_int_palindrome.py index ba60573ab..63dc9e213 100644 --- a/maths/is_palindrome.py +++ b/maths/is_int_palindrome.py @@ -1,19 +1,19 @@ -def is_palindrome(num: int) -> bool: +def is_int_palindrome(num: int) -> bool: """ Returns whether `num` is a palindrome or not (see for reference https://en.wikipedia.org/wiki/Palindromic_number). - >>> is_palindrome(-121) + >>> is_int_palindrome(-121) False - >>> is_palindrome(0) + >>> is_int_palindrome(0) True - >>> is_palindrome(10) + >>> is_int_palindrome(10) False - >>> is_palindrome(11) + >>> is_int_palindrome(11) True - >>> is_palindrome(101) + >>> is_int_palindrome(101) True - >>> is_palindrome(120) + >>> is_int_palindrome(120) False """ if num < 0: From 4b79d771cd81a820c195e62430100c416a1618ea Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Fri, 26 May 2023 09:34:17 +0200 Subject: [PATCH 669/726] Add more ruff rules (#8767) * Add more ruff rules * Add more ruff rules * pre-commit: Update ruff v0.0.269 -> v0.0.270 * Apply suggestions from code review * Fix doctest * Fix doctest (ignore whitespace) * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Dhruv Manilawala Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- .../jacobi_iteration_method.py | 30 ++-- arithmetic_analysis/lu_decomposition.py | 5 +- audio_filters/iir_filter.py | 14 +- backtracking/knight_tour.py | 3 +- bit_manipulation/reverse_bits.py | 3 +- ciphers/base64.py | 12 +- ciphers/beaufort_cipher.py | 2 +- ciphers/cryptomath_module.py | 3 +- ciphers/enigma_machine2.py | 30 ++-- ciphers/hill_cipher.py | 7 +- .../astronomical_length_scale_conversion.py | 6 +- conversions/length_conversion.py | 6 +- conversions/speed_conversions.py | 3 +- conversions/weight_conversion.py | 3 +- .../binary_search_tree_recursive.py | 6 +- .../binary_tree/binary_tree_mirror.py | 3 +- data_structures/disjoint_set/disjoint_set.py | 3 +- .../linked_list/circular_linked_list.py | 8 +- .../linked_list/doubly_linked_list.py | 4 +- .../linked_list/singly_linked_list.py | 4 +- data_structures/stacks/stack.py | 6 +- digital_image_processing/dithering/burkes.py | 3 +- divide_and_conquer/convex_hull.py | 8 +- dynamic_programming/knapsack.py | 15 +- dynamic_programming/minimum_steps_to_one.py | 3 +- dynamic_programming/rod_cutting.py | 10 +- dynamic_programming/viterbi.py | 17 ++- electronics/resistor_equivalence.py | 6 +- genetic_algorithm/basic_string.py | 8 +- graphics/vector3_for_2d_rendering.py | 8 +- graphs/breadth_first_search_shortest_path.py | 3 +- linear_algebra/src/schur_complement.py | 14 +- machine_learning/similarity_search.py | 21 +-- machine_learning/support_vector_machines.py | 3 +- maths/3n_plus_1.py | 6 +- maths/automorphic_number.py | 3 +- maths/catalan_number.py | 6 +- .../dual_number_automatic_differentiation.py | 4 +- maths/hexagonal_number.py | 3 +- maths/juggler_sequence.py | 6 +- maths/liouville_lambda.py | 3 +- maths/manhattan_distance.py | 18 +-- maths/pronic_number.py | 3 +- maths/proth_number.py | 6 +- maths/radix2_fft.py | 2 +- maths/sieve_of_eratosthenes.py | 3 +- maths/sylvester_sequence.py | 3 +- maths/twin_prime.py | 3 +- matrix/matrix_operation.py | 12 +- matrix/sherman_morrison.py | 3 +- neural_network/input_data.py | 12 +- other/nested_brackets.py | 2 +- other/scoring_algorithm.py | 3 +- project_euler/problem_054/sol1.py | 6 +- project_euler/problem_068/sol1.py | 3 +- project_euler/problem_131/sol1.py | 5 +- pyproject.toml | 139 +++++++++++++----- scripts/build_directory_md.py | 2 +- sorts/dutch_national_flag_sort.py | 5 +- strings/barcode_validator.py | 3 +- strings/capitalize.py | 2 +- strings/is_spain_national_id.py | 3 +- strings/snake_case_to_camel_pascal_case.py | 8 +- web_programming/reddit.py | 3 +- web_programming/search_books_by_isbn.py | 3 +- web_programming/slack_message.py | 7 +- 67 files changed, 349 insertions(+), 223 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bd5bca8f0..4c70ae219 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.269 + rev: v0.0.270 hooks: - id: ruff diff --git a/arithmetic_analysis/jacobi_iteration_method.py b/arithmetic_analysis/jacobi_iteration_method.py index fe506a94a..17edf4bf4 100644 --- a/arithmetic_analysis/jacobi_iteration_method.py +++ b/arithmetic_analysis/jacobi_iteration_method.py @@ -49,7 +49,9 @@ def jacobi_iteration_method( >>> constant = np.array([[2], [-6]]) >>> init_val = [0.5, -0.5, -0.5] >>> iterations = 3 - >>> jacobi_iteration_method(coefficient, constant, init_val, iterations) + >>> jacobi_iteration_method( + ... coefficient, constant, init_val, iterations + ... ) # doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): ... ValueError: Coefficient and constant matrices dimensions must be nxn and nx1 but @@ -59,7 +61,9 @@ def jacobi_iteration_method( >>> constant = np.array([[2], [-6], [-4]]) >>> init_val = [0.5, -0.5] >>> iterations = 3 - >>> jacobi_iteration_method(coefficient, constant, init_val, iterations) + >>> jacobi_iteration_method( + ... coefficient, constant, init_val, iterations + ... ) # doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): ... ValueError: Number of initial values must be equal to number of rows in coefficient @@ -79,24 +83,26 @@ def jacobi_iteration_method( rows2, cols2 = constant_matrix.shape if rows1 != cols1: - raise ValueError( - f"Coefficient matrix dimensions must be nxn but received {rows1}x{cols1}" - ) + msg = f"Coefficient matrix dimensions must be nxn but received {rows1}x{cols1}" + raise ValueError(msg) if cols2 != 1: - raise ValueError(f"Constant matrix must be nx1 but received {rows2}x{cols2}") + msg = f"Constant matrix must be nx1 but received {rows2}x{cols2}" + raise ValueError(msg) if rows1 != rows2: - raise ValueError( - f"""Coefficient and constant matrices dimensions must be nxn and nx1 but - received {rows1}x{cols1} and {rows2}x{cols2}""" + msg = ( + "Coefficient and constant matrices dimensions must be nxn and nx1 but " + f"received {rows1}x{cols1} and {rows2}x{cols2}" ) + raise ValueError(msg) if len(init_val) != rows1: - raise ValueError( - f"""Number of initial values must be equal to number of rows in coefficient - matrix but received {len(init_val)} and {rows1}""" + msg = ( + "Number of initial values must be equal to number of rows in coefficient " + f"matrix but received {len(init_val)} and {rows1}" ) + raise ValueError(msg) if iterations <= 0: raise ValueError("Iterations must be at least 1") diff --git a/arithmetic_analysis/lu_decomposition.py b/arithmetic_analysis/lu_decomposition.py index 941c1dadf..eaabce544 100644 --- a/arithmetic_analysis/lu_decomposition.py +++ b/arithmetic_analysis/lu_decomposition.py @@ -80,10 +80,11 @@ def lower_upper_decomposition(table: np.ndarray) -> tuple[np.ndarray, np.ndarray # Ensure that table is a square array rows, columns = np.shape(table) if rows != columns: - raise ValueError( - f"'table' has to be of square shaped array but got a " + msg = ( + "'table' has to be of square shaped array but got a " f"{rows}x{columns} array:\n{table}" ) + raise ValueError(msg) lower = np.zeros((rows, columns)) upper = np.zeros((rows, columns)) diff --git a/audio_filters/iir_filter.py b/audio_filters/iir_filter.py index bd448175f..f3c1ad43b 100644 --- a/audio_filters/iir_filter.py +++ b/audio_filters/iir_filter.py @@ -50,16 +50,18 @@ class IIRFilter: a_coeffs = [1.0, *a_coeffs] if len(a_coeffs) != self.order + 1: - raise ValueError( - f"Expected a_coeffs to have {self.order + 1} elements for {self.order}" - f"-order filter, got {len(a_coeffs)}" + msg = ( + f"Expected a_coeffs to have {self.order + 1} elements " + f"for {self.order}-order filter, got {len(a_coeffs)}" ) + raise ValueError(msg) if len(b_coeffs) != self.order + 1: - raise ValueError( - f"Expected b_coeffs to have {self.order + 1} elements for {self.order}" - f"-order filter, got {len(a_coeffs)}" + msg = ( + f"Expected b_coeffs to have {self.order + 1} elements " + f"for {self.order}-order filter, got {len(a_coeffs)}" ) + raise ValueError(msg) self.a_coeffs = a_coeffs self.b_coeffs = b_coeffs diff --git a/backtracking/knight_tour.py b/backtracking/knight_tour.py index bb650ece3..cc88307b7 100644 --- a/backtracking/knight_tour.py +++ b/backtracking/knight_tour.py @@ -91,7 +91,8 @@ def open_knight_tour(n: int) -> list[list[int]]: return board board[i][j] = 0 - raise ValueError(f"Open Kight Tour cannot be performed on a board of size {n}") + msg = f"Open Kight Tour cannot be performed on a board of size {n}" + raise ValueError(msg) if __name__ == "__main__": diff --git a/bit_manipulation/reverse_bits.py b/bit_manipulation/reverse_bits.py index 55608ae12..a8c77c11b 100644 --- a/bit_manipulation/reverse_bits.py +++ b/bit_manipulation/reverse_bits.py @@ -14,10 +14,11 @@ def get_reverse_bit_string(number: int) -> str: TypeError: operation can not be conducted on a object of type str """ if not isinstance(number, int): - raise TypeError( + msg = ( "operation can not be conducted on a object of type " f"{type(number).__name__}" ) + raise TypeError(msg) bit_string = "" for _ in range(0, 32): bit_string += str(number % 2) diff --git a/ciphers/base64.py b/ciphers/base64.py index 38a952acc..2b950b1be 100644 --- a/ciphers/base64.py +++ b/ciphers/base64.py @@ -34,9 +34,8 @@ def base64_encode(data: bytes) -> bytes: """ # Make sure the supplied data is a bytes-like object if not isinstance(data, bytes): - raise TypeError( - f"a bytes-like object is required, not '{data.__class__.__name__}'" - ) + msg = f"a bytes-like object is required, not '{data.__class__.__name__}'" + raise TypeError(msg) binary_stream = "".join(bin(byte)[2:].zfill(8) for byte in data) @@ -88,10 +87,11 @@ def base64_decode(encoded_data: str) -> bytes: """ # Make sure encoded_data is either a string or a bytes-like object if not isinstance(encoded_data, bytes) and not isinstance(encoded_data, str): - raise TypeError( - "argument should be a bytes-like object or ASCII string, not " - f"'{encoded_data.__class__.__name__}'" + msg = ( + "argument should be a bytes-like object or ASCII string, " + f"not '{encoded_data.__class__.__name__}'" ) + raise TypeError(msg) # In case encoded_data is a bytes-like object, make sure it contains only # ASCII characters so we convert it to a string object diff --git a/ciphers/beaufort_cipher.py b/ciphers/beaufort_cipher.py index 8eae847a7..788fc72b8 100644 --- a/ciphers/beaufort_cipher.py +++ b/ciphers/beaufort_cipher.py @@ -5,7 +5,7 @@ Author: Mohit Radadiya from string import ascii_uppercase dict1 = {char: i for i, char in enumerate(ascii_uppercase)} -dict2 = {i: char for i, char in enumerate(ascii_uppercase)} +dict2 = dict(enumerate(ascii_uppercase)) # This function generates the key in diff --git a/ciphers/cryptomath_module.py b/ciphers/cryptomath_module.py index be8764ff3..6f15f7b73 100644 --- a/ciphers/cryptomath_module.py +++ b/ciphers/cryptomath_module.py @@ -6,7 +6,8 @@ def gcd(a: int, b: int) -> int: def find_mod_inverse(a: int, m: int) -> int: if gcd(a, m) != 1: - raise ValueError(f"mod inverse of {a!r} and {m!r} does not exist") + msg = f"mod inverse of {a!r} and {m!r} does not exist" + raise ValueError(msg) u1, u2, u3 = 1, 0, a v1, v2, v3 = 0, 1, m while v3 != 0: diff --git a/ciphers/enigma_machine2.py b/ciphers/enigma_machine2.py index 07d21893f..ec0d44e4a 100644 --- a/ciphers/enigma_machine2.py +++ b/ciphers/enigma_machine2.py @@ -87,22 +87,20 @@ def _validator( # Checks if there are 3 unique rotors if (unique_rotsel := len(set(rotsel))) < 3: - raise Exception(f"Please use 3 unique rotors (not {unique_rotsel})") + msg = f"Please use 3 unique rotors (not {unique_rotsel})" + raise Exception(msg) # Checks if rotor positions are valid rotorpos1, rotorpos2, rotorpos3 = rotpos if not 0 < rotorpos1 <= len(abc): - raise ValueError( - "First rotor position is not within range of 1..26 (" f"{rotorpos1}" - ) + msg = f"First rotor position is not within range of 1..26 ({rotorpos1}" + raise ValueError(msg) if not 0 < rotorpos2 <= len(abc): - raise ValueError( - "Second rotor position is not within range of 1..26 (" f"{rotorpos2})" - ) + msg = f"Second rotor position is not within range of 1..26 ({rotorpos2})" + raise ValueError(msg) if not 0 < rotorpos3 <= len(abc): - raise ValueError( - "Third rotor position is not within range of 1..26 (" f"{rotorpos3})" - ) + msg = f"Third rotor position is not within range of 1..26 ({rotorpos3})" + raise ValueError(msg) # Validates string and returns dict pbdict = _plugboard(pb) @@ -130,9 +128,11 @@ def _plugboard(pbstring: str) -> dict[str, str]: # a) is type string # b) has even length (so pairs can be made) if not isinstance(pbstring, str): - raise TypeError(f"Plugboard setting isn't type string ({type(pbstring)})") + msg = f"Plugboard setting isn't type string ({type(pbstring)})" + raise TypeError(msg) elif len(pbstring) % 2 != 0: - raise Exception(f"Odd number of symbols ({len(pbstring)})") + msg = f"Odd number of symbols ({len(pbstring)})" + raise Exception(msg) elif pbstring == "": return {} @@ -142,9 +142,11 @@ def _plugboard(pbstring: str) -> dict[str, str]: tmppbl = set() for i in pbstring: if i not in abc: - raise Exception(f"'{i}' not in list of symbols") + msg = f"'{i}' not in list of symbols" + raise Exception(msg) elif i in tmppbl: - raise Exception(f"Duplicate symbol ({i})") + msg = f"Duplicate symbol ({i})" + raise Exception(msg) else: tmppbl.add(i) del tmppbl diff --git a/ciphers/hill_cipher.py b/ciphers/hill_cipher.py index f646d567b..b4424e822 100644 --- a/ciphers/hill_cipher.py +++ b/ciphers/hill_cipher.py @@ -104,10 +104,11 @@ class HillCipher: req_l = len(self.key_string) if greatest_common_divisor(det, len(self.key_string)) != 1: - raise ValueError( - f"determinant modular {req_l} of encryption key({det}) is not co prime " - f"w.r.t {req_l}.\nTry another key." + msg = ( + f"determinant modular {req_l} of encryption key({det}) " + f"is not co prime w.r.t {req_l}.\nTry another key." ) + raise ValueError(msg) def process_text(self, text: str) -> str: """ diff --git a/conversions/astronomical_length_scale_conversion.py b/conversions/astronomical_length_scale_conversion.py index 804d82487..0f4136449 100644 --- a/conversions/astronomical_length_scale_conversion.py +++ b/conversions/astronomical_length_scale_conversion.py @@ -77,15 +77,17 @@ def length_conversion(value: float, from_type: str, to_type: str) -> float: to_sanitized = UNIT_SYMBOL.get(to_sanitized, to_sanitized) if from_sanitized not in METRIC_CONVERSION: - raise ValueError( + msg = ( f"Invalid 'from_type' value: {from_type!r}.\n" f"Conversion abbreviations are: {', '.join(METRIC_CONVERSION)}" ) + raise ValueError(msg) if to_sanitized not in METRIC_CONVERSION: - raise ValueError( + msg = ( f"Invalid 'to_type' value: {to_type!r}.\n" f"Conversion abbreviations are: {', '.join(METRIC_CONVERSION)}" ) + raise ValueError(msg) from_exponent = METRIC_CONVERSION[from_sanitized] to_exponent = METRIC_CONVERSION[to_sanitized] exponent = 1 diff --git a/conversions/length_conversion.py b/conversions/length_conversion.py index 790d9c116..d8f395152 100644 --- a/conversions/length_conversion.py +++ b/conversions/length_conversion.py @@ -104,15 +104,17 @@ def length_conversion(value: float, from_type: str, to_type: str) -> float: new_to = to_type.lower().rstrip("s") new_to = TYPE_CONVERSION.get(new_to, new_to) if new_from not in METRIC_CONVERSION: - raise ValueError( + msg = ( f"Invalid 'from_type' value: {from_type!r}.\n" f"Conversion abbreviations are: {', '.join(METRIC_CONVERSION)}" ) + raise ValueError(msg) if new_to not in METRIC_CONVERSION: - raise ValueError( + msg = ( f"Invalid 'to_type' value: {to_type!r}.\n" f"Conversion abbreviations are: {', '.join(METRIC_CONVERSION)}" ) + raise ValueError(msg) return value * METRIC_CONVERSION[new_from].from_ * METRIC_CONVERSION[new_to].to diff --git a/conversions/speed_conversions.py b/conversions/speed_conversions.py index 62da9e137..ba497119d 100644 --- a/conversions/speed_conversions.py +++ b/conversions/speed_conversions.py @@ -57,10 +57,11 @@ def convert_speed(speed: float, unit_from: str, unit_to: str) -> float: 115.078 """ if unit_to not in speed_chart or unit_from not in speed_chart_inverse: - raise ValueError( + msg = ( f"Incorrect 'from_type' or 'to_type' value: {unit_from!r}, {unit_to!r}\n" f"Valid values are: {', '.join(speed_chart_inverse)}" ) + raise ValueError(msg) return round(speed * speed_chart[unit_from] * speed_chart_inverse[unit_to], 3) diff --git a/conversions/weight_conversion.py b/conversions/weight_conversion.py index 5c032a497..e8326e0b6 100644 --- a/conversions/weight_conversion.py +++ b/conversions/weight_conversion.py @@ -299,10 +299,11 @@ def weight_conversion(from_type: str, to_type: str, value: float) -> float: 1.999999998903455 """ if to_type not in KILOGRAM_CHART or from_type not in WEIGHT_TYPE_CHART: - raise ValueError( + msg = ( f"Invalid 'from_type' or 'to_type' value: {from_type!r}, {to_type!r}\n" f"Supported values are: {', '.join(WEIGHT_TYPE_CHART)}" ) + raise ValueError(msg) return value * KILOGRAM_CHART[to_type] * WEIGHT_TYPE_CHART[from_type] diff --git a/data_structures/binary_tree/binary_search_tree_recursive.py b/data_structures/binary_tree/binary_search_tree_recursive.py index 97eb8e25b..b5b983b9b 100644 --- a/data_structures/binary_tree/binary_search_tree_recursive.py +++ b/data_structures/binary_tree/binary_search_tree_recursive.py @@ -77,7 +77,8 @@ class BinarySearchTree: elif label > node.label: node.right = self._put(node.right, label, node) else: - raise Exception(f"Node with label {label} already exists") + msg = f"Node with label {label} already exists" + raise Exception(msg) return node @@ -100,7 +101,8 @@ class BinarySearchTree: def _search(self, node: Node | None, label: int) -> Node: if node is None: - raise Exception(f"Node with label {label} does not exist") + msg = f"Node with label {label} does not exist" + raise Exception(msg) else: if label < node.label: node = self._search(node.left, label) diff --git a/data_structures/binary_tree/binary_tree_mirror.py b/data_structures/binary_tree/binary_tree_mirror.py index 1ef950ad6..b8548f4ec 100644 --- a/data_structures/binary_tree/binary_tree_mirror.py +++ b/data_structures/binary_tree/binary_tree_mirror.py @@ -31,7 +31,8 @@ def binary_tree_mirror(binary_tree: dict, root: int = 1) -> dict: if not binary_tree: raise ValueError("binary tree cannot be empty") if root not in binary_tree: - raise ValueError(f"root {root} is not present in the binary_tree") + msg = f"root {root} is not present in the binary_tree" + raise ValueError(msg) binary_tree_mirror_dictionary = dict(binary_tree) binary_tree_mirror_dict(binary_tree_mirror_dictionary, root) return binary_tree_mirror_dictionary diff --git a/data_structures/disjoint_set/disjoint_set.py b/data_structures/disjoint_set/disjoint_set.py index f8500bf2c..12dafb2d9 100644 --- a/data_structures/disjoint_set/disjoint_set.py +++ b/data_structures/disjoint_set/disjoint_set.py @@ -56,7 +56,8 @@ def find_python_set(node: Node) -> set: for s in sets: if node.data in s: return s - raise ValueError(f"{node.data} is not in {sets}") + msg = f"{node.data} is not in {sets}" + raise ValueError(msg) def test_disjoint_set() -> None: diff --git a/data_structures/linked_list/circular_linked_list.py b/data_structures/linked_list/circular_linked_list.py index 9092fb29e..325d91026 100644 --- a/data_structures/linked_list/circular_linked_list.py +++ b/data_structures/linked_list/circular_linked_list.py @@ -94,25 +94,25 @@ def test_circular_linked_list() -> None: try: circular_linked_list.delete_front() - raise AssertionError() # This should not happen + raise AssertionError # This should not happen except IndexError: assert True # This should happen try: circular_linked_list.delete_tail() - raise AssertionError() # This should not happen + raise AssertionError # This should not happen except IndexError: assert True # This should happen try: circular_linked_list.delete_nth(-1) - raise AssertionError() + raise AssertionError except IndexError: assert True try: circular_linked_list.delete_nth(0) - raise AssertionError() + raise AssertionError except IndexError: assert True diff --git a/data_structures/linked_list/doubly_linked_list.py b/data_structures/linked_list/doubly_linked_list.py index 69763d12d..1a6c48191 100644 --- a/data_structures/linked_list/doubly_linked_list.py +++ b/data_structures/linked_list/doubly_linked_list.py @@ -198,13 +198,13 @@ def test_doubly_linked_list() -> None: try: linked_list.delete_head() - raise AssertionError() # This should not happen. + raise AssertionError # This should not happen. except IndexError: assert True # This should happen. try: linked_list.delete_tail() - raise AssertionError() # This should not happen. + raise AssertionError # This should not happen. except IndexError: assert True # This should happen. diff --git a/data_structures/linked_list/singly_linked_list.py b/data_structures/linked_list/singly_linked_list.py index a8f9e8ebb..890e21c9b 100644 --- a/data_structures/linked_list/singly_linked_list.py +++ b/data_structures/linked_list/singly_linked_list.py @@ -353,13 +353,13 @@ def test_singly_linked_list() -> None: try: linked_list.delete_head() - raise AssertionError() # This should not happen. + raise AssertionError # This should not happen. except IndexError: assert True # This should happen. try: linked_list.delete_tail() - raise AssertionError() # This should not happen. + raise AssertionError # This should not happen. except IndexError: assert True # This should happen. diff --git a/data_structures/stacks/stack.py b/data_structures/stacks/stack.py index 55d424d50..a14f4648a 100644 --- a/data_structures/stacks/stack.py +++ b/data_structures/stacks/stack.py @@ -92,13 +92,13 @@ def test_stack() -> None: try: _ = stack.pop() - raise AssertionError() # This should not happen + raise AssertionError # This should not happen except StackUnderflowError: assert True # This should happen try: _ = stack.peek() - raise AssertionError() # This should not happen + raise AssertionError # This should not happen except StackUnderflowError: assert True # This should happen @@ -118,7 +118,7 @@ def test_stack() -> None: try: stack.push(200) - raise AssertionError() # This should not happen + raise AssertionError # This should not happen except StackOverflowError: assert True # This should happen diff --git a/digital_image_processing/dithering/burkes.py b/digital_image_processing/dithering/burkes.py index 2bf0bbe03..0804104ab 100644 --- a/digital_image_processing/dithering/burkes.py +++ b/digital_image_processing/dithering/burkes.py @@ -21,7 +21,8 @@ class Burkes: self.max_threshold = int(self.get_greyscale(255, 255, 255)) if not self.min_threshold < threshold < self.max_threshold: - raise ValueError(f"Factor value should be from 0 to {self.max_threshold}") + msg = f"Factor value should be from 0 to {self.max_threshold}" + raise ValueError(msg) self.input_img = input_img self.threshold = threshold diff --git a/divide_and_conquer/convex_hull.py b/divide_and_conquer/convex_hull.py index 39e78be04..1ad933417 100644 --- a/divide_and_conquer/convex_hull.py +++ b/divide_and_conquer/convex_hull.py @@ -174,12 +174,12 @@ def _validate_input(points: list[Point] | list[list[float]]) -> list[Point]: """ if not hasattr(points, "__iter__"): - raise ValueError( - f"Expecting an iterable object but got an non-iterable type {points}" - ) + msg = f"Expecting an iterable object but got an non-iterable type {points}" + raise ValueError(msg) if not points: - raise ValueError(f"Expecting a list of points but got {points}") + msg = f"Expecting a list of points but got {points}" + raise ValueError(msg) return _construct_points(points) diff --git a/dynamic_programming/knapsack.py b/dynamic_programming/knapsack.py index b12d30313..489b5ada4 100644 --- a/dynamic_programming/knapsack.py +++ b/dynamic_programming/knapsack.py @@ -78,17 +78,18 @@ def knapsack_with_example_solution(w: int, wt: list, val: list): num_items = len(wt) if num_items != len(val): - raise ValueError( - "The number of weights must be the " - "same as the number of values.\nBut " - f"got {num_items} weights and {len(val)} values" + msg = ( + "The number of weights must be the same as the number of values.\n" + f"But got {num_items} weights and {len(val)} values" ) + raise ValueError(msg) for i in range(num_items): if not isinstance(wt[i], int): - raise TypeError( - "All weights must be integers but " - f"got weight of type {type(wt[i])} at index {i}" + msg = ( + "All weights must be integers but got weight of " + f"type {type(wt[i])} at index {i}" ) + raise TypeError(msg) optimal_val, dp_table = knapsack(w, wt, val, num_items) example_optional_set: set = set() diff --git a/dynamic_programming/minimum_steps_to_one.py b/dynamic_programming/minimum_steps_to_one.py index f4eb7033d..8785027fb 100644 --- a/dynamic_programming/minimum_steps_to_one.py +++ b/dynamic_programming/minimum_steps_to_one.py @@ -42,7 +42,8 @@ def min_steps_to_one(number: int) -> int: """ if number <= 0: - raise ValueError(f"n must be greater than 0. Got n = {number}") + msg = f"n must be greater than 0. Got n = {number}" + raise ValueError(msg) table = [number + 1] * (number + 1) diff --git a/dynamic_programming/rod_cutting.py b/dynamic_programming/rod_cutting.py index 79104d8f4..f80fa440a 100644 --- a/dynamic_programming/rod_cutting.py +++ b/dynamic_programming/rod_cutting.py @@ -177,13 +177,15 @@ def _enforce_args(n: int, prices: list): the rod """ if n < 0: - raise ValueError(f"n must be greater than or equal to 0. Got n = {n}") + msg = f"n must be greater than or equal to 0. Got n = {n}" + raise ValueError(msg) if n > len(prices): - raise ValueError( - "Each integral piece of rod must have a corresponding " - f"price. Got n = {n} but length of prices = {len(prices)}" + msg = ( + "Each integral piece of rod must have a corresponding price. " + f"Got n = {n} but length of prices = {len(prices)}" ) + raise ValueError(msg) def main(): diff --git a/dynamic_programming/viterbi.py b/dynamic_programming/viterbi.py index 93ab845e2..764d45dc2 100644 --- a/dynamic_programming/viterbi.py +++ b/dynamic_programming/viterbi.py @@ -297,11 +297,13 @@ def _validate_list(_object: Any, var_name: str) -> None: """ if not isinstance(_object, list): - raise ValueError(f"{var_name} must be a list") + msg = f"{var_name} must be a list" + raise ValueError(msg) else: for x in _object: if not isinstance(x, str): - raise ValueError(f"{var_name} must be a list of strings") + msg = f"{var_name} must be a list of strings" + raise ValueError(msg) def _validate_dicts( @@ -384,14 +386,15 @@ def _validate_dict( ValueError: mock_name nested dictionary all values must be float """ if not isinstance(_object, dict): - raise ValueError(f"{var_name} must be a dict") + msg = f"{var_name} must be a dict" + raise ValueError(msg) if not all(isinstance(x, str) for x in _object): - raise ValueError(f"{var_name} all keys must be strings") + msg = f"{var_name} all keys must be strings" + raise ValueError(msg) if not all(isinstance(x, value_type) for x in _object.values()): nested_text = "nested dictionary " if nested else "" - raise ValueError( - f"{var_name} {nested_text}all values must be {value_type.__name__}" - ) + msg = f"{var_name} {nested_text}all values must be {value_type.__name__}" + raise ValueError(msg) if __name__ == "__main__": diff --git a/electronics/resistor_equivalence.py b/electronics/resistor_equivalence.py index 7142f838a..55e7f2d6b 100644 --- a/electronics/resistor_equivalence.py +++ b/electronics/resistor_equivalence.py @@ -23,7 +23,8 @@ def resistor_parallel(resistors: list[float]) -> float: index = 0 for resistor in resistors: if resistor <= 0: - raise ValueError(f"Resistor at index {index} has a negative or zero value!") + msg = f"Resistor at index {index} has a negative or zero value!" + raise ValueError(msg) first_sum += 1 / float(resistor) index += 1 return 1 / first_sum @@ -47,7 +48,8 @@ def resistor_series(resistors: list[float]) -> float: for resistor in resistors: sum_r += resistor if resistor < 0: - raise ValueError(f"Resistor at index {index} has a negative value!") + msg = f"Resistor at index {index} has a negative value!" + raise ValueError(msg) index += 1 return sum_r diff --git a/genetic_algorithm/basic_string.py b/genetic_algorithm/basic_string.py index 388e7219f..089c5c99a 100644 --- a/genetic_algorithm/basic_string.py +++ b/genetic_algorithm/basic_string.py @@ -96,13 +96,13 @@ def basic(target: str, genes: list[str], debug: bool = True) -> tuple[int, int, # Verify if N_POPULATION is bigger than N_SELECTED if N_POPULATION < N_SELECTED: - raise ValueError(f"{N_POPULATION} must be bigger than {N_SELECTED}") + msg = f"{N_POPULATION} must be bigger than {N_SELECTED}" + raise ValueError(msg) # Verify that the target contains no genes besides the ones inside genes variable. not_in_genes_list = sorted({c for c in target if c not in genes}) if not_in_genes_list: - raise ValueError( - f"{not_in_genes_list} is not in genes list, evolution cannot converge" - ) + msg = f"{not_in_genes_list} is not in genes list, evolution cannot converge" + raise ValueError(msg) # Generate random starting population. population = [] diff --git a/graphics/vector3_for_2d_rendering.py b/graphics/vector3_for_2d_rendering.py index dfa22262a..a332206e6 100644 --- a/graphics/vector3_for_2d_rendering.py +++ b/graphics/vector3_for_2d_rendering.py @@ -28,9 +28,8 @@ def convert_to_2d( TypeError: Input values must either be float or int: ['1', 2, 3, 10, 10] """ if not all(isinstance(val, (float, int)) for val in locals().values()): - raise TypeError( - "Input values must either be float or int: " f"{list(locals().values())}" - ) + msg = f"Input values must either be float or int: {list(locals().values())}" + raise TypeError(msg) projected_x = ((x * distance) / (z + distance)) * scale projected_y = ((y * distance) / (z + distance)) * scale return projected_x, projected_y @@ -71,10 +70,11 @@ def rotate( input_variables = locals() del input_variables["axis"] if not all(isinstance(val, (float, int)) for val in input_variables.values()): - raise TypeError( + msg = ( "Input values except axis must either be float or int: " f"{list(input_variables.values())}" ) + raise TypeError(msg) angle = (angle % 360) / 450 * 180 / math.pi if axis == "z": new_x = x * math.cos(angle) - y * math.sin(angle) diff --git a/graphs/breadth_first_search_shortest_path.py b/graphs/breadth_first_search_shortest_path.py index cb21076f9..d489b110b 100644 --- a/graphs/breadth_first_search_shortest_path.py +++ b/graphs/breadth_first_search_shortest_path.py @@ -73,9 +73,10 @@ class Graph: target_vertex_parent = self.parent.get(target_vertex) if target_vertex_parent is None: - raise ValueError( + msg = ( f"No path from vertex: {self.source_vertex} to vertex: {target_vertex}" ) + raise ValueError(msg) return self.shortest_path(target_vertex_parent) + f"->{target_vertex}" diff --git a/linear_algebra/src/schur_complement.py b/linear_algebra/src/schur_complement.py index 3a5f4443a..750f4de5e 100644 --- a/linear_algebra/src/schur_complement.py +++ b/linear_algebra/src/schur_complement.py @@ -31,16 +31,18 @@ def schur_complement( shape_c = np.shape(mat_c) if shape_a[0] != shape_b[0]: - raise ValueError( - f"Expected the same number of rows for A and B. \ - Instead found A of size {shape_a} and B of size {shape_b}" + msg = ( + "Expected the same number of rows for A and B. " + f"Instead found A of size {shape_a} and B of size {shape_b}" ) + raise ValueError(msg) if shape_b[1] != shape_c[1]: - raise ValueError( - f"Expected the same number of columns for B and C. \ - Instead found B of size {shape_b} and C of size {shape_c}" + msg = ( + "Expected the same number of columns for B and C. " + f"Instead found B of size {shape_b} and C of size {shape_c}" ) + raise ValueError(msg) a_inv = pseudo_inv if a_inv is None: diff --git a/machine_learning/similarity_search.py b/machine_learning/similarity_search.py index 72979181f..7a23ec463 100644 --- a/machine_learning/similarity_search.py +++ b/machine_learning/similarity_search.py @@ -97,26 +97,29 @@ def similarity_search( """ if dataset.ndim != value_array.ndim: - raise ValueError( - f"Wrong input data's dimensions... dataset : {dataset.ndim}, " - f"value_array : {value_array.ndim}" + msg = ( + "Wrong input data's dimensions... " + f"dataset : {dataset.ndim}, value_array : {value_array.ndim}" ) + raise ValueError(msg) try: if dataset.shape[1] != value_array.shape[1]: - raise ValueError( - f"Wrong input data's shape... dataset : {dataset.shape[1]}, " - f"value_array : {value_array.shape[1]}" + msg = ( + "Wrong input data's shape... " + f"dataset : {dataset.shape[1]}, value_array : {value_array.shape[1]}" ) + raise ValueError(msg) except IndexError: if dataset.ndim != value_array.ndim: raise TypeError("Wrong shape") if dataset.dtype != value_array.dtype: - raise TypeError( - f"Input data have different datatype... dataset : {dataset.dtype}, " - f"value_array : {value_array.dtype}" + msg = ( + "Input data have different datatype... " + f"dataset : {dataset.dtype}, value_array : {value_array.dtype}" ) + raise TypeError(msg) answer = [] diff --git a/machine_learning/support_vector_machines.py b/machine_learning/support_vector_machines.py index df854cc85..24046115e 100644 --- a/machine_learning/support_vector_machines.py +++ b/machine_learning/support_vector_machines.py @@ -74,7 +74,8 @@ class SVC: # sklear: def_gamma = 1/(n_features * X.var()) (wiki) # previously it was 1/(n_features) else: - raise ValueError(f"Unknown kernel: {kernel}") + msg = f"Unknown kernel: {kernel}" + raise ValueError(msg) # kernels def __linear(self, vector1: ndarray, vector2: ndarray) -> float: diff --git a/maths/3n_plus_1.py b/maths/3n_plus_1.py index 59fdec48e..f9f6dfeb9 100644 --- a/maths/3n_plus_1.py +++ b/maths/3n_plus_1.py @@ -9,9 +9,11 @@ def n31(a: int) -> tuple[list[int], int]: """ if not isinstance(a, int): - raise TypeError(f"Must be int, not {type(a).__name__}") + msg = f"Must be int, not {type(a).__name__}" + raise TypeError(msg) if a < 1: - raise ValueError(f"Given integer must be positive, not {a}") + msg = f"Given integer must be positive, not {a}" + raise ValueError(msg) path = [a] while a != 1: diff --git a/maths/automorphic_number.py b/maths/automorphic_number.py index 103fc7301..8ed937563 100644 --- a/maths/automorphic_number.py +++ b/maths/automorphic_number.py @@ -40,7 +40,8 @@ def is_automorphic_number(number: int) -> bool: TypeError: Input value of [number=5.0] must be an integer """ if not isinstance(number, int): - raise TypeError(f"Input value of [number={number}] must be an integer") + msg = f"Input value of [number={number}] must be an integer" + raise TypeError(msg) if number < 0: return False number_square = number * number diff --git a/maths/catalan_number.py b/maths/catalan_number.py index 85607dc1e..20c2cfb17 100644 --- a/maths/catalan_number.py +++ b/maths/catalan_number.py @@ -31,10 +31,12 @@ def catalan(number: int) -> int: """ if not isinstance(number, int): - raise TypeError(f"Input value of [number={number}] must be an integer") + msg = f"Input value of [number={number}] must be an integer" + raise TypeError(msg) if number < 1: - raise ValueError(f"Input value of [number={number}] must be > 0") + msg = f"Input value of [number={number}] must be > 0" + raise ValueError(msg) current_number = 1 diff --git a/maths/dual_number_automatic_differentiation.py b/maths/dual_number_automatic_differentiation.py index 9aa75830c..f98997c8b 100644 --- a/maths/dual_number_automatic_differentiation.py +++ b/maths/dual_number_automatic_differentiation.py @@ -71,7 +71,7 @@ class Dual: for i in self.duals: new_duals.append(i / other) return Dual(self.real / other, new_duals) - raise ValueError() + raise ValueError def __floordiv__(self, other): if not isinstance(other, Dual): @@ -79,7 +79,7 @@ class Dual: for i in self.duals: new_duals.append(i // other) return Dual(self.real // other, new_duals) - raise ValueError() + raise ValueError def __pow__(self, n): if n < 0 or isinstance(n, float): diff --git a/maths/hexagonal_number.py b/maths/hexagonal_number.py index 28735c638..3677ab95e 100644 --- a/maths/hexagonal_number.py +++ b/maths/hexagonal_number.py @@ -36,7 +36,8 @@ def hexagonal(number: int) -> int: TypeError: Input value of [number=11.0] must be an integer """ if not isinstance(number, int): - raise TypeError(f"Input value of [number={number}] must be an integer") + msg = f"Input value of [number={number}] must be an integer" + raise TypeError(msg) if number < 1: raise ValueError("Input must be a positive integer") return number * (2 * number - 1) diff --git a/maths/juggler_sequence.py b/maths/juggler_sequence.py index 9daba8bc0..7f65d1dff 100644 --- a/maths/juggler_sequence.py +++ b/maths/juggler_sequence.py @@ -40,9 +40,11 @@ def juggler_sequence(number: int) -> list[int]: ValueError: Input value of [number=-1] must be a positive integer """ if not isinstance(number, int): - raise TypeError(f"Input value of [number={number}] must be an integer") + msg = f"Input value of [number={number}] must be an integer" + raise TypeError(msg) if number < 1: - raise ValueError(f"Input value of [number={number}] must be a positive integer") + msg = f"Input value of [number={number}] must be a positive integer" + raise ValueError(msg) sequence = [number] while number != 1: if number % 2 == 0: diff --git a/maths/liouville_lambda.py b/maths/liouville_lambda.py index 5993efa42..1ed228dd5 100644 --- a/maths/liouville_lambda.py +++ b/maths/liouville_lambda.py @@ -33,7 +33,8 @@ def liouville_lambda(number: int) -> int: TypeError: Input value of [number=11.0] must be an integer """ if not isinstance(number, int): - raise TypeError(f"Input value of [number={number}] must be an integer") + msg = f"Input value of [number={number}] must be an integer" + raise TypeError(msg) if number < 1: raise ValueError("Input must be a positive integer") return -1 if len(prime_factors(number)) % 2 else 1 diff --git a/maths/manhattan_distance.py b/maths/manhattan_distance.py index 2711d4c8c..413991468 100644 --- a/maths/manhattan_distance.py +++ b/maths/manhattan_distance.py @@ -15,15 +15,15 @@ def manhattan_distance(point_a: list, point_b: list) -> float: 9.0 >>> manhattan_distance([1,1], None) Traceback (most recent call last): - ... + ... ValueError: Missing an input >>> manhattan_distance([1,1], [2, 2, 2]) Traceback (most recent call last): - ... + ... ValueError: Both points must be in the same n-dimensional space >>> manhattan_distance([1,"one"], [2, 2, 2]) Traceback (most recent call last): - ... + ... TypeError: Expected a list of numbers as input, found str >>> manhattan_distance(1, [2, 2, 2]) Traceback (most recent call last): @@ -66,14 +66,14 @@ def _validate_point(point: list[float]) -> None: if isinstance(point, list): for item in point: if not isinstance(item, (int, float)): - raise TypeError( - f"Expected a list of numbers as input, " - f"found {type(item).__name__}" + msg = ( + "Expected a list of numbers as input, found " + f"{type(item).__name__}" ) + raise TypeError(msg) else: - raise TypeError( - f"Expected a list of numbers as input, found {type(point).__name__}" - ) + msg = f"Expected a list of numbers as input, found {type(point).__name__}" + raise TypeError(msg) else: raise ValueError("Missing an input") diff --git a/maths/pronic_number.py b/maths/pronic_number.py index 8b554dbbd..cf4d3d2eb 100644 --- a/maths/pronic_number.py +++ b/maths/pronic_number.py @@ -41,7 +41,8 @@ def is_pronic(number: int) -> bool: TypeError: Input value of [number=6.0] must be an integer """ if not isinstance(number, int): - raise TypeError(f"Input value of [number={number}] must be an integer") + msg = f"Input value of [number={number}] must be an integer" + raise TypeError(msg) if number < 0 or number % 2 == 1: return False number_sqrt = int(number**0.5) diff --git a/maths/proth_number.py b/maths/proth_number.py index ce911473a..47747ed26 100644 --- a/maths/proth_number.py +++ b/maths/proth_number.py @@ -29,10 +29,12 @@ def proth(number: int) -> int: """ if not isinstance(number, int): - raise TypeError(f"Input value of [number={number}] must be an integer") + msg = f"Input value of [number={number}] must be an integer" + raise TypeError(msg) if number < 1: - raise ValueError(f"Input value of [number={number}] must be > 0") + msg = f"Input value of [number={number}] must be > 0" + raise ValueError(msg) elif number == 1: return 3 elif number == 2: diff --git a/maths/radix2_fft.py b/maths/radix2_fft.py index af98f24f9..2c5cdc004 100644 --- a/maths/radix2_fft.py +++ b/maths/radix2_fft.py @@ -167,7 +167,7 @@ class FFT: f"{coef}*x^{i}" for coef, i in enumerate(self.product) ) - return "\n".join((a, b, c)) + return f"{a}\n{b}\n{c}" # Unit tests diff --git a/maths/sieve_of_eratosthenes.py b/maths/sieve_of_eratosthenes.py index 3cd6ce0b4..a0520aa5c 100644 --- a/maths/sieve_of_eratosthenes.py +++ b/maths/sieve_of_eratosthenes.py @@ -34,7 +34,8 @@ def prime_sieve(num: int) -> list[int]: """ if num <= 0: - raise ValueError(f"{num}: Invalid input, please enter a positive integer.") + msg = f"{num}: Invalid input, please enter a positive integer." + raise ValueError(msg) sieve = [True] * (num + 1) prime = [] diff --git a/maths/sylvester_sequence.py b/maths/sylvester_sequence.py index 114c9dd58..607424c6a 100644 --- a/maths/sylvester_sequence.py +++ b/maths/sylvester_sequence.py @@ -31,7 +31,8 @@ def sylvester(number: int) -> int: if number == 1: return 2 elif number < 1: - raise ValueError(f"The input value of [n={number}] has to be > 0") + msg = f"The input value of [n={number}] has to be > 0" + raise ValueError(msg) else: num = sylvester(number - 1) lower = num - 1 diff --git a/maths/twin_prime.py b/maths/twin_prime.py index e6ac0cc78..912b10b36 100644 --- a/maths/twin_prime.py +++ b/maths/twin_prime.py @@ -32,7 +32,8 @@ def twin_prime(number: int) -> int: TypeError: Input value of [number=6.0] must be an integer """ if not isinstance(number, int): - raise TypeError(f"Input value of [number={number}] must be an integer") + msg = f"Input value of [number={number}] must be an integer" + raise TypeError(msg) if is_prime(number) and is_prime(number + 2): return number + 2 else: diff --git a/matrix/matrix_operation.py b/matrix/matrix_operation.py index 576094902..f189f1898 100644 --- a/matrix/matrix_operation.py +++ b/matrix/matrix_operation.py @@ -70,10 +70,11 @@ def multiply(matrix_a: list[list[int]], matrix_b: list[list[int]]) -> list[list[ rows, cols = _verify_matrix_sizes(matrix_a, matrix_b) if cols[0] != rows[1]: - raise ValueError( - f"Cannot multiply matrix of dimensions ({rows[0]},{cols[0]}) " - f"and ({rows[1]},{cols[1]})" + msg = ( + "Cannot multiply matrix of dimensions " + f"({rows[0]},{cols[0]}) and ({rows[1]},{cols[1]})" ) + raise ValueError(msg) return [ [sum(m * n for m, n in zip(i, j)) for j in zip(*matrix_b)] for i in matrix_a ] @@ -174,10 +175,11 @@ def _verify_matrix_sizes( ) -> tuple[tuple[int, int], tuple[int, int]]: shape = _shape(matrix_a) + _shape(matrix_b) if shape[0] != shape[3] or shape[1] != shape[2]: - raise ValueError( - f"operands could not be broadcast together with shape " + msg = ( + "operands could not be broadcast together with shape " f"({shape[0], shape[1]}), ({shape[2], shape[3]})" ) + raise ValueError(msg) return (shape[0], shape[2]), (shape[1], shape[3]) diff --git a/matrix/sherman_morrison.py b/matrix/sherman_morrison.py index 39eddfed8..256271e8a 100644 --- a/matrix/sherman_morrison.py +++ b/matrix/sherman_morrison.py @@ -173,7 +173,8 @@ class Matrix: result[r, c] += self[r, i] * another[i, c] return result else: - raise TypeError(f"Unsupported type given for another ({type(another)})") + msg = f"Unsupported type given for another ({type(another)})" + raise TypeError(msg) def transpose(self) -> Matrix: """ diff --git a/neural_network/input_data.py b/neural_network/input_data.py index 2a32f0b82..94c018ece 100644 --- a/neural_network/input_data.py +++ b/neural_network/input_data.py @@ -198,10 +198,7 @@ class _DataSet: """Return the next `batch_size` examples from this data set.""" if fake_data: fake_image = [1] * 784 - if self.one_hot: - fake_label = [1] + [0] * 9 - else: - fake_label = 0 + fake_label = [1] + [0] * 9 if self.one_hot else 0 return ( [fake_image for _ in range(batch_size)], [fake_label for _ in range(batch_size)], @@ -324,10 +321,11 @@ def read_data_sets( test_labels = _extract_labels(f, one_hot=one_hot) if not 0 <= validation_size <= len(train_images): - raise ValueError( - f"Validation size should be between 0 and {len(train_images)}. " - f"Received: {validation_size}." + msg = ( + "Validation size should be between 0 and " + f"{len(train_images)}. Received: {validation_size}." ) + raise ValueError(msg) validation_images = train_images[:validation_size] validation_labels = train_labels[:validation_size] diff --git a/other/nested_brackets.py b/other/nested_brackets.py index ea48c0a5f..19c6dd53c 100644 --- a/other/nested_brackets.py +++ b/other/nested_brackets.py @@ -18,7 +18,7 @@ def is_balanced(s): stack = [] open_brackets = set({"(", "[", "{"}) closed_brackets = set({")", "]", "}"}) - open_to_closed = dict({"{": "}", "[": "]", "(": ")"}) + open_to_closed = {"{": "}", "[": "]", "(": ")"} for i in range(len(s)): if s[i] in open_brackets: diff --git a/other/scoring_algorithm.py b/other/scoring_algorithm.py index 8e04a8f30..af04f432e 100644 --- a/other/scoring_algorithm.py +++ b/other/scoring_algorithm.py @@ -68,7 +68,8 @@ def calculate_each_score( # weight not 0 or 1 else: - raise ValueError(f"Invalid weight of {weight:f} provided") + msg = f"Invalid weight of {weight:f} provided" + raise ValueError(msg) score_lists.append(score) diff --git a/project_euler/problem_054/sol1.py b/project_euler/problem_054/sol1.py index 9af7aef5a..74409f32c 100644 --- a/project_euler/problem_054/sol1.py +++ b/project_euler/problem_054/sol1.py @@ -119,10 +119,12 @@ class PokerHand: For example: "6S 4C KC AS TH" """ if not isinstance(hand, str): - raise TypeError(f"Hand should be of type 'str': {hand!r}") + msg = f"Hand should be of type 'str': {hand!r}" + raise TypeError(msg) # split removes duplicate whitespaces so no need of strip if len(hand.split(" ")) != 5: - raise ValueError(f"Hand should contain only 5 cards: {hand!r}") + msg = f"Hand should contain only 5 cards: {hand!r}" + raise ValueError(msg) self._hand = hand self._first_pair = 0 self._second_pair = 0 diff --git a/project_euler/problem_068/sol1.py b/project_euler/problem_068/sol1.py index 772be359f..cf814b001 100644 --- a/project_euler/problem_068/sol1.py +++ b/project_euler/problem_068/sol1.py @@ -73,7 +73,8 @@ def solution(gon_side: int = 5) -> int: if is_magic_gon(numbers): return int("".join(str(n) for n in numbers)) - raise ValueError(f"Magic {gon_side}-gon ring is impossible") + msg = f"Magic {gon_side}-gon ring is impossible" + raise ValueError(msg) def generate_gon_ring(gon_side: int, perm: list[int]) -> list[int]: diff --git a/project_euler/problem_131/sol1.py b/project_euler/problem_131/sol1.py index f5302aac8..be3ea9c81 100644 --- a/project_euler/problem_131/sol1.py +++ b/project_euler/problem_131/sol1.py @@ -26,10 +26,7 @@ def is_prime(number: int) -> bool: False """ - for divisor in range(2, isqrt(number) + 1): - if number % divisor == 0: - return False - return True + return all(number % divisor != 0 for divisor in range(2, isqrt(number) + 1)) def solution(max_prime: int = 10**6) -> int: diff --git a/pyproject.toml b/pyproject.toml index 48c3fbd40..a52619668 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,45 +17,88 @@ ignore-words-list = "3rt,ans,crate,damon,fo,followings,hist,iff,kwanza,mater,sec skip = "./.*,*.json,ciphers/prehistoric_men.txt,project_euler/problem_022/p022_names.txt,pyproject.toml,strings/dictionary.txt,strings/words.txt" [tool.ruff] -ignore = [ # `ruff rule S101` for a description of that rule - "B904", # B904: Within an `except` clause, raise exceptions with `raise ... from err` - "B905", # B905: `zip()` without an explicit `strict=` parameter - "E741", # E741: Ambiguous variable name 'l' - "G004", # G004 Logging statement uses f-string - "N999", # N999: Invalid module name - "PLC1901", # PLC1901: `{}` can be simplified to `{}` as an empty string is falsey - "PLR2004", # PLR2004: Magic value used in comparison - "PLR5501", # PLR5501: Consider using `elif` instead of `else` - "PLW0120", # PLW0120: `else` clause on loop without a `break` statement - "PLW060", # PLW060: Using global for `{name}` but no assignment is done -- DO NOT FIX - "PLW2901", # PLW2901: Redefined loop variable - "RUF00", # RUF00: Ambiguous unicode character -- DO NOT FIX - "RUF100", # RUF100: Unused `noqa` directive - "S101", # S101: Use of `assert` detected -- DO NOT FIX - "S105", # S105: Possible hardcoded password: 'password' - "S113", # S113: Probable use of requests call without timeout - "S311", # S311: Standard pseudo-random generators are not suitable for cryptographic purposes - "UP038", # UP038: Use `X | Y` in `{}` call instead of `(X, Y)` -- DO NOT FIX +ignore = [ # `ruff rule S101` for a description of that rule + "ARG001", # Unused function argument `amount` -- FIX ME? + "B904", # Within an `except` clause, raise exceptions with `raise ... from err` -- FIX ME + "B905", # `zip()` without an explicit `strict=` parameter -- FIX ME + "DTZ001", # The use of `datetime.datetime()` without `tzinfo` argument is not allowed -- FIX ME + "DTZ005", # The use of `datetime.datetime.now()` without `tzinfo` argument is not allowed -- FIX ME + "E741", # Ambiguous variable name 'l' -- FIX ME + "EM101", # Exception must not use a string literal, assign to variable first + "EXE001", # Shebang is present but file is not executable" -- FIX ME + "G004", # Logging statement uses f-string + "ICN001", # `matplotlib.pyplot` should be imported as `plt` -- FIX ME + "INP001", # File `x/y/z.py` is part of an implicit namespace package. Add an `__init__.py`. -- FIX ME + "N999", # Invalid module name -- FIX ME + "NPY002", # Replace legacy `np.random.choice` call with `np.random.Generator` -- FIX ME + "PGH003", # Use specific rule codes when ignoring type issues -- FIX ME + "PLC1901", # `{}` can be simplified to `{}` as an empty string is falsey + "PLR5501", # Consider using `elif` instead of `else` -- FIX ME + "PLW0120", # `else` clause on loop without a `break` statement -- FIX ME + "PLW060", # Using global for `{name}` but no assignment is done -- DO NOT FIX + "PLW2901", # PLW2901: Redefined loop variable -- FIX ME + "RUF00", # Ambiguous unicode character and other rules + "RUF100", # Unused `noqa` directive -- FIX ME + "S101", # Use of `assert` detected -- DO NOT FIX + "S105", # Possible hardcoded password: 'password' + "S113", # Probable use of requests call without timeout -- FIX ME + "S311", # Standard pseudo-random generators are not suitable for cryptographic purposes -- FIX ME + "SIM102", # Use a single `if` statement instead of nested `if` statements -- FIX ME + "SLF001", # Private member accessed: `_Iterator` -- FIX ME + "UP038", # Use `X | Y` in `{}` call instead of `(X, Y)` -- DO NOT FIX ] -select = [ # https://beta.ruff.rs/docs/rules - "A", # A: builtins - "B", # B: bugbear - "C40", # C40: comprehensions - "C90", # C90: mccabe code complexity - "E", # E: pycodestyle errors - "F", # F: pyflakes - "G", # G: logging format - "I", # I: isort - "N", # N: pep8 naming - "PL", # PL: pylint - "PIE", # PIE: pie - "PYI", # PYI: type hinting stub files - "RUF", # RUF: ruff - "S", # S: bandit - "TID", # TID: tidy imports - "UP", # UP: pyupgrade - "W", # W: pycodestyle warnings - "YTT", # YTT: year 2020 +select = [ # https://beta.ruff.rs/docs/rules + "A", # flake8-builtins + "ARG", # flake8-unused-arguments + "ASYNC", # flake8-async + "B", # flake8-bugbear + "BLE", # flake8-blind-except + "C4", # flake8-comprehensions + "C90", # McCabe cyclomatic complexity + "DTZ", # flake8-datetimez + "E", # pycodestyle + "EM", # flake8-errmsg + "EXE", # flake8-executable + "F", # Pyflakes + "FA", # flake8-future-annotations + "FLY", # flynt + "G", # flake8-logging-format + "I", # isort + "ICN", # flake8-import-conventions + "INP", # flake8-no-pep420 + "INT", # flake8-gettext + "N", # pep8-naming + "NPY", # NumPy-specific rules + "PGH", # pygrep-hooks + "PIE", # flake8-pie + "PL", # Pylint + "PYI", # flake8-pyi + "RSE", # flake8-raise + "RUF", # Ruff-specific rules + "S", # flake8-bandit + "SIM", # flake8-simplify + "SLF", # flake8-self + "T10", # flake8-debugger + "TD", # flake8-todos + "TID", # flake8-tidy-imports + "UP", # pyupgrade + "W", # pycodestyle + "YTT", # flake8-2020 + # "ANN", # flake8-annotations # FIX ME? + # "COM", # flake8-commas + # "D", # pydocstyle -- FIX ME? + # "DJ", # flake8-django + # "ERA", # eradicate -- DO NOT FIX + # "FBT", # flake8-boolean-trap # FIX ME + # "ISC", # flake8-implicit-str-concat # FIX ME + # "PD", # pandas-vet + # "PT", # flake8-pytest-style + # "PTH", # flake8-use-pathlib # FIX ME + # "Q", # flake8-quotes + # "RET", # flake8-return # FIX ME? + # "T20", # flake8-print + # "TCH", # flake8-type-checking + # "TRY", # tryceratops ] show-source = true target-version = "py311" @@ -63,7 +106,27 @@ target-version = "py311" [tool.ruff.mccabe] # DO NOT INCREASE THIS VALUE max-complexity = 17 # default: 10 +[tool.ruff.per-file-ignores] +"arithmetic_analysis/newton_raphson.py" = ["PGH001"] +"audio_filters/show_response.py" = ["ARG002"] +"data_structures/binary_tree/binary_search_tree_recursive.py" = ["BLE001"] +"data_structures/binary_tree/treap.py" = ["SIM114"] +"data_structures/hashing/hash_table.py" = ["ARG002"] +"data_structures/hashing/quadratic_probing.py" = ["ARG002"] +"data_structures/hashing/tests/test_hash_map.py" = ["BLE001"] +"data_structures/heap/max_heap.py" = ["SIM114"] +"graphs/minimum_spanning_tree_prims.py" = ["SIM114"] +"hashes/enigma_machine.py" = ["BLE001"] +"machine_learning/decision_tree.py" = ["SIM114"] +"machine_learning/linear_discriminant_analysis.py" = ["ARG005"] +"machine_learning/sequential_minimum_optimization.py" = ["SIM115"] +"matrix/sherman_morrison.py" = ["SIM103", "SIM114"] +"physics/newtons_second_law_of_motion.py" = ["BLE001"] +"project_euler/problem_099/sol1.py" = ["SIM115"] +"sorts/external_sort.py" = ["SIM115"] + [tool.ruff.pylint] # DO NOT INCREASE THESE VALUES +allow-magic-value-types = ["float", "int", "str"] max-args = 10 # default: 5 max-branches = 20 # default: 12 max-returns = 8 # default: 6 diff --git a/scripts/build_directory_md.py b/scripts/build_directory_md.py index b95be9ebc..24bc00cd0 100755 --- a/scripts/build_directory_md.py +++ b/scripts/build_directory_md.py @@ -33,7 +33,7 @@ def print_directory_md(top_dir: str = ".") -> None: if filepath != old_path: old_path = print_path(old_path, filepath) indent = (filepath.count(os.sep) + 1) if filepath else 0 - url = "/".join((filepath, filename)).replace(" ", "%20") + url = f"{filepath}/{filename}".replace(" ", "%20") filename = os.path.splitext(filename.replace("_", " ").title())[0] print(f"{md_prefix(indent)} [{filename}]({url})") diff --git a/sorts/dutch_national_flag_sort.py b/sorts/dutch_national_flag_sort.py index 79afefa73..758e3a887 100644 --- a/sorts/dutch_national_flag_sort.py +++ b/sorts/dutch_national_flag_sort.py @@ -84,9 +84,8 @@ def dutch_national_flag_sort(sequence: list) -> list: sequence[mid], sequence[high] = sequence[high], sequence[mid] high -= 1 else: - raise ValueError( - f"The elements inside the sequence must contains only {colors} values" - ) + msg = f"The elements inside the sequence must contains only {colors} values" + raise ValueError(msg) return sequence diff --git a/strings/barcode_validator.py b/strings/barcode_validator.py index e050cd337..b4f3864e2 100644 --- a/strings/barcode_validator.py +++ b/strings/barcode_validator.py @@ -65,7 +65,8 @@ def get_barcode(barcode: str) -> int: ValueError: Barcode 'dwefgiweuf' has alphabetic characters. """ if str(barcode).isalpha(): - raise ValueError(f"Barcode '{barcode}' has alphabetic characters.") + msg = f"Barcode '{barcode}' has alphabetic characters." + raise ValueError(msg) elif int(barcode) < 0: raise ValueError("The entered barcode has a negative value. Try again.") else: diff --git a/strings/capitalize.py b/strings/capitalize.py index 63603aa07..e7e97c2be 100644 --- a/strings/capitalize.py +++ b/strings/capitalize.py @@ -17,7 +17,7 @@ def capitalize(sentence: str) -> str: """ if not sentence: return "" - lower_to_upper = {lc: uc for lc, uc in zip(ascii_lowercase, ascii_uppercase)} + lower_to_upper = dict(zip(ascii_lowercase, ascii_uppercase)) return lower_to_upper.get(sentence[0], sentence[0]) + sentence[1:] diff --git a/strings/is_spain_national_id.py b/strings/is_spain_national_id.py index 67f49755f..60d06e123 100644 --- a/strings/is_spain_national_id.py +++ b/strings/is_spain_national_id.py @@ -48,7 +48,8 @@ def is_spain_national_id(spanish_id: str) -> bool: """ if not isinstance(spanish_id, str): - raise TypeError(f"Expected string as input, found {type(spanish_id).__name__}") + msg = f"Expected string as input, found {type(spanish_id).__name__}" + raise TypeError(msg) spanish_id_clean = spanish_id.replace("-", "").upper() if len(spanish_id_clean) != 9: diff --git a/strings/snake_case_to_camel_pascal_case.py b/strings/snake_case_to_camel_pascal_case.py index 28a28b517..8219337a6 100644 --- a/strings/snake_case_to_camel_pascal_case.py +++ b/strings/snake_case_to_camel_pascal_case.py @@ -27,11 +27,11 @@ def snake_to_camel_case(input_str: str, use_pascal: bool = False) -> str: """ if not isinstance(input_str, str): - raise ValueError(f"Expected string as input, found {type(input_str)}") + msg = f"Expected string as input, found {type(input_str)}" + raise ValueError(msg) if not isinstance(use_pascal, bool): - raise ValueError( - f"Expected boolean as use_pascal parameter, found {type(use_pascal)}" - ) + msg = f"Expected boolean as use_pascal parameter, found {type(use_pascal)}" + raise ValueError(msg) words = input_str.split("_") diff --git a/web_programming/reddit.py b/web_programming/reddit.py index 6a31c81c3..5ca5f828c 100644 --- a/web_programming/reddit.py +++ b/web_programming/reddit.py @@ -26,7 +26,8 @@ def get_subreddit_data( """ wanted_data = wanted_data or [] if invalid_search_terms := ", ".join(sorted(set(wanted_data) - valid_terms)): - raise ValueError(f"Invalid search term: {invalid_search_terms}") + msg = f"Invalid search term: {invalid_search_terms}" + raise ValueError(msg) response = requests.get( f"https://reddit.com/r/{subreddit}/{age}.json?limit={limit}", headers={"User-agent": "A random string"}, diff --git a/web_programming/search_books_by_isbn.py b/web_programming/search_books_by_isbn.py index abac3c70b..d5d4cfe92 100644 --- a/web_programming/search_books_by_isbn.py +++ b/web_programming/search_books_by_isbn.py @@ -22,7 +22,8 @@ def get_openlibrary_data(olid: str = "isbn/0140328726") -> dict: """ new_olid = olid.strip().strip("/") # Remove leading/trailing whitespace & slashes if new_olid.count("/") != 1: - raise ValueError(f"{olid} is not a valid Open Library olid") + msg = f"{olid} is not a valid Open Library olid" + raise ValueError(msg) return requests.get(f"https://openlibrary.org/{new_olid}.json").json() diff --git a/web_programming/slack_message.py b/web_programming/slack_message.py index f35aa3ca5..5e97d6b64 100644 --- a/web_programming/slack_message.py +++ b/web_programming/slack_message.py @@ -7,10 +7,11 @@ def send_slack_message(message_body: str, slack_url: str) -> None: headers = {"Content-Type": "application/json"} response = requests.post(slack_url, json={"text": message_body}, headers=headers) if response.status_code != 200: - raise ValueError( - f"Request to slack returned an error {response.status_code}, " - f"the response is:\n{response.text}" + msg = ( + "Request to slack returned an error " + f"{response.status_code}, the response is:\n{response.text}" ) + raise ValueError(msg) if __name__ == "__main__": From c93659d7ce65e3717f06333e3d049ebaa888e597 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Mon, 29 May 2023 17:37:54 -0700 Subject: [PATCH 670/726] Fix type error in `strassen_matrix_multiplication.py` (#8784) * Fix type error in strassen_matrix_multiplication.py * updating DIRECTORY.md --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 1 + ...ion.py.BROKEN => strassen_matrix_multiplication.py} | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) rename divide_and_conquer/{strassen_matrix_multiplication.py.BROKEN => strassen_matrix_multiplication.py} (97%) diff --git a/DIRECTORY.md b/DIRECTORY.md index 11ff93c91..231b0e2f1 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -294,6 +294,7 @@ * [Mergesort](divide_and_conquer/mergesort.py) * [Peak](divide_and_conquer/peak.py) * [Power](divide_and_conquer/power.py) + * [Strassen Matrix Multiplication](divide_and_conquer/strassen_matrix_multiplication.py) ## Dynamic Programming * [Abbreviation](dynamic_programming/abbreviation.py) diff --git a/divide_and_conquer/strassen_matrix_multiplication.py.BROKEN b/divide_and_conquer/strassen_matrix_multiplication.py similarity index 97% rename from divide_and_conquer/strassen_matrix_multiplication.py.BROKEN rename to divide_and_conquer/strassen_matrix_multiplication.py index 2ca91c63b..cbfc7e565 100644 --- a/divide_and_conquer/strassen_matrix_multiplication.py.BROKEN +++ b/divide_and_conquer/strassen_matrix_multiplication.py @@ -112,17 +112,19 @@ def strassen(matrix1: list, matrix2: list) -> list: [[139, 163], [121, 134], [100, 121]] """ if matrix_dimensions(matrix1)[1] != matrix_dimensions(matrix2)[0]: - raise Exception( - "Unable to multiply these matrices, please check the dimensions. \n" - f"Matrix A:{matrix1} \nMatrix B:{matrix2}" + msg = ( + "Unable to multiply these matrices, please check the dimensions.\n" + f"Matrix A: {matrix1}\n" + f"Matrix B: {matrix2}" ) + raise Exception(msg) dimension1 = matrix_dimensions(matrix1) dimension2 = matrix_dimensions(matrix2) if dimension1[0] == dimension1[1] and dimension2[0] == dimension2[1]: return [matrix1, matrix2] - maximum = max(dimension1, dimension2) + maximum = max(*dimension1, *dimension2) maxim = int(math.pow(2, math.ceil(math.log2(maximum)))) new_matrix1 = matrix1 new_matrix2 = matrix2 From 4a27b544303e6bab90ed57b72fa3acf3d785429e Mon Sep 17 00:00:00 2001 From: Sundaram Kumar Jha Date: Wed, 31 May 2023 06:26:59 +0530 Subject: [PATCH 671/726] Update permutations.py (#8102) --- data_structures/arrays/permutations.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/data_structures/arrays/permutations.py b/data_structures/arrays/permutations.py index eb3f26517..4558bd8d4 100644 --- a/data_structures/arrays/permutations.py +++ b/data_structures/arrays/permutations.py @@ -1,7 +1,6 @@ def permute(nums: list[int]) -> list[list[int]]: """ Return all permutations. - >>> from itertools import permutations >>> numbers= [1,2,3] >>> all(list(nums) in permute(numbers) for nums in permutations(numbers)) @@ -20,7 +19,32 @@ def permute(nums: list[int]) -> list[list[int]]: return result +def permute2(nums): + """ + Return all permutations of the given list. + + >>> permute2([1, 2, 3]) + [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 2, 1], [3, 1, 2]] + """ + + def backtrack(start): + if start == len(nums) - 1: + output.append(nums[:]) + else: + for i in range(start, len(nums)): + nums[start], nums[i] = nums[i], nums[start] + backtrack(start + 1) + nums[start], nums[i] = nums[i], nums[start] # backtrack + + output = [] + backtrack(0) + return output + + if __name__ == "__main__": import doctest + # use res to print the data in permute2 function + res = permute2([1, 2, 3]) + print(res) doctest.testmod() From e871540e37b834673f9e6650b8e2281d7d36a8c3 Mon Sep 17 00:00:00 2001 From: Rudransh Bhardwaj <115872354+rudransh61@users.noreply.github.com> Date: Wed, 31 May 2023 20:33:02 +0530 Subject: [PATCH 672/726] Added rank of matrix in linear algebra (#8687) * Added rank of matrix in linear algebra * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Corrected name of function * Corrected Rank_of_Matrix.py * Completed rank_of_matrix.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * delete to rename Rank_of_Matrix.py * created rank_of_matrix * added more doctests in rank_of_matrix.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fixed some issues in rank_of_matrix.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * added moreeee doctestsss in rank_of_mtrix.py and fixed some bugss * Update linear_algebra/src/rank_of_matrix.py Co-authored-by: Christian Clauss * Update linear_algebra/src/rank_of_matrix.py Co-authored-by: Christian Clauss * Update linear_algebra/src/rank_of_matrix.py Co-authored-by: Christian Clauss * Update rank_of_matrix.py * Update linear_algebra/src/rank_of_matrix.py Co-authored-by: Caeden Perelli-Harris --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss Co-authored-by: Caeden Perelli-Harris --- linear_algebra/src/rank_of_matrix.py | 89 ++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 linear_algebra/src/rank_of_matrix.py diff --git a/linear_algebra/src/rank_of_matrix.py b/linear_algebra/src/rank_of_matrix.py new file mode 100644 index 000000000..7ff3c1699 --- /dev/null +++ b/linear_algebra/src/rank_of_matrix.py @@ -0,0 +1,89 @@ +""" +Calculate the rank of a matrix. + +See: https://en.wikipedia.org/wiki/Rank_(linear_algebra) +""" + + +def rank_of_matrix(matrix: list[list[int | float]]) -> int: + """ + Finds the rank of a matrix. + Args: + matrix: The matrix as a list of lists. + Returns: + The rank of the matrix. + Example: + >>> matrix1 = [[1, 2, 3], + ... [4, 5, 6], + ... [7, 8, 9]] + >>> rank_of_matrix(matrix1) + 2 + >>> matrix2 = [[1, 0, 0], + ... [0, 1, 0], + ... [0, 0, 0]] + >>> rank_of_matrix(matrix2) + 2 + >>> matrix3 = [[1, 2, 3, 4], + ... [5, 6, 7, 8], + ... [9, 10, 11, 12]] + >>> rank_of_matrix(matrix3) + 2 + >>> rank_of_matrix([[2,3,-1,-1], + ... [1,-1,-2,4], + ... [3,1,3,-2], + ... [6,3,0,-7]]) + 4 + >>> rank_of_matrix([[2,1,-3,-6], + ... [3,-3,1,2], + ... [1,1,1,2]]) + 3 + >>> rank_of_matrix([[2,-1,0], + ... [1,3,4], + ... [4,1,-3]]) + 3 + >>> rank_of_matrix([[3,2,1], + ... [-6,-4,-2]]) + 1 + >>> rank_of_matrix([[],[]]) + 0 + >>> rank_of_matrix([[1]]) + 1 + >>> rank_of_matrix([[]]) + 0 + """ + + rows = len(matrix) + columns = len(matrix[0]) + rank = min(rows, columns) + + for row in range(rank): + # Check if diagonal element is not zero + if matrix[row][row] != 0: + # Eliminate all the elements below the diagonal + for col in range(row + 1, rows): + multiplier = matrix[col][row] / matrix[row][row] + for i in range(row, columns): + matrix[col][i] -= multiplier * matrix[row][i] + else: + # Find a non-zero diagonal element to swap rows + reduce = True + for i in range(row + 1, rows): + if matrix[i][row] != 0: + matrix[row], matrix[i] = matrix[i], matrix[row] + reduce = False + break + if reduce: + rank -= 1 + for i in range(rows): + matrix[i][row] = matrix[i][rank] + + # Reduce the row pointer by one to stay on the same row + row -= 1 + + return rank + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 4621b0bb4f5d3fff2fa4f0e53d6cb862fe002c60 Mon Sep 17 00:00:00 2001 From: nith2001 <75632283+nith2001@users.noreply.github.com> Date: Wed, 31 May 2023 13:06:12 -0700 Subject: [PATCH 673/726] Improved Graph Implementations (#8730) * Improved Graph Implementations Provides new implementation for graph_list.py and graph_matrix.py along with pytest suites for each. Fixes #8709 * Graph implementation style fixes, corrections, and refactored tests * Helpful docs about graph implementation * Refactored code to separate files and applied enumerate() * Renamed files and refactored code to fail fast * Error handling style fix * Fixed f-string code quality issue * Last f-string fix * Added return types to test functions and more style fixes * Added more function return types * Added more function return types pt2 * Fixed error messages --- graphs/graph_adjacency_list.py | 589 ++++++++++++++++++++++++++++++ graphs/graph_adjacency_matrix.py | 608 +++++++++++++++++++++++++++++++ graphs/graph_matrix.py | 24 -- graphs/tests/__init__.py | 0 4 files changed, 1197 insertions(+), 24 deletions(-) create mode 100644 graphs/graph_adjacency_list.py create mode 100644 graphs/graph_adjacency_matrix.py delete mode 100644 graphs/graph_matrix.py create mode 100644 graphs/tests/__init__.py diff --git a/graphs/graph_adjacency_list.py b/graphs/graph_adjacency_list.py new file mode 100644 index 000000000..76f34f845 --- /dev/null +++ b/graphs/graph_adjacency_list.py @@ -0,0 +1,589 @@ +#!/usr/bin/env python3 +""" +Author: Vikram Nithyanandam + +Description: +The following implementation is a robust unweighted Graph data structure +implemented using an adjacency list. This vertices and edges of this graph can be +effectively initialized and modified while storing your chosen generic +value in each vertex. + +Adjacency List: https://en.wikipedia.org/wiki/Adjacency_list + +Potential Future Ideas: +- Add a flag to set edge weights on and set edge weights +- Make edge weights and vertex values customizable to store whatever the client wants +- Support multigraph functionality if the client wants it +""" +from __future__ import annotations + +import random +import unittest +from pprint import pformat +from typing import Generic, TypeVar + +T = TypeVar("T") + + +class GraphAdjacencyList(Generic[T]): + def __init__( + self, vertices: list[T], edges: list[list[T]], directed: bool = True + ) -> None: + """ + Parameters: + - vertices: (list[T]) The list of vertex names the client wants to + pass in. Default is empty. + - edges: (list[list[T]]) The list of edges the client wants to + pass in. Each edge is a 2-element list. Default is empty. + - directed: (bool) Indicates if graph is directed or undirected. + Default is True. + """ + self.adj_list: dict[T, list[T]] = {} # dictionary of lists of T + self.directed = directed + + # Falsey checks + edges = edges or [] + vertices = vertices or [] + + for vertex in vertices: + self.add_vertex(vertex) + + for edge in edges: + if len(edge) != 2: + msg = f"Invalid input: {edge} is the wrong length." + raise ValueError(msg) + self.add_edge(edge[0], edge[1]) + + def add_vertex(self, vertex: T) -> None: + """ + Adds a vertex to the graph. If the given vertex already exists, + a ValueError will be thrown. + """ + if self.contains_vertex(vertex): + msg = f"Incorrect input: {vertex} is already in the graph." + raise ValueError(msg) + self.adj_list[vertex] = [] + + def add_edge(self, source_vertex: T, destination_vertex: T) -> None: + """ + Creates an edge from source vertex to destination vertex. If any + given vertex doesn't exist or the edge already exists, a ValueError + will be thrown. + """ + if not ( + self.contains_vertex(source_vertex) + and self.contains_vertex(destination_vertex) + ): + msg = ( + f"Incorrect input: Either {source_vertex} or " + f"{destination_vertex} does not exist" + ) + raise ValueError(msg) + if self.contains_edge(source_vertex, destination_vertex): + msg = ( + "Incorrect input: The edge already exists between " + f"{source_vertex} and {destination_vertex}" + ) + raise ValueError(msg) + + # add the destination vertex to the list associated with the source vertex + # and vice versa if not directed + self.adj_list[source_vertex].append(destination_vertex) + if not self.directed: + self.adj_list[destination_vertex].append(source_vertex) + + def remove_vertex(self, vertex: T) -> None: + """ + Removes the given vertex from the graph and deletes all incoming and + outgoing edges from the given vertex as well. If the given vertex + does not exist, a ValueError will be thrown. + """ + if not self.contains_vertex(vertex): + msg = f"Incorrect input: {vertex} does not exist in this graph." + raise ValueError(msg) + + if not self.directed: + # If not directed, find all neighboring vertices and delete all references + # of edges connecting to the given vertex + for neighbor in self.adj_list[vertex]: + self.adj_list[neighbor].remove(vertex) + else: + # If directed, search all neighbors of all vertices and delete all + # references of edges connecting to the given vertex + for edge_list in self.adj_list.values(): + if vertex in edge_list: + edge_list.remove(vertex) + + # Finally, delete the given vertex and all of its outgoing edge references + self.adj_list.pop(vertex) + + def remove_edge(self, source_vertex: T, destination_vertex: T) -> None: + """ + Removes the edge between the two vertices. If any given vertex + doesn't exist or the edge does not exist, a ValueError will be thrown. + """ + if not ( + self.contains_vertex(source_vertex) + and self.contains_vertex(destination_vertex) + ): + msg = ( + f"Incorrect input: Either {source_vertex} or " + f"{destination_vertex} does not exist" + ) + raise ValueError(msg) + if not self.contains_edge(source_vertex, destination_vertex): + msg = ( + "Incorrect input: The edge does NOT exist between " + f"{source_vertex} and {destination_vertex}" + ) + raise ValueError(msg) + + # remove the destination vertex from the list associated with the source + # vertex and vice versa if not directed + self.adj_list[source_vertex].remove(destination_vertex) + if not self.directed: + self.adj_list[destination_vertex].remove(source_vertex) + + def contains_vertex(self, vertex: T) -> bool: + """ + Returns True if the graph contains the vertex, False otherwise. + """ + return vertex in self.adj_list + + def contains_edge(self, source_vertex: T, destination_vertex: T) -> bool: + """ + Returns True if the graph contains the edge from the source_vertex to the + destination_vertex, False otherwise. If any given vertex doesn't exist, a + ValueError will be thrown. + """ + if not ( + self.contains_vertex(source_vertex) + and self.contains_vertex(destination_vertex) + ): + msg = ( + f"Incorrect input: Either {source_vertex} " + f"or {destination_vertex} does not exist." + ) + raise ValueError(msg) + + return destination_vertex in self.adj_list[source_vertex] + + def clear_graph(self) -> None: + """ + Clears all vertices and edges. + """ + self.adj_list = {} + + def __repr__(self) -> str: + return pformat(self.adj_list) + + +class TestGraphAdjacencyList(unittest.TestCase): + def __assert_graph_edge_exists_check( + self, + undirected_graph: GraphAdjacencyList, + directed_graph: GraphAdjacencyList, + edge: list[int], + ) -> None: + self.assertTrue(undirected_graph.contains_edge(edge[0], edge[1])) + self.assertTrue(undirected_graph.contains_edge(edge[1], edge[0])) + self.assertTrue(directed_graph.contains_edge(edge[0], edge[1])) + + def __assert_graph_edge_does_not_exist_check( + self, + undirected_graph: GraphAdjacencyList, + directed_graph: GraphAdjacencyList, + edge: list[int], + ) -> None: + self.assertFalse(undirected_graph.contains_edge(edge[0], edge[1])) + self.assertFalse(undirected_graph.contains_edge(edge[1], edge[0])) + self.assertFalse(directed_graph.contains_edge(edge[0], edge[1])) + + def __assert_graph_vertex_exists_check( + self, + undirected_graph: GraphAdjacencyList, + directed_graph: GraphAdjacencyList, + vertex: int, + ) -> None: + self.assertTrue(undirected_graph.contains_vertex(vertex)) + self.assertTrue(directed_graph.contains_vertex(vertex)) + + def __assert_graph_vertex_does_not_exist_check( + self, + undirected_graph: GraphAdjacencyList, + directed_graph: GraphAdjacencyList, + vertex: int, + ) -> None: + self.assertFalse(undirected_graph.contains_vertex(vertex)) + self.assertFalse(directed_graph.contains_vertex(vertex)) + + def __generate_random_edges( + self, vertices: list[int], edge_pick_count: int + ) -> list[list[int]]: + self.assertTrue(edge_pick_count <= len(vertices)) + + random_source_vertices: list[int] = random.sample( + vertices[0 : int(len(vertices) / 2)], edge_pick_count + ) + random_destination_vertices: list[int] = random.sample( + vertices[int(len(vertices) / 2) :], edge_pick_count + ) + random_edges: list[list[int]] = [] + + for source in random_source_vertices: + for dest in random_destination_vertices: + random_edges.append([source, dest]) + + return random_edges + + def __generate_graphs( + self, vertex_count: int, min_val: int, max_val: int, edge_pick_count: int + ) -> tuple[GraphAdjacencyList, GraphAdjacencyList, list[int], list[list[int]]]: + if max_val - min_val + 1 < vertex_count: + raise ValueError( + "Will result in duplicate vertices. Either increase range " + "between min_val and max_val or decrease vertex count." + ) + + # generate graph input + random_vertices: list[int] = random.sample( + range(min_val, max_val + 1), vertex_count + ) + random_edges: list[list[int]] = self.__generate_random_edges( + random_vertices, edge_pick_count + ) + + # build graphs + undirected_graph = GraphAdjacencyList( + vertices=random_vertices, edges=random_edges, directed=False + ) + directed_graph = GraphAdjacencyList( + vertices=random_vertices, edges=random_edges, directed=True + ) + + return undirected_graph, directed_graph, random_vertices, random_edges + + def test_init_check(self) -> None: + ( + undirected_graph, + directed_graph, + random_vertices, + random_edges, + ) = self.__generate_graphs(20, 0, 100, 4) + + # test graph initialization with vertices and edges + for num in random_vertices: + self.__assert_graph_vertex_exists_check( + undirected_graph, directed_graph, num + ) + + for edge in random_edges: + self.__assert_graph_edge_exists_check( + undirected_graph, directed_graph, edge + ) + self.assertFalse(undirected_graph.directed) + self.assertTrue(directed_graph.directed) + + def test_contains_vertex(self) -> None: + random_vertices: list[int] = random.sample(range(101), 20) + + # Build graphs WITHOUT edges + undirected_graph = GraphAdjacencyList( + vertices=random_vertices, edges=[], directed=False + ) + directed_graph = GraphAdjacencyList( + vertices=random_vertices, edges=[], directed=True + ) + + # Test contains_vertex + for num in range(101): + self.assertEqual( + num in random_vertices, undirected_graph.contains_vertex(num) + ) + self.assertEqual( + num in random_vertices, directed_graph.contains_vertex(num) + ) + + def test_add_vertices(self) -> None: + random_vertices: list[int] = random.sample(range(101), 20) + + # build empty graphs + undirected_graph: GraphAdjacencyList = GraphAdjacencyList( + vertices=[], edges=[], directed=False + ) + directed_graph: GraphAdjacencyList = GraphAdjacencyList( + vertices=[], edges=[], directed=True + ) + + # run add_vertex + for num in random_vertices: + undirected_graph.add_vertex(num) + + for num in random_vertices: + directed_graph.add_vertex(num) + + # test add_vertex worked + for num in random_vertices: + self.__assert_graph_vertex_exists_check( + undirected_graph, directed_graph, num + ) + + def test_remove_vertices(self) -> None: + random_vertices: list[int] = random.sample(range(101), 20) + + # build graphs WITHOUT edges + undirected_graph = GraphAdjacencyList( + vertices=random_vertices, edges=[], directed=False + ) + directed_graph = GraphAdjacencyList( + vertices=random_vertices, edges=[], directed=True + ) + + # test remove_vertex worked + for num in random_vertices: + self.__assert_graph_vertex_exists_check( + undirected_graph, directed_graph, num + ) + + undirected_graph.remove_vertex(num) + directed_graph.remove_vertex(num) + + self.__assert_graph_vertex_does_not_exist_check( + undirected_graph, directed_graph, num + ) + + def test_add_and_remove_vertices_repeatedly(self) -> None: + random_vertices1: list[int] = random.sample(range(51), 20) + random_vertices2: list[int] = random.sample(range(51, 101), 20) + + # build graphs WITHOUT edges + undirected_graph = GraphAdjacencyList( + vertices=random_vertices1, edges=[], directed=False + ) + directed_graph = GraphAdjacencyList( + vertices=random_vertices1, edges=[], directed=True + ) + + # test adding and removing vertices + for i, _ in enumerate(random_vertices1): + undirected_graph.add_vertex(random_vertices2[i]) + directed_graph.add_vertex(random_vertices2[i]) + + self.__assert_graph_vertex_exists_check( + undirected_graph, directed_graph, random_vertices2[i] + ) + + undirected_graph.remove_vertex(random_vertices1[i]) + directed_graph.remove_vertex(random_vertices1[i]) + + self.__assert_graph_vertex_does_not_exist_check( + undirected_graph, directed_graph, random_vertices1[i] + ) + + # remove all vertices + for i, _ in enumerate(random_vertices1): + undirected_graph.remove_vertex(random_vertices2[i]) + directed_graph.remove_vertex(random_vertices2[i]) + + self.__assert_graph_vertex_does_not_exist_check( + undirected_graph, directed_graph, random_vertices2[i] + ) + + def test_contains_edge(self) -> None: + # generate graphs and graph input + vertex_count = 20 + ( + undirected_graph, + directed_graph, + random_vertices, + random_edges, + ) = self.__generate_graphs(vertex_count, 0, 100, 4) + + # generate all possible edges for testing + all_possible_edges: list[list[int]] = [] + for i in range(vertex_count - 1): + for j in range(i + 1, vertex_count): + all_possible_edges.append([random_vertices[i], random_vertices[j]]) + all_possible_edges.append([random_vertices[j], random_vertices[i]]) + + # test contains_edge function + for edge in all_possible_edges: + if edge in random_edges: + self.__assert_graph_edge_exists_check( + undirected_graph, directed_graph, edge + ) + elif [edge[1], edge[0]] in random_edges: + # since this edge exists for undirected but the reverse + # may not exist for directed + self.__assert_graph_edge_exists_check( + undirected_graph, directed_graph, [edge[1], edge[0]] + ) + else: + self.__assert_graph_edge_does_not_exist_check( + undirected_graph, directed_graph, edge + ) + + def test_add_edge(self) -> None: + # generate graph input + random_vertices: list[int] = random.sample(range(101), 15) + random_edges: list[list[int]] = self.__generate_random_edges(random_vertices, 4) + + # build graphs WITHOUT edges + undirected_graph = GraphAdjacencyList( + vertices=random_vertices, edges=[], directed=False + ) + directed_graph = GraphAdjacencyList( + vertices=random_vertices, edges=[], directed=True + ) + + # run and test add_edge + for edge in random_edges: + undirected_graph.add_edge(edge[0], edge[1]) + directed_graph.add_edge(edge[0], edge[1]) + self.__assert_graph_edge_exists_check( + undirected_graph, directed_graph, edge + ) + + def test_remove_edge(self) -> None: + # generate graph input and graphs + ( + undirected_graph, + directed_graph, + random_vertices, + random_edges, + ) = self.__generate_graphs(20, 0, 100, 4) + + # run and test remove_edge + for edge in random_edges: + self.__assert_graph_edge_exists_check( + undirected_graph, directed_graph, edge + ) + undirected_graph.remove_edge(edge[0], edge[1]) + directed_graph.remove_edge(edge[0], edge[1]) + self.__assert_graph_edge_does_not_exist_check( + undirected_graph, directed_graph, edge + ) + + def test_add_and_remove_edges_repeatedly(self) -> None: + ( + undirected_graph, + directed_graph, + random_vertices, + random_edges, + ) = self.__generate_graphs(20, 0, 100, 4) + + # make some more edge options! + more_random_edges: list[list[int]] = [] + + while len(more_random_edges) != len(random_edges): + edges: list[list[int]] = self.__generate_random_edges(random_vertices, 4) + for edge in edges: + if len(more_random_edges) == len(random_edges): + break + elif edge not in more_random_edges and edge not in random_edges: + more_random_edges.append(edge) + + for i, _ in enumerate(random_edges): + undirected_graph.add_edge(more_random_edges[i][0], more_random_edges[i][1]) + directed_graph.add_edge(more_random_edges[i][0], more_random_edges[i][1]) + + self.__assert_graph_edge_exists_check( + undirected_graph, directed_graph, more_random_edges[i] + ) + + undirected_graph.remove_edge(random_edges[i][0], random_edges[i][1]) + directed_graph.remove_edge(random_edges[i][0], random_edges[i][1]) + + self.__assert_graph_edge_does_not_exist_check( + undirected_graph, directed_graph, random_edges[i] + ) + + def test_add_vertex_exception_check(self) -> None: + ( + undirected_graph, + directed_graph, + random_vertices, + random_edges, + ) = self.__generate_graphs(20, 0, 100, 4) + + for vertex in random_vertices: + with self.assertRaises(ValueError): + undirected_graph.add_vertex(vertex) + with self.assertRaises(ValueError): + directed_graph.add_vertex(vertex) + + def test_remove_vertex_exception_check(self) -> None: + ( + undirected_graph, + directed_graph, + random_vertices, + random_edges, + ) = self.__generate_graphs(20, 0, 100, 4) + + for i in range(101): + if i not in random_vertices: + with self.assertRaises(ValueError): + undirected_graph.remove_vertex(i) + with self.assertRaises(ValueError): + directed_graph.remove_vertex(i) + + def test_add_edge_exception_check(self) -> None: + ( + undirected_graph, + directed_graph, + random_vertices, + random_edges, + ) = self.__generate_graphs(20, 0, 100, 4) + + for edge in random_edges: + with self.assertRaises(ValueError): + undirected_graph.add_edge(edge[0], edge[1]) + with self.assertRaises(ValueError): + directed_graph.add_edge(edge[0], edge[1]) + + def test_remove_edge_exception_check(self) -> None: + ( + undirected_graph, + directed_graph, + random_vertices, + random_edges, + ) = self.__generate_graphs(20, 0, 100, 4) + + more_random_edges: list[list[int]] = [] + + while len(more_random_edges) != len(random_edges): + edges: list[list[int]] = self.__generate_random_edges(random_vertices, 4) + for edge in edges: + if len(more_random_edges) == len(random_edges): + break + elif edge not in more_random_edges and edge not in random_edges: + more_random_edges.append(edge) + + for edge in more_random_edges: + with self.assertRaises(ValueError): + undirected_graph.remove_edge(edge[0], edge[1]) + with self.assertRaises(ValueError): + directed_graph.remove_edge(edge[0], edge[1]) + + def test_contains_edge_exception_check(self) -> None: + ( + undirected_graph, + directed_graph, + random_vertices, + random_edges, + ) = self.__generate_graphs(20, 0, 100, 4) + + for vertex in random_vertices: + with self.assertRaises(ValueError): + undirected_graph.contains_edge(vertex, 102) + with self.assertRaises(ValueError): + directed_graph.contains_edge(vertex, 102) + + with self.assertRaises(ValueError): + undirected_graph.contains_edge(103, 102) + with self.assertRaises(ValueError): + directed_graph.contains_edge(103, 102) + + +if __name__ == "__main__": + unittest.main() diff --git a/graphs/graph_adjacency_matrix.py b/graphs/graph_adjacency_matrix.py new file mode 100644 index 000000000..4d2e02f73 --- /dev/null +++ b/graphs/graph_adjacency_matrix.py @@ -0,0 +1,608 @@ +#!/usr/bin/env python3 +""" +Author: Vikram Nithyanandam + +Description: +The following implementation is a robust unweighted Graph data structure +implemented using an adjacency matrix. This vertices and edges of this graph can be +effectively initialized and modified while storing your chosen generic +value in each vertex. + +Adjacency Matrix: https://mathworld.wolfram.com/AdjacencyMatrix.html + +Potential Future Ideas: +- Add a flag to set edge weights on and set edge weights +- Make edge weights and vertex values customizable to store whatever the client wants +- Support multigraph functionality if the client wants it +""" +from __future__ import annotations + +import random +import unittest +from pprint import pformat +from typing import Generic, TypeVar + +T = TypeVar("T") + + +class GraphAdjacencyMatrix(Generic[T]): + def __init__( + self, vertices: list[T], edges: list[list[T]], directed: bool = True + ) -> None: + """ + Parameters: + - vertices: (list[T]) The list of vertex names the client wants to + pass in. Default is empty. + - edges: (list[list[T]]) The list of edges the client wants to + pass in. Each edge is a 2-element list. Default is empty. + - directed: (bool) Indicates if graph is directed or undirected. + Default is True. + """ + self.directed = directed + self.vertex_to_index: dict[T, int] = {} + self.adj_matrix: list[list[int]] = [] + + # Falsey checks + edges = edges or [] + vertices = vertices or [] + + for vertex in vertices: + self.add_vertex(vertex) + + for edge in edges: + if len(edge) != 2: + msg = f"Invalid input: {edge} must have length 2." + raise ValueError(msg) + self.add_edge(edge[0], edge[1]) + + def add_edge(self, source_vertex: T, destination_vertex: T) -> None: + """ + Creates an edge from source vertex to destination vertex. If any + given vertex doesn't exist or the edge already exists, a ValueError + will be thrown. + """ + if not ( + self.contains_vertex(source_vertex) + and self.contains_vertex(destination_vertex) + ): + msg = ( + f"Incorrect input: Either {source_vertex} or " + f"{destination_vertex} does not exist" + ) + raise ValueError(msg) + if self.contains_edge(source_vertex, destination_vertex): + msg = ( + "Incorrect input: The edge already exists between " + f"{source_vertex} and {destination_vertex}" + ) + raise ValueError(msg) + + # Get the indices of the corresponding vertices and set their edge value to 1. + u: int = self.vertex_to_index[source_vertex] + v: int = self.vertex_to_index[destination_vertex] + self.adj_matrix[u][v] = 1 + if not self.directed: + self.adj_matrix[v][u] = 1 + + def remove_edge(self, source_vertex: T, destination_vertex: T) -> None: + """ + Removes the edge between the two vertices. If any given vertex + doesn't exist or the edge does not exist, a ValueError will be thrown. + """ + if not ( + self.contains_vertex(source_vertex) + and self.contains_vertex(destination_vertex) + ): + msg = ( + f"Incorrect input: Either {source_vertex} or " + f"{destination_vertex} does not exist" + ) + raise ValueError(msg) + if not self.contains_edge(source_vertex, destination_vertex): + msg = ( + "Incorrect input: The edge does NOT exist between " + f"{source_vertex} and {destination_vertex}" + ) + raise ValueError(msg) + + # Get the indices of the corresponding vertices and set their edge value to 0. + u: int = self.vertex_to_index[source_vertex] + v: int = self.vertex_to_index[destination_vertex] + self.adj_matrix[u][v] = 0 + if not self.directed: + self.adj_matrix[v][u] = 0 + + def add_vertex(self, vertex: T) -> None: + """ + Adds a vertex to the graph. If the given vertex already exists, + a ValueError will be thrown. + """ + if self.contains_vertex(vertex): + msg = f"Incorrect input: {vertex} already exists in this graph." + raise ValueError(msg) + + # build column for vertex + for row in self.adj_matrix: + row.append(0) + + # build row for vertex and update other data structures + self.adj_matrix.append([0] * (len(self.adj_matrix) + 1)) + self.vertex_to_index[vertex] = len(self.adj_matrix) - 1 + + def remove_vertex(self, vertex: T) -> None: + """ + Removes the given vertex from the graph and deletes all incoming and + outgoing edges from the given vertex as well. If the given vertex + does not exist, a ValueError will be thrown. + """ + if not self.contains_vertex(vertex): + msg = f"Incorrect input: {vertex} does not exist in this graph." + raise ValueError(msg) + + # first slide up the rows by deleting the row corresponding to + # the vertex being deleted. + start_index = self.vertex_to_index[vertex] + self.adj_matrix.pop(start_index) + + # next, slide the columns to the left by deleting the values in + # the column corresponding to the vertex being deleted + for lst in self.adj_matrix: + lst.pop(start_index) + + # final clean up + self.vertex_to_index.pop(vertex) + + # decrement indices for vertices shifted by the deleted vertex in the adj matrix + for vertex in self.vertex_to_index: + if self.vertex_to_index[vertex] >= start_index: + self.vertex_to_index[vertex] = self.vertex_to_index[vertex] - 1 + + def contains_vertex(self, vertex: T) -> bool: + """ + Returns True if the graph contains the vertex, False otherwise. + """ + return vertex in self.vertex_to_index + + def contains_edge(self, source_vertex: T, destination_vertex: T) -> bool: + """ + Returns True if the graph contains the edge from the source_vertex to the + destination_vertex, False otherwise. If any given vertex doesn't exist, a + ValueError will be thrown. + """ + if not ( + self.contains_vertex(source_vertex) + and self.contains_vertex(destination_vertex) + ): + msg = ( + f"Incorrect input: Either {source_vertex} " + f"or {destination_vertex} does not exist." + ) + raise ValueError(msg) + + u = self.vertex_to_index[source_vertex] + v = self.vertex_to_index[destination_vertex] + return self.adj_matrix[u][v] == 1 + + def clear_graph(self) -> None: + """ + Clears all vertices and edges. + """ + self.vertex_to_index = {} + self.adj_matrix = [] + + def __repr__(self) -> str: + first = "Adj Matrix:\n" + pformat(self.adj_matrix) + second = "\nVertex to index mapping:\n" + pformat(self.vertex_to_index) + return first + second + + +class TestGraphMatrix(unittest.TestCase): + def __assert_graph_edge_exists_check( + self, + undirected_graph: GraphAdjacencyMatrix, + directed_graph: GraphAdjacencyMatrix, + edge: list[int], + ) -> None: + self.assertTrue(undirected_graph.contains_edge(edge[0], edge[1])) + self.assertTrue(undirected_graph.contains_edge(edge[1], edge[0])) + self.assertTrue(directed_graph.contains_edge(edge[0], edge[1])) + + def __assert_graph_edge_does_not_exist_check( + self, + undirected_graph: GraphAdjacencyMatrix, + directed_graph: GraphAdjacencyMatrix, + edge: list[int], + ) -> None: + self.assertFalse(undirected_graph.contains_edge(edge[0], edge[1])) + self.assertFalse(undirected_graph.contains_edge(edge[1], edge[0])) + self.assertFalse(directed_graph.contains_edge(edge[0], edge[1])) + + def __assert_graph_vertex_exists_check( + self, + undirected_graph: GraphAdjacencyMatrix, + directed_graph: GraphAdjacencyMatrix, + vertex: int, + ) -> None: + self.assertTrue(undirected_graph.contains_vertex(vertex)) + self.assertTrue(directed_graph.contains_vertex(vertex)) + + def __assert_graph_vertex_does_not_exist_check( + self, + undirected_graph: GraphAdjacencyMatrix, + directed_graph: GraphAdjacencyMatrix, + vertex: int, + ) -> None: + self.assertFalse(undirected_graph.contains_vertex(vertex)) + self.assertFalse(directed_graph.contains_vertex(vertex)) + + def __generate_random_edges( + self, vertices: list[int], edge_pick_count: int + ) -> list[list[int]]: + self.assertTrue(edge_pick_count <= len(vertices)) + + random_source_vertices: list[int] = random.sample( + vertices[0 : int(len(vertices) / 2)], edge_pick_count + ) + random_destination_vertices: list[int] = random.sample( + vertices[int(len(vertices) / 2) :], edge_pick_count + ) + random_edges: list[list[int]] = [] + + for source in random_source_vertices: + for dest in random_destination_vertices: + random_edges.append([source, dest]) + + return random_edges + + def __generate_graphs( + self, vertex_count: int, min_val: int, max_val: int, edge_pick_count: int + ) -> tuple[GraphAdjacencyMatrix, GraphAdjacencyMatrix, list[int], list[list[int]]]: + if max_val - min_val + 1 < vertex_count: + raise ValueError( + "Will result in duplicate vertices. Either increase " + "range between min_val and max_val or decrease vertex count" + ) + + # generate graph input + random_vertices: list[int] = random.sample( + range(min_val, max_val + 1), vertex_count + ) + random_edges: list[list[int]] = self.__generate_random_edges( + random_vertices, edge_pick_count + ) + + # build graphs + undirected_graph = GraphAdjacencyMatrix( + vertices=random_vertices, edges=random_edges, directed=False + ) + directed_graph = GraphAdjacencyMatrix( + vertices=random_vertices, edges=random_edges, directed=True + ) + + return undirected_graph, directed_graph, random_vertices, random_edges + + def test_init_check(self) -> None: + ( + undirected_graph, + directed_graph, + random_vertices, + random_edges, + ) = self.__generate_graphs(20, 0, 100, 4) + + # test graph initialization with vertices and edges + for num in random_vertices: + self.__assert_graph_vertex_exists_check( + undirected_graph, directed_graph, num + ) + + for edge in random_edges: + self.__assert_graph_edge_exists_check( + undirected_graph, directed_graph, edge + ) + + self.assertFalse(undirected_graph.directed) + self.assertTrue(directed_graph.directed) + + def test_contains_vertex(self) -> None: + random_vertices: list[int] = random.sample(range(101), 20) + + # Build graphs WITHOUT edges + undirected_graph = GraphAdjacencyMatrix( + vertices=random_vertices, edges=[], directed=False + ) + directed_graph = GraphAdjacencyMatrix( + vertices=random_vertices, edges=[], directed=True + ) + + # Test contains_vertex + for num in range(101): + self.assertEqual( + num in random_vertices, undirected_graph.contains_vertex(num) + ) + self.assertEqual( + num in random_vertices, directed_graph.contains_vertex(num) + ) + + def test_add_vertices(self) -> None: + random_vertices: list[int] = random.sample(range(101), 20) + + # build empty graphs + undirected_graph: GraphAdjacencyMatrix = GraphAdjacencyMatrix( + vertices=[], edges=[], directed=False + ) + directed_graph: GraphAdjacencyMatrix = GraphAdjacencyMatrix( + vertices=[], edges=[], directed=True + ) + + # run add_vertex + for num in random_vertices: + undirected_graph.add_vertex(num) + + for num in random_vertices: + directed_graph.add_vertex(num) + + # test add_vertex worked + for num in random_vertices: + self.__assert_graph_vertex_exists_check( + undirected_graph, directed_graph, num + ) + + def test_remove_vertices(self) -> None: + random_vertices: list[int] = random.sample(range(101), 20) + + # build graphs WITHOUT edges + undirected_graph = GraphAdjacencyMatrix( + vertices=random_vertices, edges=[], directed=False + ) + directed_graph = GraphAdjacencyMatrix( + vertices=random_vertices, edges=[], directed=True + ) + + # test remove_vertex worked + for num in random_vertices: + self.__assert_graph_vertex_exists_check( + undirected_graph, directed_graph, num + ) + + undirected_graph.remove_vertex(num) + directed_graph.remove_vertex(num) + + self.__assert_graph_vertex_does_not_exist_check( + undirected_graph, directed_graph, num + ) + + def test_add_and_remove_vertices_repeatedly(self) -> None: + random_vertices1: list[int] = random.sample(range(51), 20) + random_vertices2: list[int] = random.sample(range(51, 101), 20) + + # build graphs WITHOUT edges + undirected_graph = GraphAdjacencyMatrix( + vertices=random_vertices1, edges=[], directed=False + ) + directed_graph = GraphAdjacencyMatrix( + vertices=random_vertices1, edges=[], directed=True + ) + + # test adding and removing vertices + for i, _ in enumerate(random_vertices1): + undirected_graph.add_vertex(random_vertices2[i]) + directed_graph.add_vertex(random_vertices2[i]) + + self.__assert_graph_vertex_exists_check( + undirected_graph, directed_graph, random_vertices2[i] + ) + + undirected_graph.remove_vertex(random_vertices1[i]) + directed_graph.remove_vertex(random_vertices1[i]) + + self.__assert_graph_vertex_does_not_exist_check( + undirected_graph, directed_graph, random_vertices1[i] + ) + + # remove all vertices + for i, _ in enumerate(random_vertices1): + undirected_graph.remove_vertex(random_vertices2[i]) + directed_graph.remove_vertex(random_vertices2[i]) + + self.__assert_graph_vertex_does_not_exist_check( + undirected_graph, directed_graph, random_vertices2[i] + ) + + def test_contains_edge(self) -> None: + # generate graphs and graph input + vertex_count = 20 + ( + undirected_graph, + directed_graph, + random_vertices, + random_edges, + ) = self.__generate_graphs(vertex_count, 0, 100, 4) + + # generate all possible edges for testing + all_possible_edges: list[list[int]] = [] + for i in range(vertex_count - 1): + for j in range(i + 1, vertex_count): + all_possible_edges.append([random_vertices[i], random_vertices[j]]) + all_possible_edges.append([random_vertices[j], random_vertices[i]]) + + # test contains_edge function + for edge in all_possible_edges: + if edge in random_edges: + self.__assert_graph_edge_exists_check( + undirected_graph, directed_graph, edge + ) + elif [edge[1], edge[0]] in random_edges: + # since this edge exists for undirected but the reverse may + # not exist for directed + self.__assert_graph_edge_exists_check( + undirected_graph, directed_graph, [edge[1], edge[0]] + ) + else: + self.__assert_graph_edge_does_not_exist_check( + undirected_graph, directed_graph, edge + ) + + def test_add_edge(self) -> None: + # generate graph input + random_vertices: list[int] = random.sample(range(101), 15) + random_edges: list[list[int]] = self.__generate_random_edges(random_vertices, 4) + + # build graphs WITHOUT edges + undirected_graph = GraphAdjacencyMatrix( + vertices=random_vertices, edges=[], directed=False + ) + directed_graph = GraphAdjacencyMatrix( + vertices=random_vertices, edges=[], directed=True + ) + + # run and test add_edge + for edge in random_edges: + undirected_graph.add_edge(edge[0], edge[1]) + directed_graph.add_edge(edge[0], edge[1]) + self.__assert_graph_edge_exists_check( + undirected_graph, directed_graph, edge + ) + + def test_remove_edge(self) -> None: + # generate graph input and graphs + ( + undirected_graph, + directed_graph, + random_vertices, + random_edges, + ) = self.__generate_graphs(20, 0, 100, 4) + + # run and test remove_edge + for edge in random_edges: + self.__assert_graph_edge_exists_check( + undirected_graph, directed_graph, edge + ) + undirected_graph.remove_edge(edge[0], edge[1]) + directed_graph.remove_edge(edge[0], edge[1]) + self.__assert_graph_edge_does_not_exist_check( + undirected_graph, directed_graph, edge + ) + + def test_add_and_remove_edges_repeatedly(self) -> None: + ( + undirected_graph, + directed_graph, + random_vertices, + random_edges, + ) = self.__generate_graphs(20, 0, 100, 4) + + # make some more edge options! + more_random_edges: list[list[int]] = [] + + while len(more_random_edges) != len(random_edges): + edges: list[list[int]] = self.__generate_random_edges(random_vertices, 4) + for edge in edges: + if len(more_random_edges) == len(random_edges): + break + elif edge not in more_random_edges and edge not in random_edges: + more_random_edges.append(edge) + + for i, _ in enumerate(random_edges): + undirected_graph.add_edge(more_random_edges[i][0], more_random_edges[i][1]) + directed_graph.add_edge(more_random_edges[i][0], more_random_edges[i][1]) + + self.__assert_graph_edge_exists_check( + undirected_graph, directed_graph, more_random_edges[i] + ) + + undirected_graph.remove_edge(random_edges[i][0], random_edges[i][1]) + directed_graph.remove_edge(random_edges[i][0], random_edges[i][1]) + + self.__assert_graph_edge_does_not_exist_check( + undirected_graph, directed_graph, random_edges[i] + ) + + def test_add_vertex_exception_check(self) -> None: + ( + undirected_graph, + directed_graph, + random_vertices, + random_edges, + ) = self.__generate_graphs(20, 0, 100, 4) + + for vertex in random_vertices: + with self.assertRaises(ValueError): + undirected_graph.add_vertex(vertex) + with self.assertRaises(ValueError): + directed_graph.add_vertex(vertex) + + def test_remove_vertex_exception_check(self) -> None: + ( + undirected_graph, + directed_graph, + random_vertices, + random_edges, + ) = self.__generate_graphs(20, 0, 100, 4) + + for i in range(101): + if i not in random_vertices: + with self.assertRaises(ValueError): + undirected_graph.remove_vertex(i) + with self.assertRaises(ValueError): + directed_graph.remove_vertex(i) + + def test_add_edge_exception_check(self) -> None: + ( + undirected_graph, + directed_graph, + random_vertices, + random_edges, + ) = self.__generate_graphs(20, 0, 100, 4) + + for edge in random_edges: + with self.assertRaises(ValueError): + undirected_graph.add_edge(edge[0], edge[1]) + with self.assertRaises(ValueError): + directed_graph.add_edge(edge[0], edge[1]) + + def test_remove_edge_exception_check(self) -> None: + ( + undirected_graph, + directed_graph, + random_vertices, + random_edges, + ) = self.__generate_graphs(20, 0, 100, 4) + + more_random_edges: list[list[int]] = [] + + while len(more_random_edges) != len(random_edges): + edges: list[list[int]] = self.__generate_random_edges(random_vertices, 4) + for edge in edges: + if len(more_random_edges) == len(random_edges): + break + elif edge not in more_random_edges and edge not in random_edges: + more_random_edges.append(edge) + + for edge in more_random_edges: + with self.assertRaises(ValueError): + undirected_graph.remove_edge(edge[0], edge[1]) + with self.assertRaises(ValueError): + directed_graph.remove_edge(edge[0], edge[1]) + + def test_contains_edge_exception_check(self) -> None: + ( + undirected_graph, + directed_graph, + random_vertices, + random_edges, + ) = self.__generate_graphs(20, 0, 100, 4) + + for vertex in random_vertices: + with self.assertRaises(ValueError): + undirected_graph.contains_edge(vertex, 102) + with self.assertRaises(ValueError): + directed_graph.contains_edge(vertex, 102) + + with self.assertRaises(ValueError): + undirected_graph.contains_edge(103, 102) + with self.assertRaises(ValueError): + directed_graph.contains_edge(103, 102) + + +if __name__ == "__main__": + unittest.main() diff --git a/graphs/graph_matrix.py b/graphs/graph_matrix.py deleted file mode 100644 index 4adc6c0bb..000000000 --- a/graphs/graph_matrix.py +++ /dev/null @@ -1,24 +0,0 @@ -class Graph: - def __init__(self, vertex): - self.vertex = vertex - self.graph = [[0] * vertex for i in range(vertex)] - - def add_edge(self, u, v): - self.graph[u - 1][v - 1] = 1 - self.graph[v - 1][u - 1] = 1 - - def show(self): - for i in self.graph: - for j in i: - print(j, end=" ") - print(" ") - - -g = Graph(100) - -g.add_edge(1, 4) -g.add_edge(4, 2) -g.add_edge(4, 5) -g.add_edge(2, 5) -g.add_edge(5, 3) -g.show() diff --git a/graphs/tests/__init__.py b/graphs/tests/__init__.py new file mode 100644 index 000000000..e69de29bb From 3a9e5fa5ecea0df54ed3ffdcb74f46171199f552 Mon Sep 17 00:00:00 2001 From: Chris O <46587501+ChrisO345@users.noreply.github.com> Date: Fri, 2 Jun 2023 17:14:25 +1200 Subject: [PATCH 674/726] Create a Simultaneous Equation Solver Algorithm (#8773) * Added simultaneous_linear_equation_solver.py * Removed Augment class, replaced with recursive functions * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fixed edge cases * Update settings.json --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .vscode/settings.json | 5 + maths/simultaneous_linear_equation_solver.py | 142 +++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 .vscode/settings.json create mode 100644 maths/simultaneous_linear_equation_solver.py diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..ef16fa1aa --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "githubPullRequests.ignoredPullRequestBranches": [ + "master" + ] +} diff --git a/maths/simultaneous_linear_equation_solver.py b/maths/simultaneous_linear_equation_solver.py new file mode 100644 index 000000000..1287b2002 --- /dev/null +++ b/maths/simultaneous_linear_equation_solver.py @@ -0,0 +1,142 @@ +""" +https://en.wikipedia.org/wiki/Augmented_matrix + +This algorithm solves simultaneous linear equations of the form +λa + λb + λc + λd + ... = γ as [λ, λ, λ, λ, ..., γ] +Where λ & γ are individual coefficients, the no. of equations = no. of coefficients - 1 + +Note in order to work there must exist 1 equation where all instances of λ and γ != 0 +""" + + +def simplify(current_set: list[list]) -> list[list]: + """ + >>> simplify([[1, 2, 3], [4, 5, 6]]) + [[1.0, 2.0, 3.0], [0.0, 0.75, 1.5]] + >>> simplify([[5, 2, 5], [5, 1, 10]]) + [[1.0, 0.4, 1.0], [0.0, 0.2, -1.0]] + """ + # Divide each row by magnitude of first term --> creates 'unit' matrix + duplicate_set = current_set.copy() + for row_index, row in enumerate(duplicate_set): + magnitude = row[0] + for column_index, column in enumerate(row): + if magnitude == 0: + current_set[row_index][column_index] = column + continue + current_set[row_index][column_index] = column / magnitude + # Subtract to cancel term + first_row = current_set[0] + final_set = [first_row] + current_set = current_set[1::] + for row in current_set: + temp_row = [] + # If first term is 0, it is already in form we want, so we preserve it + if row[0] == 0: + final_set.append(row) + continue + for column_index in range(len(row)): + temp_row.append(first_row[column_index] - row[column_index]) + final_set.append(temp_row) + # Create next recursion iteration set + if len(final_set[0]) != 3: + current_first_row = final_set[0] + current_first_column = [] + next_iteration = [] + for row in final_set[1::]: + current_first_column.append(row[0]) + next_iteration.append(row[1::]) + resultant = simplify(next_iteration) + for i in range(len(resultant)): + resultant[i].insert(0, current_first_column[i]) + resultant.insert(0, current_first_row) + final_set = resultant + return final_set + + +def solve_simultaneous(equations: list[list]) -> list: + """ + >>> solve_simultaneous([[1, 2, 3],[4, 5, 6]]) + [-1.0, 2.0] + >>> solve_simultaneous([[0, -3, 1, 7],[3, 2, -1, 11],[5, 1, -2, 12]]) + [6.4, 1.2, 10.6] + >>> solve_simultaneous([]) + Traceback (most recent call last): + ... + IndexError: solve_simultaneous() requires n lists of length n+1 + >>> solve_simultaneous([[1, 2, 3],[1, 2]]) + Traceback (most recent call last): + ... + IndexError: solve_simultaneous() requires n lists of length n+1 + >>> solve_simultaneous([[1, 2, 3],["a", 7, 8]]) + Traceback (most recent call last): + ... + ValueError: solve_simultaneous() requires lists of integers + >>> solve_simultaneous([[0, 2, 3],[4, 0, 6]]) + Traceback (most recent call last): + ... + ValueError: solve_simultaneous() requires at least 1 full equation + """ + if len(equations) == 0: + raise IndexError("solve_simultaneous() requires n lists of length n+1") + _length = len(equations) + 1 + if any(len(item) != _length for item in equations): + raise IndexError("solve_simultaneous() requires n lists of length n+1") + for row in equations: + if any(not isinstance(column, (int, float)) for column in row): + raise ValueError("solve_simultaneous() requires lists of integers") + if len(equations) == 1: + return [equations[0][-1] / equations[0][0]] + data_set = equations.copy() + if any(0 in row for row in data_set): + temp_data = data_set.copy() + full_row = [] + for row_index, row in enumerate(temp_data): + if 0 not in row: + full_row = data_set.pop(row_index) + break + if not full_row: + raise ValueError("solve_simultaneous() requires at least 1 full equation") + data_set.insert(0, full_row) + useable_form = data_set.copy() + simplified = simplify(useable_form) + simplified = simplified[::-1] + solutions: list = [] + for row in simplified: + current_solution = row[-1] + if not solutions: + if row[-2] == 0: + solutions.append(0) + continue + solutions.append(current_solution / row[-2]) + continue + temp_row = row.copy()[: len(row) - 1 :] + while temp_row[0] == 0: + temp_row.pop(0) + if len(temp_row) == 0: + solutions.append(0) + continue + temp_row = temp_row[1::] + temp_row = temp_row[::-1] + for column_index, column in enumerate(temp_row): + current_solution -= column * solutions[column_index] + solutions.append(current_solution) + final = [] + for item in solutions: + final.append(float(round(item, 5))) + return final[::-1] + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + eq = [ + [2, 1, 1, 1, 1, 4], + [1, 2, 1, 1, 1, 5], + [1, 1, 2, 1, 1, 6], + [1, 1, 1, 2, 1, 7], + [1, 1, 1, 1, 2, 8], + ] + print(solve_simultaneous(eq)) + print(solve_simultaneous([[4, 2]])) From 80d95fccc390d366a9f617d8628a546a7be7b2a3 Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Sat, 3 Jun 2023 17:16:33 +0100 Subject: [PATCH 675/726] Pytest locally fails due to API_KEY env variable (#8738) * fix: Pytest locally fails due to API_KEY env variable (#8737) * chore: Fix ruff errors --- web_programming/currency_converter.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/web_programming/currency_converter.py b/web_programming/currency_converter.py index 69f2a2c4d..3bbcafa8f 100644 --- a/web_programming/currency_converter.py +++ b/web_programming/currency_converter.py @@ -8,13 +8,7 @@ import os import requests URL_BASE = "https://www.amdoren.com/api/currency.php" -TESTING = os.getenv("CI", "") -API_KEY = os.getenv("AMDOREN_API_KEY", "") -if not API_KEY and not TESTING: - raise KeyError( - "API key must be provided in the 'AMDOREN_API_KEY' environment variable." - ) # Currency and their description list_of_currencies = """ @@ -175,20 +169,31 @@ ZMW Zambian Kwacha def convert_currency( - from_: str = "USD", to: str = "INR", amount: float = 1.0, api_key: str = API_KEY + from_: str = "USD", to: str = "INR", amount: float = 1.0, api_key: str = "" ) -> str: """https://www.amdoren.com/currency-api/""" + # Instead of manually generating parameters params = locals() + # from is a reserved keyword params["from"] = params.pop("from_") res = requests.get(URL_BASE, params=params).json() return str(res["amount"]) if res["error"] == 0 else res["error_message"] if __name__ == "__main__": + TESTING = os.getenv("CI", "") + API_KEY = os.getenv("AMDOREN_API_KEY", "") + + if not API_KEY and not TESTING: + raise KeyError( + "API key must be provided in the 'AMDOREN_API_KEY' environment variable." + ) + print( convert_currency( input("Enter from currency: ").strip(), input("Enter to currency: ").strip(), float(input("Enter the amount: ").strip()), + API_KEY, ) ) From fa12b9a286bf42d250b30a772e8f226dc14953f4 Mon Sep 17 00:00:00 2001 From: ShivaDahal99 <130563462+ShivaDahal99@users.noreply.github.com> Date: Wed, 7 Jun 2023 23:47:27 +0200 Subject: [PATCH 676/726] Speed of sound (#8803) * Create TestShiva * Delete TestShiva * Add speed of sound * Update physics/speed_of_sound.py Co-authored-by: Christian Clauss * Update physics/speed_of_sound.py Co-authored-by: Christian Clauss * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update speed_of_sound.py * Update speed_of_sound.py --------- Co-authored-by: jlhuhn <134317018+jlhuhn@users.noreply.github.com> Co-authored-by: Christian Clauss Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- physics/speed_of_sound.py | 52 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 physics/speed_of_sound.py diff --git a/physics/speed_of_sound.py b/physics/speed_of_sound.py new file mode 100644 index 000000000..a4658366a --- /dev/null +++ b/physics/speed_of_sound.py @@ -0,0 +1,52 @@ +""" +Title : Calculating the speed of sound + +Description : + The speed of sound (c) is the speed that a sound wave travels + per unit time (m/s). During propagation, the sound wave propagates + through an elastic medium. Its SI unit is meter per second (m/s). + + Only longitudinal waves can propagate in liquids and gas other then + solid where they also travel in transverse wave. The following Algo- + rithem calculates the speed of sound in fluid depanding on the bulk + module and the density of the fluid. + + Equation for calculating speed od sound in fluid: + c_fluid = (K_s*p)**0.5 + + c_fluid: speed of sound in fluid + K_s: isentropic bulk modulus + p: density of fluid + + + +Source : https://en.wikipedia.org/wiki/Speed_of_sound +""" + + +def speed_of_sound_in_a_fluid(density: float, bulk_modulus: float) -> float: + """ + This method calculates the speed of sound in fluid - + This is calculated from the other two provided values + Examples: + Example 1 --> Water 20°C: bulk_moduls= 2.15MPa, density=998kg/m³ + Example 2 --> Murcery 20°: bulk_moduls= 28.5MPa, density=13600kg/m³ + + >>> speed_of_sound_in_a_fluid(bulk_modulus=2.15*10**9, density=998) + 1467.7563207952705 + >>> speed_of_sound_in_a_fluid(bulk_modulus=28.5*10**9, density=13600) + 1447.614670861731 + """ + + if density <= 0: + raise ValueError("Impossible fluid density") + if bulk_modulus <= 0: + raise ValueError("Impossible bulk modulus") + + return (bulk_modulus / density) ** 0.5 + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 7775de0ef779a28cec7d9f28af97a89b2bc29d7e Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Thu, 8 Jun 2023 13:40:38 +0100 Subject: [PATCH 677/726] Create number container system algorithm (#8808) * feat: Create number container system algorithm * updating DIRECTORY.md * chore: Fix failing tests * Update other/number_container_system.py Co-authored-by: Christian Clauss * Update other/number_container_system.py Co-authored-by: Christian Clauss * Update other/number_container_system.py Co-authored-by: Christian Clauss * chore: Add more tests * chore: Create binary_search_insert failing test * type: Update typehints to accept str, list and range --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss --- DIRECTORY.md | 6 +- other/number_container_system.py | 180 +++++++++++++++++++++++++++++++ 2 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 other/number_container_system.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 231b0e2f1..6dac4a9a5 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -419,8 +419,9 @@ * [Frequent Pattern Graph Miner](graphs/frequent_pattern_graph_miner.py) * [G Topological Sort](graphs/g_topological_sort.py) * [Gale Shapley Bigraph](graphs/gale_shapley_bigraph.py) + * [Graph Adjacency List](graphs/graph_adjacency_list.py) + * [Graph Adjacency Matrix](graphs/graph_adjacency_matrix.py) * [Graph List](graphs/graph_list.py) - * [Graph Matrix](graphs/graph_matrix.py) * [Graphs Floyd Warshall](graphs/graphs_floyd_warshall.py) * [Greedy Best First](graphs/greedy_best_first.py) * [Greedy Min Vertex Cover](graphs/greedy_min_vertex_cover.py) @@ -479,6 +480,7 @@ * [Lib](linear_algebra/src/lib.py) * [Polynom For Points](linear_algebra/src/polynom_for_points.py) * [Power Iteration](linear_algebra/src/power_iteration.py) + * [Rank Of Matrix](linear_algebra/src/rank_of_matrix.py) * [Rayleigh Quotient](linear_algebra/src/rayleigh_quotient.py) * [Schur Complement](linear_algebra/src/schur_complement.py) * [Test Linear Algebra](linear_algebra/src/test_linear_algebra.py) @@ -651,6 +653,7 @@ * [Sigmoid Linear Unit](maths/sigmoid_linear_unit.py) * [Signum](maths/signum.py) * [Simpson Rule](maths/simpson_rule.py) + * [Simultaneous Linear Equation Solver](maths/simultaneous_linear_equation_solver.py) * [Sin](maths/sin.py) * [Sock Merchant](maths/sock_merchant.py) * [Softmax](maths/softmax.py) @@ -726,6 +729,7 @@ * [Maximum Subarray](other/maximum_subarray.py) * [Maximum Subsequence](other/maximum_subsequence.py) * [Nested Brackets](other/nested_brackets.py) + * [Number Container System](other/number_container_system.py) * [Password](other/password.py) * [Quine](other/quine.py) * [Scoring Algorithm](other/scoring_algorithm.py) diff --git a/other/number_container_system.py b/other/number_container_system.py new file mode 100644 index 000000000..f547bc8a2 --- /dev/null +++ b/other/number_container_system.py @@ -0,0 +1,180 @@ +""" +A number container system that uses binary search to delete and insert values into +arrays with O(n logn) write times and O(1) read times. + +This container system holds integers at indexes. + +Further explained in this leetcode problem +> https://leetcode.com/problems/minimum-cost-tree-from-leaf-values +""" + + +class NumberContainer: + def __init__(self) -> None: + # numbermap keys are the number and its values are lists of indexes sorted + # in ascending order + self.numbermap: dict[int, list[int]] = {} + # indexmap keys are an index and it's values are the number at that index + self.indexmap: dict[int, int] = {} + + def binary_search_delete(self, array: list | str | range, item: int) -> list[int]: + """ + Removes the item from the sorted array and returns + the new array. + + >>> NumberContainer().binary_search_delete([1,2,3], 2) + [1, 3] + >>> NumberContainer().binary_search_delete([0, 0, 0], 0) + [0, 0] + >>> NumberContainer().binary_search_delete([-1, -1, -1], -1) + [-1, -1] + >>> NumberContainer().binary_search_delete([-1, 0], 0) + [-1] + >>> NumberContainer().binary_search_delete([-1, 0], -1) + [0] + >>> NumberContainer().binary_search_delete(range(7), 3) + [0, 1, 2, 4, 5, 6] + >>> NumberContainer().binary_search_delete([1.1, 2.2, 3.3], 2.2) + [1.1, 3.3] + >>> NumberContainer().binary_search_delete("abcde", "c") + ['a', 'b', 'd', 'e'] + >>> NumberContainer().binary_search_delete([0, -1, 2, 4], 0) + Traceback (most recent call last): + ... + ValueError: Either the item is not in the array or the array was unsorted + >>> NumberContainer().binary_search_delete([2, 0, 4, -1, 11], -1) + Traceback (most recent call last): + ... + ValueError: Either the item is not in the array or the array was unsorted + >>> NumberContainer().binary_search_delete(125, 1) + Traceback (most recent call last): + ... + TypeError: binary_search_delete() only accepts either a list, range or str + """ + if isinstance(array, (range, str)): + array = list(array) + elif not isinstance(array, list): + raise TypeError( + "binary_search_delete() only accepts either a list, range or str" + ) + + low = 0 + high = len(array) - 1 + + while low <= high: + mid = (low + high) // 2 + if array[mid] == item: + array.pop(mid) + return array + elif array[mid] < item: + low = mid + 1 + else: + high = mid - 1 + raise ValueError( + "Either the item is not in the array or the array was unsorted" + ) + + def binary_search_insert(self, array: list | str | range, index: int) -> list[int]: + """ + Inserts the index into the sorted array + at the correct position. + + >>> NumberContainer().binary_search_insert([1,2,3], 2) + [1, 2, 2, 3] + >>> NumberContainer().binary_search_insert([0,1,3], 2) + [0, 1, 2, 3] + >>> NumberContainer().binary_search_insert([-5, -3, 0, 0, 11, 103], 51) + [-5, -3, 0, 0, 11, 51, 103] + >>> NumberContainer().binary_search_insert([-5, -3, 0, 0, 11, 100, 103], 101) + [-5, -3, 0, 0, 11, 100, 101, 103] + >>> NumberContainer().binary_search_insert(range(10), 4) + [0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 9] + >>> NumberContainer().binary_search_insert("abd", "c") + ['a', 'b', 'c', 'd'] + >>> NumberContainer().binary_search_insert(131, 23) + Traceback (most recent call last): + ... + TypeError: binary_search_insert() only accepts either a list, range or str + """ + if isinstance(array, (range, str)): + array = list(array) + elif not isinstance(array, list): + raise TypeError( + "binary_search_insert() only accepts either a list, range or str" + ) + + low = 0 + high = len(array) - 1 + + while low <= high: + mid = (low + high) // 2 + if array[mid] == index: + # If the item already exists in the array, + # insert it after the existing item + array.insert(mid + 1, index) + return array + elif array[mid] < index: + low = mid + 1 + else: + high = mid - 1 + + # If the item doesn't exist in the array, insert it at the appropriate position + array.insert(low, index) + return array + + def change(self, index: int, number: int) -> None: + """ + Changes (sets) the index as number + + >>> cont = NumberContainer() + >>> cont.change(0, 10) + >>> cont.change(0, 20) + >>> cont.change(-13, 20) + >>> cont.change(-100030, 20032903290) + """ + # Remove previous index + if index in self.indexmap: + n = self.indexmap[index] + if len(self.numbermap[n]) == 1: + del self.numbermap[n] + else: + self.numbermap[n] = self.binary_search_delete(self.numbermap[n], index) + + # Set new index + self.indexmap[index] = number + + # Number not seen before or empty so insert number value + if number not in self.numbermap: + self.numbermap[number] = [index] + + # Here we need to perform a binary search insertion in order to insert + # The item in the correct place + else: + self.numbermap[number] = self.binary_search_insert( + self.numbermap[number], index + ) + + def find(self, number: int) -> int: + """ + Returns the smallest index where the number is. + + >>> cont = NumberContainer() + >>> cont.find(10) + -1 + >>> cont.change(0, 10) + >>> cont.find(10) + 0 + >>> cont.change(0, 20) + >>> cont.find(10) + -1 + >>> cont.find(20) + 0 + """ + # Simply return the 0th index (smallest) of the indexes found (or -1) + return self.numbermap.get(number, [-1])[0] + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 9c9da8ebf1d35ae40ac5438c05cc273f7c6d4473 Mon Sep 17 00:00:00 2001 From: Jan Wojciechowski <96974442+yanvoi@users.noreply.github.com> Date: Fri, 9 Jun 2023 11:06:37 +0200 Subject: [PATCH 678/726] Improve readability of ciphers/mixed_keyword_cypher.py (#8626) * refactored the code * the code will now pass the test * looked more into it and fixed the logic * made the code easier to read, added comments and fixed the logic * got rid of redundant code + plaintext can contain chars that are not in the alphabet * fixed the reduntant conversion of ascii_uppercase to a list * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * keyword and plaintext won't have default values * ran the ruff command * Update linear_discriminant_analysis.py and rsa_cipher.py (#8680) * Update rsa_cipher.py by replacing %s with {} * Update rsa_cipher.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update linear_discriminant_analysis.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update linear_discriminant_analysis.py * Update linear_discriminant_analysis.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update linear_discriminant_analysis.py * Update linear_discriminant_analysis.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update linear_discriminant_analysis.py * Update machine_learning/linear_discriminant_analysis.py Co-authored-by: Christian Clauss * Update linear_discriminant_analysis.py * updated --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss * fixed some difficulties * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * added comments, made printing mapping optional, added 1 test * shortened the line that was too long * Update ciphers/mixed_keyword_cypher.py Co-authored-by: Tianyi Zheng --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Rohan Anand <96521078+rohan472000@users.noreply.github.com> Co-authored-by: Christian Clauss Co-authored-by: Tianyi Zheng --- ciphers/mixed_keyword_cypher.py | 100 +++++++++++++++++--------------- 1 file changed, 53 insertions(+), 47 deletions(-) diff --git a/ciphers/mixed_keyword_cypher.py b/ciphers/mixed_keyword_cypher.py index 93a0e3acb..b984808fc 100644 --- a/ciphers/mixed_keyword_cypher.py +++ b/ciphers/mixed_keyword_cypher.py @@ -1,7 +1,11 @@ -def mixed_keyword(key: str = "college", pt: str = "UNIVERSITY") -> str: - """ +from string import ascii_uppercase - For key:hello + +def mixed_keyword( + keyword: str, plaintext: str, verbose: bool = False, alphabet: str = ascii_uppercase +) -> str: + """ + For keyword: hello H E L O A B C D @@ -12,58 +16,60 @@ def mixed_keyword(key: str = "college", pt: str = "UNIVERSITY") -> str: Y Z and map vertically - >>> mixed_keyword("college", "UNIVERSITY") # doctest: +NORMALIZE_WHITESPACE + >>> mixed_keyword("college", "UNIVERSITY", True) # doctest: +NORMALIZE_WHITESPACE {'A': 'C', 'B': 'A', 'C': 'I', 'D': 'P', 'E': 'U', 'F': 'Z', 'G': 'O', 'H': 'B', 'I': 'J', 'J': 'Q', 'K': 'V', 'L': 'L', 'M': 'D', 'N': 'K', 'O': 'R', 'P': 'W', 'Q': 'E', 'R': 'F', 'S': 'M', 'T': 'S', 'U': 'X', 'V': 'G', 'W': 'H', 'X': 'N', 'Y': 'T', 'Z': 'Y'} 'XKJGUFMJST' + + >>> mixed_keyword("college", "UNIVERSITY", False) # doctest: +NORMALIZE_WHITESPACE + 'XKJGUFMJST' """ - key = key.upper() - pt = pt.upper() - temp = [] - for i in key: - if i not in temp: - temp.append(i) - len_temp = len(temp) - # print(temp) - alpha = [] - modalpha = [] - for j in range(65, 91): - t = chr(j) - alpha.append(t) - if t not in temp: - temp.append(t) - # print(temp) - r = int(26 / 4) - # print(r) - k = 0 - for _ in range(r): - s = [] - for _ in range(len_temp): - s.append(temp[k]) - if k >= 25: + keyword = keyword.upper() + plaintext = plaintext.upper() + alphabet_set = set(alphabet) + + # create a list of unique characters in the keyword - their order matters + # it determines how we will map plaintext characters to the ciphertext + unique_chars = [] + for char in keyword: + if char in alphabet_set and char not in unique_chars: + unique_chars.append(char) + # the number of those unique characters will determine the number of rows + num_unique_chars_in_keyword = len(unique_chars) + + # create a shifted version of the alphabet + shifted_alphabet = unique_chars + [ + char for char in alphabet if char not in unique_chars + ] + + # create a modified alphabet by splitting the shifted alphabet into rows + modified_alphabet = [ + shifted_alphabet[k : k + num_unique_chars_in_keyword] + for k in range(0, 26, num_unique_chars_in_keyword) + ] + + # map the alphabet characters to the modified alphabet characters + # going 'vertically' through the modified alphabet - consider columns first + mapping = {} + letter_index = 0 + for column in range(num_unique_chars_in_keyword): + for row in modified_alphabet: + # if current row (the last one) is too short, break out of loop + if len(row) <= column: break - k += 1 - modalpha.append(s) - # print(modalpha) - d = {} - j = 0 - k = 0 - for j in range(len_temp): - for m in modalpha: - if not len(m) - 1 >= j: - break - d[alpha[k]] = m[j] - if not k < 25: - break - k += 1 - print(d) - cypher = "" - for i in pt: - cypher += d[i] - return cypher + + # map current letter to letter in modified alphabet + mapping[alphabet[letter_index]] = row[column] + letter_index += 1 + + if verbose: + print(mapping) + # create the encrypted text by mapping the plaintext to the modified alphabet + return "".join(mapping[char] if char in mapping else char for char in plaintext) if __name__ == "__main__": + # example use print(mixed_keyword("college", "UNIVERSITY")) From daa0c8f3d340485ce295570e6d76b38891e371bd Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Sat, 10 Jun 2023 13:21:49 +0100 Subject: [PATCH 679/726] Create count negative numbers in matrix algorithm (#8813) * updating DIRECTORY.md * feat: Count negative numbers in sorted matrix * updating DIRECTORY.md * chore: Fix pre-commit * refactor: Combine functions into iteration * style: Reformat reference * feat: Add timings of each implementation * chore: Fix problems with algorithms-keeper bot * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * test: Remove doctest from benchmark function * Update matrix/count_negative_numbers_in_sorted_matrix.py Co-authored-by: Christian Clauss * Update matrix/count_negative_numbers_in_sorted_matrix.py Co-authored-by: Christian Clauss * Update matrix/count_negative_numbers_in_sorted_matrix.py Co-authored-by: Christian Clauss * Update matrix/count_negative_numbers_in_sorted_matrix.py Co-authored-by: Christian Clauss * Update matrix/count_negative_numbers_in_sorted_matrix.py Co-authored-by: Christian Clauss * Update matrix/count_negative_numbers_in_sorted_matrix.py Co-authored-by: Christian Clauss * refactor: Use sum instead of large iteration * refactor: Use len not sum * Update count_negative_numbers_in_sorted_matrix.py --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- DIRECTORY.md | 2 + ...count_negative_numbers_in_sorted_matrix.py | 151 ++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 matrix/count_negative_numbers_in_sorted_matrix.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 6dac4a9a5..8511c261a 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -679,6 +679,7 @@ ## Matrix * [Binary Search Matrix](matrix/binary_search_matrix.py) * [Count Islands In Matrix](matrix/count_islands_in_matrix.py) + * [Count Negative Numbers In Sorted Matrix](matrix/count_negative_numbers_in_sorted_matrix.py) * [Count Paths](matrix/count_paths.py) * [Cramers Rule 2X2](matrix/cramers_rule_2x2.py) * [Inverse Of Matrix](matrix/inverse_of_matrix.py) @@ -753,6 +754,7 @@ * [Potential Energy](physics/potential_energy.py) * [Rms Speed Of Molecule](physics/rms_speed_of_molecule.py) * [Shear Stress](physics/shear_stress.py) + * [Speed Of Sound](physics/speed_of_sound.py) ## Project Euler * Problem 001 diff --git a/matrix/count_negative_numbers_in_sorted_matrix.py b/matrix/count_negative_numbers_in_sorted_matrix.py new file mode 100644 index 000000000..2799ff3b4 --- /dev/null +++ b/matrix/count_negative_numbers_in_sorted_matrix.py @@ -0,0 +1,151 @@ +""" +Given an matrix of numbers in which all rows and all columns are sorted in decreasing +order, return the number of negative numbers in grid. + +Reference: https://leetcode.com/problems/count-negative-numbers-in-a-sorted-matrix +""" + + +def generate_large_matrix() -> list[list[int]]: + """ + >>> generate_large_matrix() # doctest: +ELLIPSIS + [[1000, ..., -999], [999, ..., -1001], ..., [2, ..., -1998]] + """ + return [list(range(1000 - i, -1000 - i, -1)) for i in range(1000)] + + +grid = generate_large_matrix() +test_grids = ( + [[4, 3, 2, -1], [3, 2, 1, -1], [1, 1, -1, -2], [-1, -1, -2, -3]], + [[3, 2], [1, 0]], + [[7, 7, 6]], + [[7, 7, 6], [-1, -2, -3]], + grid, +) + + +def validate_grid(grid: list[list[int]]) -> None: + """ + Validate that the rows and columns of the grid is sorted in decreasing order. + >>> for grid in test_grids: + ... validate_grid(grid) + """ + assert all(row == sorted(row, reverse=True) for row in grid) + assert all(list(col) == sorted(col, reverse=True) for col in zip(*grid)) + + +def find_negative_index(array: list[int]) -> int: + """ + Find the smallest negative index + + >>> find_negative_index([0,0,0,0]) + 4 + >>> find_negative_index([4,3,2,-1]) + 3 + >>> find_negative_index([1,0,-1,-10]) + 2 + >>> find_negative_index([0,0,0,-1]) + 3 + >>> find_negative_index([11,8,7,-3,-5,-9]) + 3 + >>> find_negative_index([-1,-1,-2,-3]) + 0 + >>> find_negative_index([5,1,0]) + 3 + >>> find_negative_index([-5,-5,-5]) + 0 + >>> find_negative_index([0]) + 1 + >>> find_negative_index([]) + 0 + """ + left = 0 + right = len(array) - 1 + + # Edge cases such as no values or all numbers are negative. + if not array or array[0] < 0: + return 0 + + while right + 1 > left: + mid = (left + right) // 2 + num = array[mid] + + # Num must be negative and the index must be greater than or equal to 0. + if num < 0 and array[mid - 1] >= 0: + return mid + + if num >= 0: + left = mid + 1 + else: + right = mid - 1 + # No negative numbers so return the last index of the array + 1 which is the length. + return len(array) + + +def count_negatives_binary_search(grid: list[list[int]]) -> int: + """ + An O(m logn) solution that uses binary search in order to find the boundary between + positive and negative numbers + + >>> [count_negatives_binary_search(grid) for grid in test_grids] + [8, 0, 0, 3, 1498500] + """ + total = 0 + bound = len(grid[0]) + + for i in range(len(grid)): + bound = find_negative_index(grid[i][:bound]) + total += bound + return (len(grid) * len(grid[0])) - total + + +def count_negatives_brute_force(grid: list[list[int]]) -> int: + """ + This solution is O(n^2) because it iterates through every column and row. + + >>> [count_negatives_brute_force(grid) for grid in test_grids] + [8, 0, 0, 3, 1498500] + """ + return len([number for row in grid for number in row if number < 0]) + + +def count_negatives_brute_force_with_break(grid: list[list[int]]) -> int: + """ + Similar to the brute force solution above but uses break in order to reduce the + number of iterations. + + >>> [count_negatives_brute_force_with_break(grid) for grid in test_grids] + [8, 0, 0, 3, 1498500] + """ + total = 0 + for row in grid: + for i, number in enumerate(row): + if number < 0: + total += len(row) - i + break + return total + + +def benchmark() -> None: + """Benchmark our functions next to each other""" + from timeit import timeit + + print("Running benchmarks") + setup = ( + "from __main__ import count_negatives_binary_search, " + "count_negatives_brute_force, count_negatives_brute_force_with_break, grid" + ) + for func in ( + "count_negatives_binary_search", # took 0.7727 seconds + "count_negatives_brute_force_with_break", # took 4.6505 seconds + "count_negatives_brute_force", # took 12.8160 seconds + ): + time = timeit(f"{func}(grid=grid)", setup=setup, number=500) + print(f"{func}() took {time:0.4f} seconds") + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + benchmark() From 46379861257d43bb7140d261094bf17dc414950f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 13 Jun 2023 00:09:33 +0200 Subject: [PATCH 680/726] [pre-commit.ci] pre-commit autoupdate (#8817) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/charliermarsh/ruff-pre-commit: v0.0.270 → v0.0.272](https://github.com/charliermarsh/ruff-pre-commit/compare/v0.0.270...v0.0.272) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4c70ae219..1d4b73681 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.270 + rev: v0.0.272 hooks: - id: ruff From e6f89a6b89941ffed911e96362be3611a45420e7 Mon Sep 17 00:00:00 2001 From: Ilkin Mengusoglu <113149540+imengus@users.noreply.github.com> Date: Sun, 18 Jun 2023 17:00:02 +0100 Subject: [PATCH 681/726] Simplex algorithm (#8825) * feat: added simplex.py * added docstrings * Update linear_programming/simplex.py Co-authored-by: Caeden Perelli-Harris * Update linear_programming/simplex.py Co-authored-by: Caeden Perelli-Harris * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update linear_programming/simplex.py Co-authored-by: Caeden Perelli-Harris * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * ruff fix Co-authored by: CaedenPH * removed README to add in separate PR * Update linear_programming/simplex.py Co-authored-by: Tianyi Zheng * Update linear_programming/simplex.py Co-authored-by: Tianyi Zheng * fix class docstring * add comments --------- Co-authored-by: Caeden Perelli-Harris Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Tianyi Zheng --- linear_programming/simplex.py | 311 ++++++++++++++++++++++++++++++++++ 1 file changed, 311 insertions(+) create mode 100644 linear_programming/simplex.py diff --git a/linear_programming/simplex.py b/linear_programming/simplex.py new file mode 100644 index 000000000..ba64add40 --- /dev/null +++ b/linear_programming/simplex.py @@ -0,0 +1,311 @@ +""" +Python implementation of the simplex algorithm for solving linear programs in +tabular form with +- `>=`, `<=`, and `=` constraints and +- each variable `x1, x2, ...>= 0`. + +See https://gist.github.com/imengus/f9619a568f7da5bc74eaf20169a24d98 for how to +convert linear programs to simplex tableaus, and the steps taken in the simplex +algorithm. + +Resources: +https://en.wikipedia.org/wiki/Simplex_algorithm +https://tinyurl.com/simplex4beginners +""" +from typing import Any + +import numpy as np + + +class Tableau: + """Operate on simplex tableaus + + >>> t = Tableau(np.array([[-1,-1,0,0,-1],[1,3,1,0,4],[3,1,0,1,4.]]), 2) + Traceback (most recent call last): + ... + ValueError: RHS must be > 0 + """ + + def __init__(self, tableau: np.ndarray, n_vars: int) -> None: + # Check if RHS is negative + if np.any(tableau[:, -1], where=tableau[:, -1] < 0): + raise ValueError("RHS must be > 0") + + self.tableau = tableau + self.n_rows, _ = tableau.shape + + # Number of decision variables x1, x2, x3... + self.n_vars = n_vars + + # Number of artificial variables to be minimised + self.n_art_vars = len(np.where(tableau[self.n_vars : -1] == -1)[0]) + + # 2 if there are >= or == constraints (nonstandard), 1 otherwise (std) + self.n_stages = (self.n_art_vars > 0) + 1 + + # Number of slack variables added to make inequalities into equalities + self.n_slack = self.n_rows - self.n_stages + + # Objectives for each stage + self.objectives = ["max"] + + # In two stage simplex, first minimise then maximise + if self.n_art_vars: + self.objectives.append("min") + + self.col_titles = [""] + + # Index of current pivot row and column + self.row_idx = None + self.col_idx = None + + # Does objective row only contain (non)-negative values? + self.stop_iter = False + + @staticmethod + def generate_col_titles(*args: int) -> list[str]: + """Generate column titles for tableau of specific dimensions + + >>> Tableau.generate_col_titles(2, 3, 1) + ['x1', 'x2', 's1', 's2', 's3', 'a1', 'RHS'] + + >>> Tableau.generate_col_titles() + Traceback (most recent call last): + ... + ValueError: Must provide n_vars, n_slack, and n_art_vars + >>> Tableau.generate_col_titles(-2, 3, 1) + Traceback (most recent call last): + ... + ValueError: All arguments must be non-negative integers + """ + if len(args) != 3: + raise ValueError("Must provide n_vars, n_slack, and n_art_vars") + + if not all(x >= 0 and isinstance(x, int) for x in args): + raise ValueError("All arguments must be non-negative integers") + + # decision | slack | artificial + string_starts = ["x", "s", "a"] + titles = [] + for i in range(3): + for j in range(args[i]): + titles.append(string_starts[i] + str(j + 1)) + titles.append("RHS") + return titles + + def find_pivot(self, tableau: np.ndarray) -> tuple[Any, Any]: + """Finds the pivot row and column. + >>> t = Tableau(np.array([[-2,1,0,0,0], [3,1,1,0,6], [1,2,0,1,7.]]), 2) + >>> t.find_pivot(t.tableau) + (1, 0) + """ + objective = self.objectives[-1] + + # Find entries of highest magnitude in objective rows + sign = (objective == "min") - (objective == "max") + col_idx = np.argmax(sign * tableau[0, : self.n_vars]) + + # Choice is only valid if below 0 for maximise, and above for minimise + if sign * self.tableau[0, col_idx] <= 0: + self.stop_iter = True + return 0, 0 + + # Pivot row is chosen as having the lowest quotient when elements of + # the pivot column divide the right-hand side + + # Slice excluding the objective rows + s = slice(self.n_stages, self.n_rows) + + # RHS + dividend = tableau[s, -1] + + # Elements of pivot column within slice + divisor = tableau[s, col_idx] + + # Array filled with nans + nans = np.full(self.n_rows - self.n_stages, np.nan) + + # If element in pivot column is greater than zeron_stages, return + # quotient or nan otherwise + quotients = np.divide(dividend, divisor, out=nans, where=divisor > 0) + + # Arg of minimum quotient excluding the nan values. n_stages is added + # to compensate for earlier exclusion of objective columns + row_idx = np.nanargmin(quotients) + self.n_stages + return row_idx, col_idx + + def pivot(self, tableau: np.ndarray, row_idx: int, col_idx: int) -> np.ndarray: + """Pivots on value on the intersection of pivot row and column. + + >>> t = Tableau(np.array([[-2,-3,0,0,0],[1,3,1,0,4],[3,1,0,1,4.]]), 2) + >>> t.pivot(t.tableau, 1, 0).tolist() + ... # doctest: +NORMALIZE_WHITESPACE + [[0.0, 3.0, 2.0, 0.0, 8.0], + [1.0, 3.0, 1.0, 0.0, 4.0], + [0.0, -8.0, -3.0, 1.0, -8.0]] + """ + # Avoid changes to original tableau + piv_row = tableau[row_idx].copy() + + piv_val = piv_row[col_idx] + + # Entry becomes 1 + piv_row *= 1 / piv_val + + # Variable in pivot column becomes basic, ie the only non-zero entry + for idx, coeff in enumerate(tableau[:, col_idx]): + tableau[idx] += -coeff * piv_row + tableau[row_idx] = piv_row + return tableau + + def change_stage(self, tableau: np.ndarray) -> np.ndarray: + """Exits first phase of the two-stage method by deleting artificial + rows and columns, or completes the algorithm if exiting the standard + case. + + >>> t = Tableau(np.array([ + ... [3, 3, -1, -1, 0, 0, 4], + ... [2, 1, 0, 0, 0, 0, 0.], + ... [1, 2, -1, 0, 1, 0, 2], + ... [2, 1, 0, -1, 0, 1, 2] + ... ]), 2) + >>> t.change_stage(t.tableau).tolist() + ... # doctest: +NORMALIZE_WHITESPACE + [[2.0, 1.0, 0.0, 0.0, 0.0, 0.0], + [1.0, 2.0, -1.0, 0.0, 1.0, 2.0], + [2.0, 1.0, 0.0, -1.0, 0.0, 2.0]] + """ + # Objective of original objective row remains + self.objectives.pop() + + if not self.objectives: + return tableau + + # Slice containing ids for artificial columns + s = slice(-self.n_art_vars - 1, -1) + + # Delete the artificial variable columns + tableau = np.delete(tableau, s, axis=1) + + # Delete the objective row of the first stage + tableau = np.delete(tableau, 0, axis=0) + + self.n_stages = 1 + self.n_rows -= 1 + self.n_art_vars = 0 + self.stop_iter = False + return tableau + + def run_simplex(self) -> dict[Any, Any]: + """Operate on tableau until objective function cannot be + improved further. + + # Standard linear program: + Max: x1 + x2 + ST: x1 + 3x2 <= 4 + 3x1 + x2 <= 4 + >>> Tableau(np.array([[-1,-1,0,0,0],[1,3,1,0,4],[3,1,0,1,4.]]), + ... 2).run_simplex() + {'P': 2.0, 'x1': 1.0, 'x2': 1.0} + + # Optimal tableau input: + >>> Tableau(np.array([ + ... [0, 0, 0.25, 0.25, 2], + ... [0, 1, 0.375, -0.125, 1], + ... [1, 0, -0.125, 0.375, 1] + ... ]), 2).run_simplex() + {'P': 2.0, 'x1': 1.0, 'x2': 1.0} + + # Non-standard: >= constraints + Max: 2x1 + 3x2 + x3 + ST: x1 + x2 + x3 <= 40 + 2x1 + x2 - x3 >= 10 + - x2 + x3 >= 10 + >>> Tableau(np.array([ + ... [2, 0, 0, 0, -1, -1, 0, 0, 20], + ... [-2, -3, -1, 0, 0, 0, 0, 0, 0], + ... [1, 1, 1, 1, 0, 0, 0, 0, 40], + ... [2, 1, -1, 0, -1, 0, 1, 0, 10], + ... [0, -1, 1, 0, 0, -1, 0, 1, 10.] + ... ]), 3).run_simplex() + {'P': 70.0, 'x1': 10.0, 'x2': 10.0, 'x3': 20.0} + + # Non standard: minimisation and equalities + Min: x1 + x2 + ST: 2x1 + x2 = 12 + 6x1 + 5x2 = 40 + >>> Tableau(np.array([ + ... [8, 6, 0, -1, 0, -1, 0, 0, 52], + ... [1, 1, 0, 0, 0, 0, 0, 0, 0], + ... [2, 1, 1, 0, 0, 0, 0, 0, 12], + ... [2, 1, 0, -1, 0, 0, 1, 0, 12], + ... [6, 5, 0, 0, 1, 0, 0, 0, 40], + ... [6, 5, 0, 0, 0, -1, 0, 1, 40.] + ... ]), 2).run_simplex() + {'P': 7.0, 'x1': 5.0, 'x2': 2.0} + """ + # Stop simplex algorithm from cycling. + for _ in range(100): + # Completion of each stage removes an objective. If both stages + # are complete, then no objectives are left + if not self.objectives: + self.col_titles = self.generate_col_titles( + self.n_vars, self.n_slack, self.n_art_vars + ) + + # Find the values of each variable at optimal solution + return self.interpret_tableau(self.tableau, self.col_titles) + + row_idx, col_idx = self.find_pivot(self.tableau) + + # If there are no more negative values in objective row + if self.stop_iter: + # Delete artificial variable columns and rows. Update attributes + self.tableau = self.change_stage(self.tableau) + else: + self.tableau = self.pivot(self.tableau, row_idx, col_idx) + return {} + + def interpret_tableau( + self, tableau: np.ndarray, col_titles: list[str] + ) -> dict[str, float]: + """Given the final tableau, add the corresponding values of the basic + decision variables to the `output_dict` + >>> tableau = np.array([ + ... [0,0,0.875,0.375,5], + ... [0,1,0.375,-0.125,1], + ... [1,0,-0.125,0.375,1] + ... ]) + >>> t = Tableau(tableau, 2) + >>> t.interpret_tableau(tableau, ["x1", "x2", "s1", "s2", "RHS"]) + {'P': 5.0, 'x1': 1.0, 'x2': 1.0} + """ + # P = RHS of final tableau + output_dict = {"P": abs(tableau[0, -1])} + + for i in range(self.n_vars): + # Gives ids of nonzero entries in the ith column + nonzero = np.nonzero(tableau[:, i]) + n_nonzero = len(nonzero[0]) + + # First entry in the nonzero ids + nonzero_rowidx = nonzero[0][0] + nonzero_val = tableau[nonzero_rowidx, i] + + # If there is only one nonzero value in column, which is one + if n_nonzero == nonzero_val == 1: + rhs_val = tableau[nonzero_rowidx, -1] + output_dict[col_titles[i]] = rhs_val + + # Check for basic variables + for title in col_titles: + # Don't add RHS or slack variables to output dict + if title[0] not in "R-s-a": + output_dict.setdefault(title, 0) + return output_dict + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From b0f871032e78dd1d2f2214acbaae2fac88fa55b0 Mon Sep 17 00:00:00 2001 From: Frank-1998 <77809242+Frank-1998@users.noreply.github.com> Date: Sun, 18 Jun 2023 10:30:06 -0600 Subject: [PATCH 682/726] Fix removing the root node in binary_search_tree.py removes the whole tree (#8752) * fix issue #8715 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- data_structures/binary_tree/binary_search_tree.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/binary_tree/binary_search_tree.py b/data_structures/binary_tree/binary_search_tree.py index cd88cc10e..c72195424 100644 --- a/data_structures/binary_tree/binary_search_tree.py +++ b/data_structures/binary_tree/binary_search_tree.py @@ -40,7 +40,7 @@ class BinarySearchTree: else: node.parent.left = new_children else: - self.root = None + self.root = new_children def is_right(self, node: Node) -> bool: if node.parent and node.parent.right: From ea6c6056cf2215358834710bf89422310f831178 Mon Sep 17 00:00:00 2001 From: Turro <42980188+smturro2@users.noreply.github.com> Date: Mon, 19 Jun 2023 06:46:29 -0500 Subject: [PATCH 683/726] Added apr_interest function to financial (#6025) * Added apr_interest function to financial * Update interest.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update financial/interest.py * float --------- Co-authored-by: Christian Clauss Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- financial/interest.py | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/financial/interest.py b/financial/interest.py index c69c73045..33d02e27c 100644 --- a/financial/interest.py +++ b/financial/interest.py @@ -4,7 +4,7 @@ from __future__ import annotations def simple_interest( - principal: float, daily_interest_rate: float, days_between_payments: int + principal: float, daily_interest_rate: float, days_between_payments: float ) -> float: """ >>> simple_interest(18000.0, 0.06, 3) @@ -42,7 +42,7 @@ def simple_interest( def compound_interest( principal: float, nominal_annual_interest_rate_percentage: float, - number_of_compounding_periods: int, + number_of_compounding_periods: float, ) -> float: """ >>> compound_interest(10000.0, 0.05, 3) @@ -77,6 +77,43 @@ def compound_interest( ) +def apr_interest( + principal: float, + nominal_annual_percentage_rate: float, + number_of_years: float, +) -> float: + """ + >>> apr_interest(10000.0, 0.05, 3) + 1618.223072263547 + >>> apr_interest(10000.0, 0.05, 1) + 512.6749646744732 + >>> apr_interest(0.5, 0.05, 3) + 0.08091115361317736 + >>> apr_interest(10000.0, 0.06, -4) + Traceback (most recent call last): + ... + ValueError: number_of_years must be > 0 + >>> apr_interest(10000.0, -3.5, 3.0) + Traceback (most recent call last): + ... + ValueError: nominal_annual_percentage_rate must be >= 0 + >>> apr_interest(-5500.0, 0.01, 5) + Traceback (most recent call last): + ... + ValueError: principal must be > 0 + """ + if number_of_years <= 0: + raise ValueError("number_of_years must be > 0") + if nominal_annual_percentage_rate < 0: + raise ValueError("nominal_annual_percentage_rate must be >= 0") + if principal <= 0: + raise ValueError("principal must be > 0") + + return compound_interest( + principal, nominal_annual_percentage_rate / 365, number_of_years * 365 + ) + + if __name__ == "__main__": import doctest From 0dee4a402c85981af0c2d4c53af27a69a7eb91bf Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 20 Jun 2023 15:56:14 +0200 Subject: [PATCH 684/726] [pre-commit.ci] pre-commit autoupdate (#8827) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/codespell-project/codespell: v2.2.4 → v2.2.5](https://github.com/codespell-project/codespell/compare/v2.2.4...v2.2.5) - [github.com/tox-dev/pyproject-fmt: 0.11.2 → 0.12.0](https://github.com/tox-dev/pyproject-fmt/compare/0.11.2...0.12.0) * updating DIRECTORY.md --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- DIRECTORY.md | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1d4b73681..591fd7819 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,14 +26,14 @@ repos: - id: black - repo: https://github.com/codespell-project/codespell - rev: v2.2.4 + rev: v2.2.5 hooks: - id: codespell additional_dependencies: - tomli - repo: https://github.com/tox-dev/pyproject-fmt - rev: "0.11.2" + rev: "0.12.0" hooks: - id: pyproject-fmt diff --git a/DIRECTORY.md b/DIRECTORY.md index 8511c261a..6ec8d5111 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -486,6 +486,9 @@ * [Test Linear Algebra](linear_algebra/src/test_linear_algebra.py) * [Transformations 2D](linear_algebra/src/transformations_2d.py) +## Linear Programming + * [Simplex](linear_programming/simplex.py) + ## Machine Learning * [Astar](machine_learning/astar.py) * [Data Transformations](machine_learning/data_transformations.py) From 07e68128883b84fb7e342c6bce88863a05fbbf62 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 20 Jun 2023 18:03:16 +0200 Subject: [PATCH 685/726] Update .pre-commit-config.yaml (#8828) * Update .pre-commit-config.yaml * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- pyproject.toml | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a52619668..1dcce044a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,21 +1,3 @@ -[tool.pytest.ini_options] -markers = [ - "mat_ops: mark a test as utilizing matrix operations.", -] -addopts = [ - "--durations=10", - "--doctest-modules", - "--showlocals", -] - -[tool.coverage.report] -omit = [".env/*"] -sort = "Cover" - -[tool.codespell] -ignore-words-list = "3rt,ans,crate,damon,fo,followings,hist,iff,kwanza,mater,secant,som,sur,tim,zar" -skip = "./.*,*.json,ciphers/prehistoric_men.txt,project_euler/problem_022/p022_names.txt,pyproject.toml,strings/dictionary.txt,strings/words.txt" - [tool.ruff] ignore = [ # `ruff rule S101` for a description of that rule "ARG001", # Unused function argument `amount` -- FIX ME? @@ -131,3 +113,21 @@ max-args = 10 # default: 5 max-branches = 20 # default: 12 max-returns = 8 # default: 6 max-statements = 88 # default: 50 + +[tool.pytest.ini_options] +markers = [ + "mat_ops: mark a test as utilizing matrix operations.", +] +addopts = [ + "--durations=10", + "--doctest-modules", + "--showlocals", +] + +[tool.coverage.report] +omit = [".env/*"] +sort = "Cover" + +[tool.codespell] +ignore-words-list = "3rt,ans,crate,damon,fo,followings,hist,iff,kwanza,mater,secant,som,sur,tim,zar" +skip = "./.*,*.json,ciphers/prehistoric_men.txt,project_euler/problem_022/p022_names.txt,pyproject.toml,strings/dictionary.txt,strings/words.txt" From 5b0890bd833eb85c58fae9afc4984d520e7e2ad6 Mon Sep 17 00:00:00 2001 From: "Linus M. Henkel" <86628476+linushenkel@users.noreply.github.com> Date: Thu, 22 Jun 2023 13:49:09 +0200 Subject: [PATCH 686/726] Dijkstra algorithm with binary grid (#8802) * Create TestShiva * Delete TestShiva * Implementation of the Dijkstra-Algorithm in a binary grid * Update double_ended_queue.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update least_common_multiple.py * Update sol1.py * Update pyproject.toml * Update pyproject.toml * https://github.com/astral-sh/ruff-pre-commit v0.0.274 --------- Co-authored-by: ShivaDahal99 <130563462+ShivaDahal99@users.noreply.github.com> Co-authored-by: jlhuhn <134317018+jlhuhn@users.noreply.github.com> Co-authored-by: Christian Clauss Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 +- data_structures/queue/double_ended_queue.py | 4 +- graphs/dijkstra_binary_grid.py | 89 +++++++++++++++++++++ maths/least_common_multiple.py | 6 +- project_euler/problem_054/sol1.py | 18 ++--- pyproject.toml | 1 + 6 files changed, 106 insertions(+), 16 deletions(-) create mode 100644 graphs/dijkstra_binary_grid.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 591fd7819..3d4cc4084 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,8 +15,8 @@ repos: hooks: - id: auto-walrus - - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.272 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.0.274 hooks: - id: ruff diff --git a/data_structures/queue/double_ended_queue.py b/data_structures/queue/double_ended_queue.py index 637b7f62f..2472371b4 100644 --- a/data_structures/queue/double_ended_queue.py +++ b/data_structures/queue/double_ended_queue.py @@ -32,7 +32,7 @@ class Deque: the number of nodes """ - __slots__ = ["_front", "_back", "_len"] + __slots__ = ("_front", "_back", "_len") @dataclass class _Node: @@ -54,7 +54,7 @@ class Deque: the current node of the iteration. """ - __slots__ = ["_cur"] + __slots__ = "_cur" def __init__(self, cur: Deque._Node | None) -> None: self._cur = cur diff --git a/graphs/dijkstra_binary_grid.py b/graphs/dijkstra_binary_grid.py new file mode 100644 index 000000000..c23d82343 --- /dev/null +++ b/graphs/dijkstra_binary_grid.py @@ -0,0 +1,89 @@ +""" +This script implements the Dijkstra algorithm on a binary grid. +The grid consists of 0s and 1s, where 1 represents +a walkable node and 0 represents an obstacle. +The algorithm finds the shortest path from a start node to a destination node. +Diagonal movement can be allowed or disallowed. +""" + +from heapq import heappop, heappush + +import numpy as np + + +def dijkstra( + grid: np.ndarray, + source: tuple[int, int], + destination: tuple[int, int], + allow_diagonal: bool, +) -> tuple[float | int, list[tuple[int, int]]]: + """ + Implements Dijkstra's algorithm on a binary grid. + + Args: + grid (np.ndarray): A 2D numpy array representing the grid. + 1 represents a walkable node and 0 represents an obstacle. + source (Tuple[int, int]): A tuple representing the start node. + destination (Tuple[int, int]): A tuple representing the + destination node. + allow_diagonal (bool): A boolean determining whether + diagonal movements are allowed. + + Returns: + Tuple[Union[float, int], List[Tuple[int, int]]]: + The shortest distance from the start node to the destination node + and the shortest path as a list of nodes. + + >>> dijkstra(np.array([[1, 1, 1], [0, 1, 0], [0, 1, 1]]), (0, 0), (2, 2), False) + (4.0, [(0, 0), (0, 1), (1, 1), (2, 1), (2, 2)]) + + >>> dijkstra(np.array([[1, 1, 1], [0, 1, 0], [0, 1, 1]]), (0, 0), (2, 2), True) + (2.0, [(0, 0), (1, 1), (2, 2)]) + + >>> dijkstra(np.array([[1, 1, 1], [0, 0, 1], [0, 1, 1]]), (0, 0), (2, 2), False) + (4.0, [(0, 0), (0, 1), (0, 2), (1, 2), (2, 2)]) + """ + rows, cols = grid.shape + dx = [-1, 1, 0, 0] + dy = [0, 0, -1, 1] + if allow_diagonal: + dx += [-1, -1, 1, 1] + dy += [-1, 1, -1, 1] + + queue, visited = [(0, source)], set() + matrix = np.full((rows, cols), np.inf) + matrix[source] = 0 + predecessors = np.empty((rows, cols), dtype=object) + predecessors[source] = None + + while queue: + (dist, (x, y)) = heappop(queue) + if (x, y) in visited: + continue + visited.add((x, y)) + + if (x, y) == destination: + path = [] + while (x, y) != source: + path.append((x, y)) + x, y = predecessors[x, y] + path.append(source) # add the source manually + path.reverse() + return matrix[destination], path + + for i in range(len(dx)): + nx, ny = x + dx[i], y + dy[i] + if 0 <= nx < rows and 0 <= ny < cols: + next_node = grid[nx][ny] + if next_node == 1 and matrix[nx, ny] > dist + 1: + heappush(queue, (dist + 1, (nx, ny))) + matrix[nx, ny] = dist + 1 + predecessors[nx, ny] = (x, y) + + return np.inf, [] + + +if __name__ == "__main__": + import doctest + + doctest.testmod() diff --git a/maths/least_common_multiple.py b/maths/least_common_multiple.py index 621d93720..10cc63ac7 100644 --- a/maths/least_common_multiple.py +++ b/maths/least_common_multiple.py @@ -67,7 +67,7 @@ def benchmark(): class TestLeastCommonMultiple(unittest.TestCase): - test_inputs = [ + test_inputs = ( (10, 20), (13, 15), (4, 31), @@ -77,8 +77,8 @@ class TestLeastCommonMultiple(unittest.TestCase): (12, 25), (10, 25), (6, 9), - ] - expected_results = [20, 195, 124, 210, 1462, 60, 300, 50, 18] + ) + expected_results = (20, 195, 124, 210, 1462, 60, 300, 50, 18) def test_lcm_function(self): for i, (first_num, second_num) in enumerate(self.test_inputs): diff --git a/project_euler/problem_054/sol1.py b/project_euler/problem_054/sol1.py index 74409f32c..86dfa5edd 100644 --- a/project_euler/problem_054/sol1.py +++ b/project_euler/problem_054/sol1.py @@ -47,18 +47,18 @@ import os class PokerHand: """Create an object representing a Poker Hand based on an input of a - string which represents the best 5 card combination from the player's hand + string which represents the best 5-card combination from the player's hand and board cards. Attributes: (read-only) - hand: string representing the hand consisting of five cards + hand: a string representing the hand consisting of five cards Methods: compare_with(opponent): takes in player's hand (self) and opponent's hand (opponent) and compares both hands according to the rules of Texas Hold'em. Returns one of 3 strings (Win, Loss, Tie) based on whether - player's hand is better than opponent's hand. + player's hand is better than the opponent's hand. hand_name(): Returns a string made up of two parts: hand name and high card. @@ -66,11 +66,11 @@ class PokerHand: Supported operators: Rich comparison operators: <, >, <=, >=, ==, != - Supported builtin methods and functions: + Supported built-in methods and functions: list.sort(), sorted() """ - _HAND_NAME = [ + _HAND_NAME = ( "High card", "One pair", "Two pairs", @@ -81,10 +81,10 @@ class PokerHand: "Four of a kind", "Straight flush", "Royal flush", - ] + ) - _CARD_NAME = [ - "", # placeholder as lists are zero indexed + _CARD_NAME = ( + "", # placeholder as tuples are zero-indexed "One", "Two", "Three", @@ -99,7 +99,7 @@ class PokerHand: "Queen", "King", "Ace", - ] + ) def __init__(self, hand: str) -> None: """ diff --git a/pyproject.toml b/pyproject.toml index 1dcce044a..4f21a9519 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -103,6 +103,7 @@ max-complexity = 17 # default: 10 "machine_learning/linear_discriminant_analysis.py" = ["ARG005"] "machine_learning/sequential_minimum_optimization.py" = ["SIM115"] "matrix/sherman_morrison.py" = ["SIM103", "SIM114"] +"other/l*u_cache.py" = ["RUF012"] "physics/newtons_second_law_of_motion.py" = ["BLE001"] "project_euler/problem_099/sol1.py" = ["SIM115"] "sorts/external_sort.py" = ["SIM115"] From 5ffe601c86a9b44691a4dce37480c6d904102d49 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Thu, 22 Jun 2023 05:24:34 -0700 Subject: [PATCH 687/726] Fix `mypy` errors in `maths/sigmoid_linear_unit.py` (#8786) * updating DIRECTORY.md * Fix mypy errors in sigmoid_linear_unit.py * updating DIRECTORY.md * updating DIRECTORY.md --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- maths/sigmoid_linear_unit.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/maths/sigmoid_linear_unit.py b/maths/sigmoid_linear_unit.py index a8ada10dd..0ee09bf82 100644 --- a/maths/sigmoid_linear_unit.py +++ b/maths/sigmoid_linear_unit.py @@ -17,7 +17,7 @@ This script is inspired by a corresponding research paper. import numpy as np -def sigmoid(vector: np.array) -> np.array: +def sigmoid(vector: np.ndarray) -> np.ndarray: """ Mathematical function sigmoid takes a vector x of K real numbers as input and returns 1/ (1 + e^-x). @@ -29,17 +29,15 @@ def sigmoid(vector: np.array) -> np.array: return 1 / (1 + np.exp(-vector)) -def sigmoid_linear_unit(vector: np.array) -> np.array: +def sigmoid_linear_unit(vector: np.ndarray) -> np.ndarray: """ Implements the Sigmoid Linear Unit (SiLU) or swish function Parameters: - vector (np.array): A numpy array consisting of real - values. + vector (np.ndarray): A numpy array consisting of real values Returns: - swish_vec (np.array): The input numpy array, after applying - swish. + swish_vec (np.ndarray): The input numpy array, after applying swish Examples: >>> sigmoid_linear_unit(np.array([-1.0, 1.0, 2.0])) From f54a9668103e560f20b50559fb54ac38a74d1fe8 Mon Sep 17 00:00:00 2001 From: Jan-Lukas Huhn <134317018+jlhuhn@users.noreply.github.com> Date: Thu, 22 Jun 2023 14:31:48 +0200 Subject: [PATCH 688/726] Energy conversions (#8801) * Create TestShiva * Delete TestShiva * Create energy_conversions.py * Update conversions/energy_conversions.py Co-authored-by: Caeden Perelli-Harris --------- Co-authored-by: ShivaDahal99 <130563462+ShivaDahal99@users.noreply.github.com> Co-authored-by: Caeden Perelli-Harris --- conversions/energy_conversions.py | 114 ++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 conversions/energy_conversions.py diff --git a/conversions/energy_conversions.py b/conversions/energy_conversions.py new file mode 100644 index 000000000..51de6b313 --- /dev/null +++ b/conversions/energy_conversions.py @@ -0,0 +1,114 @@ +""" +Conversion of energy units. + +Available units: joule, kilojoule, megajoule, gigajoule,\ + wattsecond, watthour, kilowatthour, newtonmeter, calorie_nutr,\ + kilocalorie_nutr, electronvolt, britishthermalunit_it, footpound + +USAGE : +-> Import this file into their respective project. +-> Use the function energy_conversion() for conversion of energy units. +-> Parameters : + -> from_type : From which type you want to convert + -> to_type : To which type you want to convert + -> value : the value which you want to convert + +REFERENCES : +-> Wikipedia reference: https://en.wikipedia.org/wiki/Units_of_energy +-> Wikipedia reference: https://en.wikipedia.org/wiki/Joule +-> Wikipedia reference: https://en.wikipedia.org/wiki/Kilowatt-hour +-> Wikipedia reference: https://en.wikipedia.org/wiki/Newton-metre +-> Wikipedia reference: https://en.wikipedia.org/wiki/Calorie +-> Wikipedia reference: https://en.wikipedia.org/wiki/Electronvolt +-> Wikipedia reference: https://en.wikipedia.org/wiki/British_thermal_unit +-> Wikipedia reference: https://en.wikipedia.org/wiki/Foot-pound_(energy) +-> Unit converter reference: https://www.unitconverters.net/energy-converter.html +""" + +ENERGY_CONVERSION: dict[str, float] = { + "joule": 1.0, + "kilojoule": 1_000, + "megajoule": 1_000_000, + "gigajoule": 1_000_000_000, + "wattsecond": 1.0, + "watthour": 3_600, + "kilowatthour": 3_600_000, + "newtonmeter": 1.0, + "calorie_nutr": 4_186.8, + "kilocalorie_nutr": 4_186_800.00, + "electronvolt": 1.602_176_634e-19, + "britishthermalunit_it": 1_055.055_85, + "footpound": 1.355_818, +} + + +def energy_conversion(from_type: str, to_type: str, value: float) -> float: + """ + Conversion of energy units. + >>> energy_conversion("joule", "joule", 1) + 1.0 + >>> energy_conversion("joule", "kilojoule", 1) + 0.001 + >>> energy_conversion("joule", "megajoule", 1) + 1e-06 + >>> energy_conversion("joule", "gigajoule", 1) + 1e-09 + >>> energy_conversion("joule", "wattsecond", 1) + 1.0 + >>> energy_conversion("joule", "watthour", 1) + 0.0002777777777777778 + >>> energy_conversion("joule", "kilowatthour", 1) + 2.7777777777777776e-07 + >>> energy_conversion("joule", "newtonmeter", 1) + 1.0 + >>> energy_conversion("joule", "calorie_nutr", 1) + 0.00023884589662749592 + >>> energy_conversion("joule", "kilocalorie_nutr", 1) + 2.388458966274959e-07 + >>> energy_conversion("joule", "electronvolt", 1) + 6.241509074460763e+18 + >>> energy_conversion("joule", "britishthermalunit_it", 1) + 0.0009478171226670134 + >>> energy_conversion("joule", "footpound", 1) + 0.7375621211696556 + >>> energy_conversion("joule", "megajoule", 1000) + 0.001 + >>> energy_conversion("calorie_nutr", "kilocalorie_nutr", 1000) + 1.0 + >>> energy_conversion("kilowatthour", "joule", 10) + 36000000.0 + >>> energy_conversion("britishthermalunit_it", "footpound", 1) + 778.1692306784539 + >>> energy_conversion("watthour", "joule", "a") # doctest: +ELLIPSIS + Traceback (most recent call last): + ... + TypeError: unsupported operand type(s) for /: 'str' and 'float' + >>> energy_conversion("wrongunit", "joule", 1) # doctest: +ELLIPSIS + Traceback (most recent call last): + ... + ValueError: Incorrect 'from_type' or 'to_type' value: 'wrongunit', 'joule' + Valid values are: joule, ... footpound + >>> energy_conversion("joule", "wrongunit", 1) # doctest: +ELLIPSIS + Traceback (most recent call last): + ... + ValueError: Incorrect 'from_type' or 'to_type' value: 'joule', 'wrongunit' + Valid values are: joule, ... footpound + >>> energy_conversion("123", "abc", 1) # doctest: +ELLIPSIS + Traceback (most recent call last): + ... + ValueError: Incorrect 'from_type' or 'to_type' value: '123', 'abc' + Valid values are: joule, ... footpound + """ + if to_type not in ENERGY_CONVERSION or from_type not in ENERGY_CONVERSION: + msg = ( + f"Incorrect 'from_type' or 'to_type' value: {from_type!r}, {to_type!r}\n" + f"Valid values are: {', '.join(ENERGY_CONVERSION)}" + ) + raise ValueError(msg) + return value * ENERGY_CONVERSION[from_type] / ENERGY_CONVERSION[to_type] + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 331585f3f866e210e23d11700b09a8770a1c2490 Mon Sep 17 00:00:00 2001 From: Himanshu Tomar Date: Fri, 23 Jun 2023 13:56:05 +0530 Subject: [PATCH 689/726] Algorithm: Calculating Product Sum from a Special Array with Nested Structures (#8761) * Added minimum waiting time problem solution using greedy algorithm * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * ruff --fix * Add type hints * Added two more doc test * Removed unnecessary comments * updated type hints * Updated the code as per the code review * Added recursive algo to calculate product sum from an array * Added recursive algo to calculate product sum from an array * Update doc string * Added doctest for product_sum function * Updated the code and added more doctests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Added more test coverage for product_sum method * Update product_sum.py --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- DIRECTORY.md | 1 + data_structures/arrays/product_sum.py | 98 +++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 data_structures/arrays/product_sum.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 6ec8d5111..83389dab1 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -166,6 +166,7 @@ * Arrays * [Permutations](data_structures/arrays/permutations.py) * [Prefix Sum](data_structures/arrays/prefix_sum.py) + * [Product Sum Array](data_structures/arrays/product_sum.py) * Binary Tree * [Avl Tree](data_structures/binary_tree/avl_tree.py) * [Basic Binary Tree](data_structures/binary_tree/basic_binary_tree.py) diff --git a/data_structures/arrays/product_sum.py b/data_structures/arrays/product_sum.py new file mode 100644 index 000000000..4fb906f36 --- /dev/null +++ b/data_structures/arrays/product_sum.py @@ -0,0 +1,98 @@ +""" +Calculate the Product Sum from a Special Array. +reference: https://dev.to/sfrasica/algorithms-product-sum-from-an-array-dc6 + +Python doctests can be run with the following command: +python -m doctest -v product_sum.py + +Calculate the product sum of a "special" array which can contain integers or nested +arrays. The product sum is obtained by adding all elements and multiplying by their +respective depths. + +For example, in the array [x, y], the product sum is (x + y). In the array [x, [y, z]], +the product sum is x + 2 * (y + z). In the array [x, [y, [z]]], +the product sum is x + 2 * (y + 3z). + +Example Input: +[5, 2, [-7, 1], 3, [6, [-13, 8], 4]] +Output: 12 + +""" + + +def product_sum(arr: list[int | list], depth: int) -> int: + """ + Recursively calculates the product sum of an array. + + The product sum of an array is defined as the sum of its elements multiplied by + their respective depths. If an element is a list, its product sum is calculated + recursively by multiplying the sum of its elements with its depth plus one. + + Args: + arr: The array of integers and nested lists. + depth: The current depth level. + + Returns: + int: The product sum of the array. + + Examples: + >>> product_sum([1, 2, 3], 1) + 6 + >>> product_sum([-1, 2, [-3, 4]], 2) + 8 + >>> product_sum([1, 2, 3], -1) + -6 + >>> product_sum([1, 2, 3], 0) + 0 + >>> product_sum([1, 2, 3], 7) + 42 + >>> product_sum((1, 2, 3), 7) + 42 + >>> product_sum({1, 2, 3}, 7) + 42 + >>> product_sum([1, -1], 1) + 0 + >>> product_sum([1, -2], 1) + -1 + >>> product_sum([-3.5, [1, [0.5]]], 1) + 1.5 + + """ + total_sum = 0 + for ele in arr: + total_sum += product_sum(ele, depth + 1) if isinstance(ele, list) else ele + return total_sum * depth + + +def product_sum_array(array: list[int | list]) -> int: + """ + Calculates the product sum of an array. + + Args: + array (List[Union[int, List]]): The array of integers and nested lists. + + Returns: + int: The product sum of the array. + + Examples: + >>> product_sum_array([1, 2, 3]) + 6 + >>> product_sum_array([1, [2, 3]]) + 11 + >>> product_sum_array([1, [2, [3, 4]]]) + 47 + >>> product_sum_array([0]) + 0 + >>> product_sum_array([-3.5, [1, [0.5]]]) + 1.5 + >>> product_sum_array([1, -2]) + -1 + + """ + return product_sum(array, 1) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 267a8b72f97762383e7c313ed20df859115e2815 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Fri, 23 Jun 2023 06:56:58 -0700 Subject: [PATCH 690/726] Clarify how to add issue numbers in PR template and CONTRIBUTING.md (#8833) * updating DIRECTORY.md * Clarify wording in PR template * Clarify CONTRIBUTING.md wording about adding issue numbers * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Add suggested change from review to CONTRIBUTING.md Co-authored-by: Christian Clauss * Incorporate review edit to CONTRIBUTING.md Co-authored-by: Christian Clauss --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .github/pull_request_template.md | 2 +- CONTRIBUTING.md | 7 ++++++- DIRECTORY.md | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index b3ba8baf9..1f9797fae 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -17,4 +17,4 @@ * [ ] All function parameters and return values are annotated with Python [type hints](https://docs.python.org/3/library/typing.html). * [ ] All functions have [doctests](https://docs.python.org/3/library/doctest.html) that pass the automated testing. * [ ] All new algorithms include at least one URL that points to Wikipedia or another similar explanation. -* [ ] If this pull request resolves one or more open issues then the commit message contains `Fixes: #{$ISSUE_NO}`. +* [ ] If this pull request resolves one or more open issues then the description above includes the issue number(s) with a [closing keyword](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue): "Fixes #ISSUE-NUMBER". diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2bb0c2e39..618cca868 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -25,7 +25,12 @@ We appreciate any contribution, from fixing a grammar mistake in a comment to im Your contribution will be tested by our [automated testing on GitHub Actions](https://github.com/TheAlgorithms/Python/actions) to save time and mental energy. After you have submitted your pull request, you should see the GitHub Actions tests start to run at the bottom of your submission page. If those tests fail, then click on the ___details___ button try to read through the GitHub Actions output to understand the failure. If you do not understand, please leave a comment on your submission page and a community member will try to help. -Please help us keep our issue list small by adding fixes: #{$ISSUE_NO} to the commit message of pull requests that resolve open issues. GitHub will use this tag to auto-close the issue when the PR is merged. +Please help us keep our issue list small by adding `Fixes #{$ISSUE_NUMBER}` to the description of pull requests that resolve open issues. +For example, if your pull request fixes issue #10, then please add the following to its description: +``` +Fixes #10 +``` +GitHub will use this tag to [auto-close the issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) if and when the PR is merged. #### What is an Algorithm? diff --git a/DIRECTORY.md b/DIRECTORY.md index 83389dab1..1414aacf9 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -146,6 +146,7 @@ * [Decimal To Binary Recursion](conversions/decimal_to_binary_recursion.py) * [Decimal To Hexadecimal](conversions/decimal_to_hexadecimal.py) * [Decimal To Octal](conversions/decimal_to_octal.py) + * [Energy Conversions](conversions/energy_conversions.py) * [Excel Title To Column](conversions/excel_title_to_column.py) * [Hex To Bin](conversions/hex_to_bin.py) * [Hexadecimal To Decimal](conversions/hexadecimal_to_decimal.py) @@ -411,6 +412,7 @@ * [Dijkstra 2](graphs/dijkstra_2.py) * [Dijkstra Algorithm](graphs/dijkstra_algorithm.py) * [Dijkstra Alternate](graphs/dijkstra_alternate.py) + * [Dijkstra Binary Grid](graphs/dijkstra_binary_grid.py) * [Dinic](graphs/dinic.py) * [Directed And Undirected (Weighted) Graph](graphs/directed_and_undirected_(weighted)_graph.py) * [Edmonds Karp Multiple Source And Sink](graphs/edmonds_karp_multiple_source_and_sink.py) From 3bfa89dacf877b1d7a62b14f82d54e8de99a838e Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sun, 25 Jun 2023 18:28:01 +0200 Subject: [PATCH 691/726] GitHub Actions build: Add more tests (#8837) * GitHub Actions build: Add more tests Re-enable some tests that were disabled in #6591. Fixes #8818 * updating DIRECTORY.md * TODO: Re-enable quantum tests * fails: pytest quantum/bb84.py quantum/q_fourier_transform.py --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .github/workflows/build.yml | 7 +++---- DIRECTORY.md | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6b9cc890b..5229edaf8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,11 +22,10 @@ jobs: python -m pip install --upgrade pip setuptools six wheel python -m pip install pytest-cov -r requirements.txt - name: Run tests - # See: #6591 for re-enabling tests on Python v3.11 + # TODO: #8818 Re-enable quantum tests run: pytest - --ignore=computer_vision/cnn_classification.py - --ignore=machine_learning/lstm/lstm_prediction.py - --ignore=quantum/ + --ignore=quantum/bb84.py + --ignore=quantum/q_fourier_transform.py --ignore=project_euler/ --ignore=scripts/validate_solutions.py --cov-report=term-missing:skip-covered diff --git a/DIRECTORY.md b/DIRECTORY.md index 1414aacf9..0c21b9537 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -167,7 +167,7 @@ * Arrays * [Permutations](data_structures/arrays/permutations.py) * [Prefix Sum](data_structures/arrays/prefix_sum.py) - * [Product Sum Array](data_structures/arrays/product_sum.py) + * [Product Sum](data_structures/arrays/product_sum.py) * Binary Tree * [Avl Tree](data_structures/binary_tree/avl_tree.py) * [Basic Binary Tree](data_structures/binary_tree/basic_binary_tree.py) From d764eec655c1c51f5ef3490d27ea72430191a000 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 26 Jun 2023 05:24:50 +0200 Subject: [PATCH 692/726] Fix failing pytest quantum/bb84.py (#8838) * Fix failing pytest quantum/bb84.py * Update bb84.py test results to match current qiskit --- .github/workflows/build.yml | 1 - quantum/bb84.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5229edaf8..fc8cb6369 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,7 +24,6 @@ jobs: - name: Run tests # TODO: #8818 Re-enable quantum tests run: pytest - --ignore=quantum/bb84.py --ignore=quantum/q_fourier_transform.py --ignore=project_euler/ --ignore=scripts/validate_solutions.py diff --git a/quantum/bb84.py b/quantum/bb84.py index 60d64371f..e90a11c2a 100644 --- a/quantum/bb84.py +++ b/quantum/bb84.py @@ -64,10 +64,10 @@ def bb84(key_len: int = 8, seed: int | None = None) -> str: key: The key generated using BB84 protocol. >>> bb84(16, seed=0) - '1101101100010000' + '0111110111010010' >>> bb84(8, seed=0) - '01011011' + '10110001' """ # Set up the random number generator. rng = np.random.default_rng(seed=seed) From 62dcbea943e8cc4ea4d83eff115c4e6f6a4808af Mon Sep 17 00:00:00 2001 From: duongoku Date: Mon, 26 Jun 2023 14:39:18 +0700 Subject: [PATCH 693/726] Add power sum problem (#8832) * Add powersum problem * Add doctest * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Add more doctests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Add more doctests * Improve paramater name * Fix line too long * Remove global variables * Apply suggestions from code review * Apply suggestions from code review --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- backtracking/power_sum.py | 93 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 backtracking/power_sum.py diff --git a/backtracking/power_sum.py b/backtracking/power_sum.py new file mode 100644 index 000000000..fcf1429f8 --- /dev/null +++ b/backtracking/power_sum.py @@ -0,0 +1,93 @@ +""" +Problem source: https://www.hackerrank.com/challenges/the-power-sum/problem +Find the number of ways that a given integer X, can be expressed as the sum +of the Nth powers of unique, natural numbers. For example, if X=13 and N=2. +We have to find all combinations of unique squares adding up to 13. +The only solution is 2^2+3^2. Constraints: 1<=X<=1000, 2<=N<=10. +""" + +from math import pow + + +def backtrack( + needed_sum: int, + power: int, + current_number: int, + current_sum: int, + solutions_count: int, +) -> tuple[int, int]: + """ + >>> backtrack(13, 2, 1, 0, 0) + (0, 1) + >>> backtrack(100, 2, 1, 0, 0) + (0, 3) + >>> backtrack(100, 3, 1, 0, 0) + (0, 1) + >>> backtrack(800, 2, 1, 0, 0) + (0, 561) + >>> backtrack(1000, 10, 1, 0, 0) + (0, 0) + >>> backtrack(400, 2, 1, 0, 0) + (0, 55) + >>> backtrack(50, 1, 1, 0, 0) + (0, 3658) + """ + if current_sum == needed_sum: + # If the sum of the powers is equal to needed_sum, then we have a solution. + solutions_count += 1 + return current_sum, solutions_count + + i_to_n = int(pow(current_number, power)) + if current_sum + i_to_n <= needed_sum: + # If the sum of the powers is less than needed_sum, then continue adding powers. + current_sum += i_to_n + current_sum, solutions_count = backtrack( + needed_sum, power, current_number + 1, current_sum, solutions_count + ) + current_sum -= i_to_n + if i_to_n < needed_sum: + # If the power of i is less than needed_sum, then try with the next power. + current_sum, solutions_count = backtrack( + needed_sum, power, current_number + 1, current_sum, solutions_count + ) + return current_sum, solutions_count + + +def solve(needed_sum: int, power: int) -> int: + """ + >>> solve(13, 2) + 1 + >>> solve(100, 2) + 3 + >>> solve(100, 3) + 1 + >>> solve(800, 2) + 561 + >>> solve(1000, 10) + 0 + >>> solve(400, 2) + 55 + >>> solve(50, 1) + Traceback (most recent call last): + ... + ValueError: Invalid input + needed_sum must be between 1 and 1000, power between 2 and 10. + >>> solve(-10, 5) + Traceback (most recent call last): + ... + ValueError: Invalid input + needed_sum must be between 1 and 1000, power between 2 and 10. + """ + if not (1 <= needed_sum <= 1000 and 2 <= power <= 10): + raise ValueError( + "Invalid input\n" + "needed_sum must be between 1 and 1000, power between 2 and 10." + ) + + return backtrack(needed_sum, power, 1, 0, 0)[1] # Return the solutions_count + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 69f20033e55ae62c337e2fb2146aea5fabf3e5a0 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Mon, 26 Jun 2023 02:15:31 -0700 Subject: [PATCH 694/726] Remove duplicate implementation of Collatz sequence (#8836) * updating DIRECTORY.md * Remove duplicate implementation of Collatz sequence * updating DIRECTORY.md * Add suggestions from PR review --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 1 - maths/3n_plus_1.py | 151 -------------------------------------- maths/collatz_sequence.py | 69 +++++++++++------ 3 files changed, 46 insertions(+), 175 deletions(-) delete mode 100644 maths/3n_plus_1.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 0c21b9537..1e0e450bc 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -522,7 +522,6 @@ * [Xgboost Regressor](machine_learning/xgboost_regressor.py) ## Maths - * [3N Plus 1](maths/3n_plus_1.py) * [Abs](maths/abs.py) * [Add](maths/add.py) * [Addition Without Arithmetic](maths/addition_without_arithmetic.py) diff --git a/maths/3n_plus_1.py b/maths/3n_plus_1.py deleted file mode 100644 index f9f6dfeb9..000000000 --- a/maths/3n_plus_1.py +++ /dev/null @@ -1,151 +0,0 @@ -from __future__ import annotations - - -def n31(a: int) -> tuple[list[int], int]: - """ - Returns the Collatz sequence and its length of any positive integer. - >>> n31(4) - ([4, 2, 1], 3) - """ - - if not isinstance(a, int): - msg = f"Must be int, not {type(a).__name__}" - raise TypeError(msg) - if a < 1: - msg = f"Given integer must be positive, not {a}" - raise ValueError(msg) - - path = [a] - while a != 1: - if a % 2 == 0: - a //= 2 - else: - a = 3 * a + 1 - path.append(a) - return path, len(path) - - -def test_n31(): - """ - >>> test_n31() - """ - assert n31(4) == ([4, 2, 1], 3) - assert n31(11) == ([11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1], 15) - assert n31(31) == ( - [ - 31, - 94, - 47, - 142, - 71, - 214, - 107, - 322, - 161, - 484, - 242, - 121, - 364, - 182, - 91, - 274, - 137, - 412, - 206, - 103, - 310, - 155, - 466, - 233, - 700, - 350, - 175, - 526, - 263, - 790, - 395, - 1186, - 593, - 1780, - 890, - 445, - 1336, - 668, - 334, - 167, - 502, - 251, - 754, - 377, - 1132, - 566, - 283, - 850, - 425, - 1276, - 638, - 319, - 958, - 479, - 1438, - 719, - 2158, - 1079, - 3238, - 1619, - 4858, - 2429, - 7288, - 3644, - 1822, - 911, - 2734, - 1367, - 4102, - 2051, - 6154, - 3077, - 9232, - 4616, - 2308, - 1154, - 577, - 1732, - 866, - 433, - 1300, - 650, - 325, - 976, - 488, - 244, - 122, - 61, - 184, - 92, - 46, - 23, - 70, - 35, - 106, - 53, - 160, - 80, - 40, - 20, - 10, - 5, - 16, - 8, - 4, - 2, - 1, - ], - 107, - ) - - -if __name__ == "__main__": - num = 4 - path, length = n31(num) - print(f"The Collatz sequence of {num} took {length} steps. \nPath: {path}") diff --git a/maths/collatz_sequence.py b/maths/collatz_sequence.py index 7b3636de6..4f3aa5582 100644 --- a/maths/collatz_sequence.py +++ b/maths/collatz_sequence.py @@ -1,43 +1,66 @@ +""" +The Collatz conjecture is a famous unsolved problem in mathematics. Given a starting +positive integer, define the following sequence: +- If the current term n is even, then the next term is n/2. +- If the current term n is odd, then the next term is 3n + 1. +The conjecture claims that this sequence will always reach 1 for any starting number. + +Other names for this problem include the 3n + 1 problem, the Ulam conjecture, Kakutani's +problem, the Thwaites conjecture, Hasse's algorithm, the Syracuse problem, and the +hailstone sequence. + +Reference: https://en.wikipedia.org/wiki/Collatz_conjecture +""" + from __future__ import annotations +from collections.abc import Generator -def collatz_sequence(n: int) -> list[int]: + +def collatz_sequence(n: int) -> Generator[int, None, None]: """ - Collatz conjecture: start with any positive integer n. The next term is - obtained as follows: - If n term is even, the next term is: n / 2 . - If n is odd, the next term is: 3 * n + 1. - - The conjecture states the sequence will always reach 1 for any starting value n. - Example: - >>> collatz_sequence(2.1) + Generate the Collatz sequence starting at n. + >>> tuple(collatz_sequence(2.1)) Traceback (most recent call last): ... - Exception: Sequence only defined for natural numbers - >>> collatz_sequence(0) + Exception: Sequence only defined for positive integers + >>> tuple(collatz_sequence(0)) Traceback (most recent call last): ... - Exception: Sequence only defined for natural numbers - >>> collatz_sequence(43) # doctest: +NORMALIZE_WHITESPACE - [43, 130, 65, 196, 98, 49, 148, 74, 37, 112, 56, 28, 14, 7, - 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1] + Exception: Sequence only defined for positive integers + >>> tuple(collatz_sequence(4)) + (4, 2, 1) + >>> tuple(collatz_sequence(11)) + (11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1) + >>> tuple(collatz_sequence(31)) # doctest: +NORMALIZE_WHITESPACE + (31, 94, 47, 142, 71, 214, 107, 322, 161, 484, 242, 121, 364, 182, 91, 274, 137, + 412, 206, 103, 310, 155, 466, 233, 700, 350, 175, 526, 263, 790, 395, 1186, 593, + 1780, 890, 445, 1336, 668, 334, 167, 502, 251, 754, 377, 1132, 566, 283, 850, 425, + 1276, 638, 319, 958, 479, 1438, 719, 2158, 1079, 3238, 1619, 4858, 2429, 7288, 3644, + 1822, 911, 2734, 1367, 4102, 2051, 6154, 3077, 9232, 4616, 2308, 1154, 577, 1732, + 866, 433, 1300, 650, 325, 976, 488, 244, 122, 61, 184, 92, 46, 23, 70, 35, 106, 53, + 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1) + >>> tuple(collatz_sequence(43)) # doctest: +NORMALIZE_WHITESPACE + (43, 130, 65, 196, 98, 49, 148, 74, 37, 112, 56, 28, 14, 7, 22, 11, 34, 17, 52, 26, + 13, 40, 20, 10, 5, 16, 8, 4, 2, 1) """ - if not isinstance(n, int) or n < 1: - raise Exception("Sequence only defined for natural numbers") + raise Exception("Sequence only defined for positive integers") - sequence = [n] + yield n while n != 1: - n = 3 * n + 1 if n & 1 else n // 2 - sequence.append(n) - return sequence + if n % 2 == 0: + n //= 2 + else: + n = 3 * n + 1 + yield n def main(): n = 43 - sequence = collatz_sequence(n) + sequence = tuple(collatz_sequence(n)) print(sequence) - print(f"collatz sequence from {n} took {len(sequence)} steps.") + print(f"Collatz sequence from {n} took {len(sequence)} steps.") if __name__ == "__main__": From 929d3d9219020d2978d5560e3b931df69a6f2d50 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 27 Jun 2023 07:23:54 +0200 Subject: [PATCH 695/726] [pre-commit.ci] pre-commit autoupdate (#8842) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.0.274 → v0.0.275](https://github.com/astral-sh/ruff-pre-commit/compare/v0.0.274...v0.0.275) - [github.com/tox-dev/pyproject-fmt: 0.12.0 → 0.12.1](https://github.com/tox-dev/pyproject-fmt/compare/0.12.0...0.12.1) - [github.com/pre-commit/mirrors-mypy: v1.3.0 → v1.4.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.3.0...v1.4.1) * updating DIRECTORY.md --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- DIRECTORY.md | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3d4cc4084..1d92d2ff3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.0.274 + rev: v0.0.275 hooks: - id: ruff @@ -33,7 +33,7 @@ repos: - tomli - repo: https://github.com/tox-dev/pyproject-fmt - rev: "0.12.0" + rev: "0.12.1" hooks: - id: pyproject-fmt @@ -51,7 +51,7 @@ repos: - id: validate-pyproject - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.3.0 + rev: v1.4.1 hooks: - id: mypy args: diff --git a/DIRECTORY.md b/DIRECTORY.md index 1e0e450bc..d25d665ef 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -29,6 +29,7 @@ * [Minmax](backtracking/minmax.py) * [N Queens](backtracking/n_queens.py) * [N Queens Math](backtracking/n_queens_math.py) + * [Power Sum](backtracking/power_sum.py) * [Rat In Maze](backtracking/rat_in_maze.py) * [Sudoku](backtracking/sudoku.py) * [Sum Of Subsets](backtracking/sum_of_subsets.py) From c9ee6ed1887fadd25c1c43c31ed55a99b2be5f24 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 4 Jul 2023 00:20:35 +0200 Subject: [PATCH 696/726] [pre-commit.ci] pre-commit autoupdate (#8853) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.0.275 → v0.0.276](https://github.com/astral-sh/ruff-pre-commit/compare/v0.0.275...v0.0.276) * Update double_ended_queue.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update double_ended_queue.py --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .pre-commit-config.yaml | 2 +- data_structures/queue/double_ended_queue.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1d92d2ff3..42ebeed14 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.0.275 + rev: v0.0.276 hooks: - id: ruff diff --git a/data_structures/queue/double_ended_queue.py b/data_structures/queue/double_ended_queue.py index 2472371b4..44dc863b9 100644 --- a/data_structures/queue/double_ended_queue.py +++ b/data_structures/queue/double_ended_queue.py @@ -54,7 +54,7 @@ class Deque: the current node of the iteration. """ - __slots__ = "_cur" + __slots__ = ("_cur",) def __init__(self, cur: Deque._Node | None) -> None: self._cur = cur From a0eec90466beeb3b6ce0f7afd905f96454e9b14c Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Tue, 11 Jul 2023 02:44:12 -0700 Subject: [PATCH 697/726] Consolidate duplicate implementations of max subarray (#8849) * Remove max subarray sum duplicate implementations * updating DIRECTORY.md * Rename max_sum_contiguous_subsequence.py * Fix typo in dynamic_programming/max_subarray_sum.py * Remove duplicate divide and conquer max subarray * updating DIRECTORY.md --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 8 +- divide_and_conquer/max_subarray.py | 112 ++++++++++++++++++ divide_and_conquer/max_subarray_sum.py | 78 ------------ dynamic_programming/max_sub_array.py | 93 --------------- dynamic_programming/max_subarray_sum.py | 60 ++++++++++ .../max_sum_contiguous_subsequence.py | 20 ---- maths/kadanes.py | 63 ---------- maths/largest_subarray_sum.py | 21 ---- other/maximum_subarray.py | 32 ----- 9 files changed, 174 insertions(+), 313 deletions(-) create mode 100644 divide_and_conquer/max_subarray.py delete mode 100644 divide_and_conquer/max_subarray_sum.py delete mode 100644 dynamic_programming/max_sub_array.py create mode 100644 dynamic_programming/max_subarray_sum.py delete mode 100644 dynamic_programming/max_sum_contiguous_subsequence.py delete mode 100644 maths/kadanes.py delete mode 100644 maths/largest_subarray_sum.py delete mode 100644 other/maximum_subarray.py diff --git a/DIRECTORY.md b/DIRECTORY.md index d25d665ef..77938f450 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -293,7 +293,7 @@ * [Inversions](divide_and_conquer/inversions.py) * [Kth Order Statistic](divide_and_conquer/kth_order_statistic.py) * [Max Difference Pair](divide_and_conquer/max_difference_pair.py) - * [Max Subarray Sum](divide_and_conquer/max_subarray_sum.py) + * [Max Subarray](divide_and_conquer/max_subarray.py) * [Mergesort](divide_and_conquer/mergesort.py) * [Peak](divide_and_conquer/peak.py) * [Power](divide_and_conquer/power.py) @@ -324,8 +324,7 @@ * [Matrix Chain Order](dynamic_programming/matrix_chain_order.py) * [Max Non Adjacent Sum](dynamic_programming/max_non_adjacent_sum.py) * [Max Product Subarray](dynamic_programming/max_product_subarray.py) - * [Max Sub Array](dynamic_programming/max_sub_array.py) - * [Max Sum Contiguous Subsequence](dynamic_programming/max_sum_contiguous_subsequence.py) + * [Max Subarray Sum](dynamic_programming/max_subarray_sum.py) * [Min Distance Up Bottom](dynamic_programming/min_distance_up_bottom.py) * [Minimum Coin Change](dynamic_programming/minimum_coin_change.py) * [Minimum Cost Path](dynamic_programming/minimum_cost_path.py) @@ -591,12 +590,10 @@ * [Is Square Free](maths/is_square_free.py) * [Jaccard Similarity](maths/jaccard_similarity.py) * [Juggler Sequence](maths/juggler_sequence.py) - * [Kadanes](maths/kadanes.py) * [Karatsuba](maths/karatsuba.py) * [Krishnamurthy Number](maths/krishnamurthy_number.py) * [Kth Lexicographic Permutation](maths/kth_lexicographic_permutation.py) * [Largest Of Very Large Numbers](maths/largest_of_very_large_numbers.py) - * [Largest Subarray Sum](maths/largest_subarray_sum.py) * [Least Common Multiple](maths/least_common_multiple.py) * [Line Length](maths/line_length.py) * [Liouville Lambda](maths/liouville_lambda.py) @@ -733,7 +730,6 @@ * [Linear Congruential Generator](other/linear_congruential_generator.py) * [Lru Cache](other/lru_cache.py) * [Magicdiamondpattern](other/magicdiamondpattern.py) - * [Maximum Subarray](other/maximum_subarray.py) * [Maximum Subsequence](other/maximum_subsequence.py) * [Nested Brackets](other/nested_brackets.py) * [Number Container System](other/number_container_system.py) diff --git a/divide_and_conquer/max_subarray.py b/divide_and_conquer/max_subarray.py new file mode 100644 index 000000000..851ef621a --- /dev/null +++ b/divide_and_conquer/max_subarray.py @@ -0,0 +1,112 @@ +""" +The maximum subarray problem is the task of finding the continuous subarray that has the +maximum sum within a given array of numbers. For example, given the array +[-2, 1, -3, 4, -1, 2, 1, -5, 4], the contiguous subarray with the maximum sum is +[4, -1, 2, 1], which has a sum of 6. + +This divide-and-conquer algorithm finds the maximum subarray in O(n log n) time. +""" +from __future__ import annotations + +import time +from collections.abc import Sequence +from random import randint + +from matplotlib import pyplot as plt + + +def max_subarray( + arr: Sequence[float], low: int, high: int +) -> tuple[int | None, int | None, float]: + """ + Solves the maximum subarray problem using divide and conquer. + :param arr: the given array of numbers + :param low: the start index + :param high: the end index + :return: the start index of the maximum subarray, the end index of the + maximum subarray, and the maximum subarray sum + + >>> nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4] + >>> max_subarray(nums, 0, len(nums) - 1) + (3, 6, 6) + >>> nums = [2, 8, 9] + >>> max_subarray(nums, 0, len(nums) - 1) + (0, 2, 19) + >>> nums = [0, 0] + >>> max_subarray(nums, 0, len(nums) - 1) + (0, 0, 0) + >>> nums = [-1.0, 0.0, 1.0] + >>> max_subarray(nums, 0, len(nums) - 1) + (2, 2, 1.0) + >>> nums = [-2, -3, -1, -4, -6] + >>> max_subarray(nums, 0, len(nums) - 1) + (2, 2, -1) + >>> max_subarray([], 0, 0) + (None, None, 0) + """ + if not arr: + return None, None, 0 + if low == high: + return low, high, arr[low] + + mid = (low + high) // 2 + left_low, left_high, left_sum = max_subarray(arr, low, mid) + right_low, right_high, right_sum = max_subarray(arr, mid + 1, high) + cross_left, cross_right, cross_sum = max_cross_sum(arr, low, mid, high) + if left_sum >= right_sum and left_sum >= cross_sum: + return left_low, left_high, left_sum + elif right_sum >= left_sum and right_sum >= cross_sum: + return right_low, right_high, right_sum + return cross_left, cross_right, cross_sum + + +def max_cross_sum( + arr: Sequence[float], low: int, mid: int, high: int +) -> tuple[int, int, float]: + left_sum, max_left = float("-inf"), -1 + right_sum, max_right = float("-inf"), -1 + + summ: int | float = 0 + for i in range(mid, low - 1, -1): + summ += arr[i] + if summ > left_sum: + left_sum = summ + max_left = i + + summ = 0 + for i in range(mid + 1, high + 1): + summ += arr[i] + if summ > right_sum: + right_sum = summ + max_right = i + + return max_left, max_right, (left_sum + right_sum) + + +def time_max_subarray(input_size: int) -> float: + arr = [randint(1, input_size) for _ in range(input_size)] + start = time.time() + max_subarray(arr, 0, input_size - 1) + end = time.time() + return end - start + + +def plot_runtimes() -> None: + input_sizes = [10, 100, 1000, 10000, 50000, 100000, 200000, 300000, 400000, 500000] + runtimes = [time_max_subarray(input_size) for input_size in input_sizes] + print("No of Inputs\t\tTime Taken") + for input_size, runtime in zip(input_sizes, runtimes): + print(input_size, "\t\t", runtime) + plt.plot(input_sizes, runtimes) + plt.xlabel("Number of Inputs") + plt.ylabel("Time taken in seconds") + plt.show() + + +if __name__ == "__main__": + """ + A random simulation of this algorithm. + """ + from doctest import testmod + + testmod() diff --git a/divide_and_conquer/max_subarray_sum.py b/divide_and_conquer/max_subarray_sum.py deleted file mode 100644 index f23e81719..000000000 --- a/divide_and_conquer/max_subarray_sum.py +++ /dev/null @@ -1,78 +0,0 @@ -""" -Given a array of length n, max_subarray_sum() finds -the maximum of sum of contiguous sub-array using divide and conquer method. - -Time complexity : O(n log n) - -Ref : INTRODUCTION TO ALGORITHMS THIRD EDITION -(section : 4, sub-section : 4.1, page : 70) - -""" - - -def max_sum_from_start(array): - """This function finds the maximum contiguous sum of array from 0 index - - Parameters : - array (list[int]) : given array - - Returns : - max_sum (int) : maximum contiguous sum of array from 0 index - - """ - array_sum = 0 - max_sum = float("-inf") - for num in array: - array_sum += num - if array_sum > max_sum: - max_sum = array_sum - return max_sum - - -def max_cross_array_sum(array, left, mid, right): - """This function finds the maximum contiguous sum of left and right arrays - - Parameters : - array, left, mid, right (list[int], int, int, int) - - Returns : - (int) : maximum of sum of contiguous sum of left and right arrays - - """ - - max_sum_of_left = max_sum_from_start(array[left : mid + 1][::-1]) - max_sum_of_right = max_sum_from_start(array[mid + 1 : right + 1]) - return max_sum_of_left + max_sum_of_right - - -def max_subarray_sum(array, left, right): - """Maximum contiguous sub-array sum, using divide and conquer method - - Parameters : - array, left, right (list[int], int, int) : - given array, current left index and current right index - - Returns : - int : maximum of sum of contiguous sub-array - - """ - - # base case: array has only one element - if left == right: - return array[right] - - # Recursion - mid = (left + right) // 2 - left_half_sum = max_subarray_sum(array, left, mid) - right_half_sum = max_subarray_sum(array, mid + 1, right) - cross_sum = max_cross_array_sum(array, left, mid, right) - return max(left_half_sum, right_half_sum, cross_sum) - - -if __name__ == "__main__": - array = [-2, -5, 6, -2, -3, 1, 5, -6] - array_length = len(array) - print( - "Maximum sum of contiguous subarray:", - max_subarray_sum(array, 0, array_length - 1), - ) diff --git a/dynamic_programming/max_sub_array.py b/dynamic_programming/max_sub_array.py deleted file mode 100644 index 07717fba4..000000000 --- a/dynamic_programming/max_sub_array.py +++ /dev/null @@ -1,93 +0,0 @@ -""" -author : Mayank Kumar Jha (mk9440) -""" -from __future__ import annotations - - -def find_max_sub_array(a, low, high): - if low == high: - return low, high, a[low] - else: - mid = (low + high) // 2 - left_low, left_high, left_sum = find_max_sub_array(a, low, mid) - right_low, right_high, right_sum = find_max_sub_array(a, mid + 1, high) - cross_left, cross_right, cross_sum = find_max_cross_sum(a, low, mid, high) - if left_sum >= right_sum and left_sum >= cross_sum: - return left_low, left_high, left_sum - elif right_sum >= left_sum and right_sum >= cross_sum: - return right_low, right_high, right_sum - else: - return cross_left, cross_right, cross_sum - - -def find_max_cross_sum(a, low, mid, high): - left_sum, max_left = -999999999, -1 - right_sum, max_right = -999999999, -1 - summ = 0 - for i in range(mid, low - 1, -1): - summ += a[i] - if summ > left_sum: - left_sum = summ - max_left = i - summ = 0 - for i in range(mid + 1, high + 1): - summ += a[i] - if summ > right_sum: - right_sum = summ - max_right = i - return max_left, max_right, (left_sum + right_sum) - - -def max_sub_array(nums: list[int]) -> int: - """ - Finds the contiguous subarray which has the largest sum and return its sum. - - >>> max_sub_array([-2, 1, -3, 4, -1, 2, 1, -5, 4]) - 6 - - An empty (sub)array has sum 0. - >>> max_sub_array([]) - 0 - - If all elements are negative, the largest subarray would be the empty array, - having the sum 0. - >>> max_sub_array([-1, -2, -3]) - 0 - >>> max_sub_array([5, -2, -3]) - 5 - >>> max_sub_array([31, -41, 59, 26, -53, 58, 97, -93, -23, 84]) - 187 - """ - best = 0 - current = 0 - for i in nums: - current += i - current = max(current, 0) - best = max(best, current) - return best - - -if __name__ == "__main__": - """ - A random simulation of this algorithm. - """ - import time - from random import randint - - from matplotlib import pyplot as plt - - inputs = [10, 100, 1000, 10000, 50000, 100000, 200000, 300000, 400000, 500000] - tim = [] - for i in inputs: - li = [randint(1, i) for j in range(i)] - strt = time.time() - (find_max_sub_array(li, 0, len(li) - 1)) - end = time.time() - tim.append(end - strt) - print("No of Inputs Time Taken") - for i in range(len(inputs)): - print(inputs[i], "\t\t", tim[i]) - plt.plot(inputs, tim) - plt.xlabel("Number of Inputs") - plt.ylabel("Time taken in seconds ") - plt.show() diff --git a/dynamic_programming/max_subarray_sum.py b/dynamic_programming/max_subarray_sum.py new file mode 100644 index 000000000..c76943472 --- /dev/null +++ b/dynamic_programming/max_subarray_sum.py @@ -0,0 +1,60 @@ +""" +The maximum subarray sum problem is the task of finding the maximum sum that can be +obtained from a contiguous subarray within a given array of numbers. For example, given +the array [-2, 1, -3, 4, -1, 2, 1, -5, 4], the contiguous subarray with the maximum sum +is [4, -1, 2, 1], so the maximum subarray sum is 6. + +Kadane's algorithm is a simple dynamic programming algorithm that solves the maximum +subarray sum problem in O(n) time and O(1) space. + +Reference: https://en.wikipedia.org/wiki/Maximum_subarray_problem +""" +from collections.abc import Sequence + + +def max_subarray_sum( + arr: Sequence[float], allow_empty_subarrays: bool = False +) -> float: + """ + Solves the maximum subarray sum problem using Kadane's algorithm. + :param arr: the given array of numbers + :param allow_empty_subarrays: if True, then the algorithm considers empty subarrays + + >>> max_subarray_sum([2, 8, 9]) + 19 + >>> max_subarray_sum([0, 0]) + 0 + >>> max_subarray_sum([-1.0, 0.0, 1.0]) + 1.0 + >>> max_subarray_sum([1, 2, 3, 4, -2]) + 10 + >>> max_subarray_sum([-2, 1, -3, 4, -1, 2, 1, -5, 4]) + 6 + >>> max_subarray_sum([2, 3, -9, 8, -2]) + 8 + >>> max_subarray_sum([-2, -3, -1, -4, -6]) + -1 + >>> max_subarray_sum([-2, -3, -1, -4, -6], allow_empty_subarrays=True) + 0 + >>> max_subarray_sum([]) + 0 + """ + if not arr: + return 0 + + max_sum = 0 if allow_empty_subarrays else float("-inf") + curr_sum = 0.0 + for num in arr: + curr_sum = max(0 if allow_empty_subarrays else num, curr_sum + num) + max_sum = max(max_sum, curr_sum) + + return max_sum + + +if __name__ == "__main__": + from doctest import testmod + + testmod() + + nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4] + print(f"{max_subarray_sum(nums) = }") diff --git a/dynamic_programming/max_sum_contiguous_subsequence.py b/dynamic_programming/max_sum_contiguous_subsequence.py deleted file mode 100644 index bac592370..000000000 --- a/dynamic_programming/max_sum_contiguous_subsequence.py +++ /dev/null @@ -1,20 +0,0 @@ -def max_subarray_sum(nums: list) -> int: - """ - >>> max_subarray_sum([6 , 9, -1, 3, -7, -5, 10]) - 17 - """ - if not nums: - return 0 - n = len(nums) - - res, s, s_pre = nums[0], nums[0], nums[0] - for i in range(1, n): - s = max(nums[i], s_pre + nums[i]) - s_pre = s - res = max(res, s) - return res - - -if __name__ == "__main__": - nums = [6, 9, -1, 3, -7, -5, 10] - print(max_subarray_sum(nums)) diff --git a/maths/kadanes.py b/maths/kadanes.py deleted file mode 100644 index c2ea53a6c..000000000 --- a/maths/kadanes.py +++ /dev/null @@ -1,63 +0,0 @@ -""" -Kadane's algorithm to get maximum subarray sum -https://medium.com/@rsinghal757/kadanes-algorithm-dynamic-programming-how-and-why-does-it-work-3fd8849ed73d -https://en.wikipedia.org/wiki/Maximum_subarray_problem -""" -test_data: tuple = ([-2, -8, -9], [2, 8, 9], [-1, 0, 1], [0, 0], []) - - -def negative_exist(arr: list) -> int: - """ - >>> negative_exist([-2,-8,-9]) - -2 - >>> [negative_exist(arr) for arr in test_data] - [-2, 0, 0, 0, 0] - """ - arr = arr or [0] - max_number = arr[0] - for i in arr: - if i >= 0: - return 0 - elif max_number <= i: - max_number = i - return max_number - - -def kadanes(arr: list) -> int: - """ - If negative_exist() returns 0 than this function will execute - else it will return the value return by negative_exist function - - For example: arr = [2, 3, -9, 8, -2] - Initially we set value of max_sum to 0 and max_till_element to 0 than when - max_sum is less than max_till particular element it will assign that value to - max_sum and when value of max_till_sum is less than 0 it will assign 0 to i - and after that whole process, return the max_sum - So the output for above arr is 8 - - >>> kadanes([2, 3, -9, 8, -2]) - 8 - >>> [kadanes(arr) for arr in test_data] - [-2, 19, 1, 0, 0] - """ - max_sum = negative_exist(arr) - if max_sum < 0: - return max_sum - - max_sum = 0 - max_till_element = 0 - - for i in arr: - max_till_element += i - max_sum = max(max_sum, max_till_element) - max_till_element = max(max_till_element, 0) - return max_sum - - -if __name__ == "__main__": - try: - print("Enter integer values sepatated by spaces") - arr = [int(x) for x in input().split()] - print(f"Maximum subarray sum of {arr} is {kadanes(arr)}") - except ValueError: - print("Please enter integer values.") diff --git a/maths/largest_subarray_sum.py b/maths/largest_subarray_sum.py deleted file mode 100644 index 90f92c712..000000000 --- a/maths/largest_subarray_sum.py +++ /dev/null @@ -1,21 +0,0 @@ -from sys import maxsize - - -def max_sub_array_sum(a: list, size: int = 0): - """ - >>> max_sub_array_sum([-13, -3, -25, -20, -3, -16, -23, -12, -5, -22, -15, -4, -7]) - -3 - """ - size = size or len(a) - max_so_far = -maxsize - 1 - max_ending_here = 0 - for i in range(0, size): - max_ending_here = max_ending_here + a[i] - max_so_far = max(max_so_far, max_ending_here) - max_ending_here = max(max_ending_here, 0) - return max_so_far - - -if __name__ == "__main__": - a = [-13, -3, -25, -20, 1, -16, -23, -12, -5, -22, -15, -4, -7] - print(("Maximum contiguous sum is", max_sub_array_sum(a, len(a)))) diff --git a/other/maximum_subarray.py b/other/maximum_subarray.py deleted file mode 100644 index 1c8c8cabc..000000000 --- a/other/maximum_subarray.py +++ /dev/null @@ -1,32 +0,0 @@ -from collections.abc import Sequence - - -def max_subarray_sum(nums: Sequence[int]) -> int: - """Return the maximum possible sum amongst all non - empty subarrays. - - Raises: - ValueError: when nums is empty. - - >>> max_subarray_sum([1,2,3,4,-2]) - 10 - >>> max_subarray_sum([-2,1,-3,4,-1,2,1,-5,4]) - 6 - """ - if not nums: - raise ValueError("Input sequence should not be empty") - - curr_max = ans = nums[0] - nums_len = len(nums) - - for i in range(1, nums_len): - num = nums[i] - curr_max = max(curr_max + num, num) - ans = max(curr_max, ans) - - return ans - - -if __name__ == "__main__": - n = int(input("Enter number of elements : ").strip()) - array = list(map(int, input("\nEnter the numbers : ").strip().split()))[:n] - print(max_subarray_sum(array)) From 44b1bcc7c7e0f15385530bf54c59ad4eb86fef0b Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Tue, 11 Jul 2023 10:51:21 +0100 Subject: [PATCH 698/726] Fix failing tests from ruff/newton_raphson (ignore S307 "possibly insecure function") (#8862) * chore: Fix failing tests (ignore S307 "possibly insecure function") * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix: Move noqa back to right line --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- arithmetic_analysis/newton_raphson.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arithmetic_analysis/newton_raphson.py b/arithmetic_analysis/newton_raphson.py index aee2f07e5..1b90ad417 100644 --- a/arithmetic_analysis/newton_raphson.py +++ b/arithmetic_analysis/newton_raphson.py @@ -25,9 +25,11 @@ def newton_raphson( """ x = a while True: - x = Decimal(x) - (Decimal(eval(func)) / Decimal(eval(str(diff(func))))) + x = Decimal(x) - ( + Decimal(eval(func)) / Decimal(eval(str(diff(func)))) # noqa: S307 + ) # This number dictates the accuracy of the answer - if abs(eval(func)) < precision: + if abs(eval(func)) < precision: # noqa: S307 return float(x) From f614ed72170011d2d439f7901e1c8daa7deac8c4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 11 Jul 2023 11:55:32 +0200 Subject: [PATCH 699/726] [pre-commit.ci] pre-commit autoupdate (#8860) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.0.276 → v0.0.277](https://github.com/astral-sh/ruff-pre-commit/compare/v0.0.276...v0.0.277) - [github.com/tox-dev/pyproject-fmt: 0.12.1 → 0.13.0](https://github.com/tox-dev/pyproject-fmt/compare/0.12.1...0.13.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 42ebeed14..bf30703bd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.0.276 + rev: v0.0.277 hooks: - id: ruff @@ -33,7 +33,7 @@ repos: - tomli - repo: https://github.com/tox-dev/pyproject-fmt - rev: "0.12.1" + rev: "0.13.0" hooks: - id: pyproject-fmt From 5aefc00f0f1c692ce772ddbc616d7cd91233236b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 18 Jul 2023 09:58:22 +0530 Subject: [PATCH 700/726] [pre-commit.ci] pre-commit autoupdate (#8872) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.0.277 → v0.0.278](https://github.com/astral-sh/ruff-pre-commit/compare/v0.0.277...v0.0.278) - [github.com/psf/black: 23.3.0 → 23.7.0](https://github.com/psf/black/compare/23.3.0...23.7.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bf30703bd..13b955dd3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,12 +16,12 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.0.277 + rev: v0.0.278 hooks: - id: ruff - repo: https://github.com/psf/black - rev: 23.3.0 + rev: 23.7.0 hooks: - id: black From 93fb169627ea9fe43436a312fdfa751818808180 Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Sat, 22 Jul 2023 13:05:10 +0300 Subject: [PATCH 701/726] [Upgrade Ruff] Fix all errors raised from ruff (#8879) * chore: Fix tests * chore: Fix failing ruff * chore: Fix ruff errors * chore: Fix ruff errors * chore: Fix ruff errors * chore: Fix ruff errors * chore: Fix ruff errors * chore: Fix ruff errors * chore: Fix ruff errors * chore: Fix ruff errors * chore: Fix ruff errors * chore: Fix ruff errors * chore: Fix ruff errors * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * chore: Fix ruff errors * chore: Fix ruff errors * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update cellular_automata/game_of_life.py Co-authored-by: Christian Clauss * chore: Update ruff version in pre-commit * chore: Fix ruff errors * Update edmonds_karp_multiple_source_and_sink.py * Update factorial.py * Update primelib.py * Update min_cost_string_conversion.py --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .pre-commit-config.yaml | 2 +- cellular_automata/game_of_life.py | 2 +- data_structures/binary_tree/red_black_tree.py | 2 +- data_structures/trie/radix_tree.py | 4 ++-- divide_and_conquer/convex_hull.py | 2 +- ...directed_and_undirected_(weighted)_graph.py | 18 +++++++++--------- .../edmonds_karp_multiple_source_and_sink.py | 2 +- maths/factorial.py | 2 +- maths/primelib.py | 2 +- other/davisb_putnamb_logemannb_loveland.py | 2 +- project_euler/problem_009/sol3.py | 16 ++++++++++------ quantum/ripple_adder_classic.py | 2 +- strings/min_cost_string_conversion.py | 2 +- web_programming/convert_number_to_words.py | 4 +--- 14 files changed, 32 insertions(+), 30 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 13b955dd3..5adf12cc7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.0.278 + rev: v0.0.280 hooks: - id: ruff diff --git a/cellular_automata/game_of_life.py b/cellular_automata/game_of_life.py index 3382af7b5..b69afdce0 100644 --- a/cellular_automata/game_of_life.py +++ b/cellular_automata/game_of_life.py @@ -98,7 +98,7 @@ def __judge_point(pt: bool, neighbours: list[list[bool]]) -> bool: if pt: if alive < 2: state = False - elif alive == 2 or alive == 3: + elif alive in {2, 3}: state = True elif alive > 3: state = False diff --git a/data_structures/binary_tree/red_black_tree.py b/data_structures/binary_tree/red_black_tree.py index 3ebc8d639..4ebe0e927 100644 --- a/data_structures/binary_tree/red_black_tree.py +++ b/data_structures/binary_tree/red_black_tree.py @@ -152,7 +152,7 @@ class RedBlackTree: self.grandparent.color = 1 self.grandparent._insert_repair() - def remove(self, label: int) -> RedBlackTree: + def remove(self, label: int) -> RedBlackTree: # noqa: PLR0912 """Remove label from this tree.""" if self.label == label: if self.left and self.right: diff --git a/data_structures/trie/radix_tree.py b/data_structures/trie/radix_tree.py index 66890346e..cf2f25c29 100644 --- a/data_structures/trie/radix_tree.py +++ b/data_structures/trie/radix_tree.py @@ -156,7 +156,7 @@ class RadixNode: del self.nodes[word[0]] # We merge the current node with its only child if len(self.nodes) == 1 and not self.is_leaf: - merging_node = list(self.nodes.values())[0] + merging_node = next(iter(self.nodes.values())) self.is_leaf = merging_node.is_leaf self.prefix += merging_node.prefix self.nodes = merging_node.nodes @@ -165,7 +165,7 @@ class RadixNode: incoming_node.is_leaf = False # If there is 1 edge, we merge it with its child else: - merging_node = list(incoming_node.nodes.values())[0] + merging_node = next(iter(incoming_node.nodes.values())) incoming_node.is_leaf = merging_node.is_leaf incoming_node.prefix += merging_node.prefix incoming_node.nodes = merging_node.nodes diff --git a/divide_and_conquer/convex_hull.py b/divide_and_conquer/convex_hull.py index 1ad933417..1d1bf301d 100644 --- a/divide_and_conquer/convex_hull.py +++ b/divide_and_conquer/convex_hull.py @@ -266,7 +266,7 @@ def convex_hull_bf(points: list[Point]) -> list[Point]: points_left_of_ij = points_right_of_ij = False ij_part_of_convex_hull = True for k in range(n): - if k != i and k != j: + if k not in {i, j}: det_k = _det(points[i], points[j], points[k]) if det_k > 0: diff --git a/graphs/directed_and_undirected_(weighted)_graph.py b/graphs/directed_and_undirected_(weighted)_graph.py index b29485031..8ca645fda 100644 --- a/graphs/directed_and_undirected_(weighted)_graph.py +++ b/graphs/directed_and_undirected_(weighted)_graph.py @@ -39,7 +39,7 @@ class DirectedGraph: stack = [] visited = [] if s == -2: - s = list(self.graph)[0] + s = next(iter(self.graph)) stack.append(s) visited.append(s) ss = s @@ -87,7 +87,7 @@ class DirectedGraph: d = deque() visited = [] if s == -2: - s = list(self.graph)[0] + s = next(iter(self.graph)) d.append(s) visited.append(s) while d: @@ -114,7 +114,7 @@ class DirectedGraph: stack = [] visited = [] if s == -2: - s = list(self.graph)[0] + s = next(iter(self.graph)) stack.append(s) visited.append(s) ss = s @@ -146,7 +146,7 @@ class DirectedGraph: def cycle_nodes(self): stack = [] visited = [] - s = list(self.graph)[0] + s = next(iter(self.graph)) stack.append(s) visited.append(s) parent = -2 @@ -199,7 +199,7 @@ class DirectedGraph: def has_cycle(self): stack = [] visited = [] - s = list(self.graph)[0] + s = next(iter(self.graph)) stack.append(s) visited.append(s) parent = -2 @@ -305,7 +305,7 @@ class Graph: stack = [] visited = [] if s == -2: - s = list(self.graph)[0] + s = next(iter(self.graph)) stack.append(s) visited.append(s) ss = s @@ -353,7 +353,7 @@ class Graph: d = deque() visited = [] if s == -2: - s = list(self.graph)[0] + s = next(iter(self.graph)) d.append(s) visited.append(s) while d: @@ -371,7 +371,7 @@ class Graph: def cycle_nodes(self): stack = [] visited = [] - s = list(self.graph)[0] + s = next(iter(self.graph)) stack.append(s) visited.append(s) parent = -2 @@ -424,7 +424,7 @@ class Graph: def has_cycle(self): stack = [] visited = [] - s = list(self.graph)[0] + s = next(iter(self.graph)) stack.append(s) visited.append(s) parent = -2 diff --git a/graphs/edmonds_karp_multiple_source_and_sink.py b/graphs/edmonds_karp_multiple_source_and_sink.py index d06108041..5c774f4b8 100644 --- a/graphs/edmonds_karp_multiple_source_and_sink.py +++ b/graphs/edmonds_karp_multiple_source_and_sink.py @@ -113,7 +113,7 @@ class PushRelabelExecutor(MaximumFlowAlgorithmExecutor): vertices_list = [ i for i in range(self.verticies_count) - if i != self.source_index and i != self.sink_index + if i not in {self.source_index, self.sink_index} ] # move through list diff --git a/maths/factorial.py b/maths/factorial.py index bbf0efc01..18cacdef9 100644 --- a/maths/factorial.py +++ b/maths/factorial.py @@ -55,7 +55,7 @@ def factorial_recursive(n: int) -> int: raise ValueError("factorial() only accepts integral values") if n < 0: raise ValueError("factorial() not defined for negative values") - return 1 if n == 0 or n == 1 else n * factorial(n - 1) + return 1 if n in {0, 1} else n * factorial(n - 1) if __name__ == "__main__": diff --git a/maths/primelib.py b/maths/primelib.py index 81d573706..28b5aee9d 100644 --- a/maths/primelib.py +++ b/maths/primelib.py @@ -154,7 +154,7 @@ def prime_factorization(number): quotient = number - if number == 0 or number == 1: + if number in {0, 1}: ans.append(number) # if 'number' not prime then builds the prime factorization of 'number' diff --git a/other/davisb_putnamb_logemannb_loveland.py b/other/davisb_putnamb_logemannb_loveland.py index a1bea5b39..f5fb103ba 100644 --- a/other/davisb_putnamb_logemannb_loveland.py +++ b/other/davisb_putnamb_logemannb_loveland.py @@ -253,7 +253,7 @@ def find_unit_clauses( unit_symbols = [] for clause in clauses: if len(clause) == 1: - unit_symbols.append(list(clause.literals.keys())[0]) + unit_symbols.append(next(iter(clause.literals.keys()))) else: f_count, n_count = 0, 0 for literal, value in clause.literals.items(): diff --git a/project_euler/problem_009/sol3.py b/project_euler/problem_009/sol3.py index d299f821d..37340d306 100644 --- a/project_euler/problem_009/sol3.py +++ b/project_euler/problem_009/sol3.py @@ -28,12 +28,16 @@ def solution() -> int: 31875000 """ - return [ - a * b * (1000 - a - b) - for a in range(1, 999) - for b in range(a, 999) - if (a * a + b * b == (1000 - a - b) ** 2) - ][0] + return next( + iter( + [ + a * b * (1000 - a - b) + for a in range(1, 999) + for b in range(a, 999) + if (a * a + b * b == (1000 - a - b) ** 2) + ] + ) + ) if __name__ == "__main__": diff --git a/quantum/ripple_adder_classic.py b/quantum/ripple_adder_classic.py index b604395bc..2284141cc 100644 --- a/quantum/ripple_adder_classic.py +++ b/quantum/ripple_adder_classic.py @@ -107,7 +107,7 @@ def ripple_adder( res = qiskit.execute(circuit, backend, shots=1).result() # The result is in binary. Convert it back to int - return int(list(res.get_counts())[0], 2) + return int(next(iter(res.get_counts())), 2) if __name__ == "__main__": diff --git a/strings/min_cost_string_conversion.py b/strings/min_cost_string_conversion.py index 089c2532f..0fad0b88c 100644 --- a/strings/min_cost_string_conversion.py +++ b/strings/min_cost_string_conversion.py @@ -61,7 +61,7 @@ def assemble_transformation(ops: list[list[str]], i: int, j: int) -> list[str]: if i == 0 and j == 0: return [] else: - if ops[i][j][0] == "C" or ops[i][j][0] == "R": + if ops[i][j][0] in {"C", "R"}: seq = assemble_transformation(ops, i - 1, j - 1) seq.append(ops[i][j]) return seq diff --git a/web_programming/convert_number_to_words.py b/web_programming/convert_number_to_words.py index 1e293df96..dac9e3e38 100644 --- a/web_programming/convert_number_to_words.py +++ b/web_programming/convert_number_to_words.py @@ -90,9 +90,7 @@ def convert(number: int) -> str: else: addition = "" if counter in placevalue: - if current == 0 and ((temp_num % 100) // 10) == 0: - addition = "" - else: + if current != 0 and ((temp_num % 100) // 10) != 0: addition = placevalue[counter] if ((temp_num % 100) // 10) == 1: words = teens[current] + addition + words From f7531d9874e0dd3682bf0ed7ae408927e1fae472 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Sat, 22 Jul 2023 03:11:04 -0700 Subject: [PATCH 702/726] Add note in `CONTRIBUTING.md` about not asking to be assigned to issues (#8871) * Add note in CONTRIBUTING.md about not asking to be assigned to issues Add a paragraph to CONTRIBUTING.md explicitly asking contributors to not ask to be assigned to issues * Update CONTRIBUTING.md * Update CONTRIBUTING.md --------- Co-authored-by: Christian Clauss --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 618cca868..4a1bb6527 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -25,6 +25,8 @@ We appreciate any contribution, from fixing a grammar mistake in a comment to im Your contribution will be tested by our [automated testing on GitHub Actions](https://github.com/TheAlgorithms/Python/actions) to save time and mental energy. After you have submitted your pull request, you should see the GitHub Actions tests start to run at the bottom of your submission page. If those tests fail, then click on the ___details___ button try to read through the GitHub Actions output to understand the failure. If you do not understand, please leave a comment on your submission page and a community member will try to help. +If you are interested in resolving an [open issue](https://github.com/TheAlgorithms/Python/issues), simply make a pull request with your proposed fix. __We do not assign issues in this repo__ so please do not ask for permission to work on an issue. + Please help us keep our issue list small by adding `Fixes #{$ISSUE_NUMBER}` to the description of pull requests that resolve open issues. For example, if your pull request fixes issue #10, then please add the following to its description: ``` From 9e08c7726dee5b18585a76e54c71922ca96c0b3a Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Sat, 22 Jul 2023 13:34:19 +0300 Subject: [PATCH 703/726] Small docstring time complexity fix in number_container _system (#8875) * fix: Write time is O(log n) not O(n log n) * chore: Update pre-commit ruff version * revert: Undo previous commit --- other/number_container_system.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/other/number_container_system.py b/other/number_container_system.py index f547bc8a2..6c95dd0a3 100644 --- a/other/number_container_system.py +++ b/other/number_container_system.py @@ -1,6 +1,6 @@ """ A number container system that uses binary search to delete and insert values into -arrays with O(n logn) write times and O(1) read times. +arrays with O(log n) write times and O(1) read times. This container system holds integers at indexes. From a03b739d23b59890b59d2d2288ebaa56e3be47ce Mon Sep 17 00:00:00 2001 From: Sangmin Jeon Date: Mon, 24 Jul 2023 18:29:05 +0900 Subject: [PATCH 704/726] Fix `radix_tree.py` insertion fail in ["*X", "*XX"] cases (#8870) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix insertion fail in ["*X", "*XX"] cases Consider a word, and a copy of that word, but with the last letter repeating twice. (e.g., ["ABC", "ABCC"]) When adding the second word's last letter, it only compares the previous word's prefix—the last letter of the word already in the Radix Tree: 'C'—and the letter to be added—the last letter of the word we're currently adding: 'C'. So it wrongly passes the "Case 1" check, marks the current node as a leaf node when it already was, then returns when there's still one more letter to add. The issue arises because `prefix` includes the letter of the node itself. (e.g., `nodes: {'C' : RadixNode()}, is_leaf: True, prefix: 'C'`) It can be easily fixed by simply adding the `is_leaf` check, asking if there are more letters to be added. - Test Case: `"A AA AAA AAAA"` - Fixed correct output: ``` Words: ['A', 'AA', 'AAA', 'AAAA'] Tree: - A (leaf) -- A (leaf) --- A (leaf) ---- A (leaf) ``` - Current incorrect output: ``` Words: ['A', 'AA', 'AAA', 'AAAA'] Tree: - A (leaf) -- AA (leaf) --- A (leaf) ``` *N.B.* This passed test cases for [Croatian Open Competition in Informatics 2012/2013 Contest #3 Task 5 HERKABE](https://hsin.hr/coci/archive/2012_2013/) * Add a doctest for previous fix * improve doctest readability --- data_structures/trie/radix_tree.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/data_structures/trie/radix_tree.py b/data_structures/trie/radix_tree.py index cf2f25c29..fadc50cb4 100644 --- a/data_structures/trie/radix_tree.py +++ b/data_structures/trie/radix_tree.py @@ -54,10 +54,17 @@ class RadixNode: word (str): word to insert >>> RadixNode("myprefix").insert("mystring") + + >>> root = RadixNode() + >>> root.insert_many(['myprefix', 'myprefixA', 'myprefixAA']) + >>> root.print_tree() + - myprefix (leaf) + -- A (leaf) + --- A (leaf) """ # Case 1: If the word is the prefix of the node # Solution: We set the current node as leaf - if self.prefix == word: + if self.prefix == word and not self.is_leaf: self.is_leaf = True # Case 2: The node has no edges that have a prefix to the word From b77e6adf3abba674eb83ab7c0182bd6c89c08891 Mon Sep 17 00:00:00 2001 From: HManiac74 <63391783+HManiac74@users.noreply.github.com> Date: Tue, 25 Jul 2023 22:23:20 +0200 Subject: [PATCH 705/726] Add Docker devcontainer configuration files (#8887) * Added Docker container configuration files * Update Dockerfile Copy and install requirements * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Updated Docker devcontainer configuration * Update requierements.txt * Update Dockerfile * Update Dockerfile * Update .devcontainer/devcontainer.json Co-authored-by: Christian Clauss * Update Dockerfile * Update Dockerfile. Add linebreak --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- .devcontainer/Dockerfile | 6 +++++ .devcontainer/devcontainer.json | 42 +++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 000000000..27b25c09b --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,6 @@ +# https://github.com/microsoft/vscode-dev-containers/blob/main/containers/python-3/README.md +ARG VARIANT=3.11-bookworm +FROM mcr.microsoft.com/vscode/devcontainers/python:${VARIANT} +COPY requirements.txt /tmp/pip-tmp/ +RUN python3 -m pip install --upgrade pip \ + && python3 -m pip install --no-cache-dir install ruff -r /tmp/pip-tmp/requirements.txt diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..c5a855b25 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,42 @@ +{ + "name": "Python 3", + "build": { + "dockerfile": "Dockerfile", + "context": "..", + "args": { + // Update 'VARIANT' to pick a Python version: 3, 3.10, 3.9, 3.8, 3.7, 3.6 + // Append -bullseye or -buster to pin to an OS version. + // Use -bullseye variants on local on arm64/Apple Silicon. + "VARIANT": "3.11-bookworm", + } + }, + + // Configure tool-specific properties. + "customizations": { + // Configure properties specific to VS Code. + "vscode": { + // Set *default* container specific settings.json values on container create. + "settings": { + "python.defaultInterpreterPath": "/usr/local/bin/python", + "python.linting.enabled": true, + "python.formatting.blackPath": "/usr/local/py-utils/bin/black", + "python.linting.mypyPath": "/usr/local/py-utils/bin/mypy" + }, + + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "ms-python.python", + "ms-python.vscode-pylance" + ] + } + }, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "pip3 install --user -r requirements.txt", + + // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. + "remoteUser": "vscode" +} From dbaff345724040b270b3097cb02759f36ce0ef46 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Fri, 28 Jul 2023 18:53:09 +0200 Subject: [PATCH 706/726] Fix ruff rules ISC flake8-implicit-str-concat (#8892) --- ciphers/diffie_hellman.py | 244 ++++++++++++------------- compression/burrows_wheeler.py | 2 +- neural_network/input_data.py | 4 +- pyproject.toml | 2 +- strings/is_srilankan_phone_number.py | 4 +- web_programming/world_covid19_stats.py | 5 +- 6 files changed, 128 insertions(+), 133 deletions(-) diff --git a/ciphers/diffie_hellman.py b/ciphers/diffie_hellman.py index cd40a6b9c..aec7fb3ea 100644 --- a/ciphers/diffie_hellman.py +++ b/ciphers/diffie_hellman.py @@ -10,13 +10,13 @@ primes = { 5: { "prime": int( "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" - + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" - + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" - + "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", base=16, ), "generator": 2, @@ -25,16 +25,16 @@ primes = { 14: { "prime": int( "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" - + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" - + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" - + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" - + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" - + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" - + "15728E5A8AACAA68FFFFFFFFFFFFFFFF", + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AACAA68FFFFFFFFFFFFFFFF", base=16, ), "generator": 2, @@ -43,21 +43,21 @@ primes = { 15: { "prime": int( "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" - + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" - + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" - + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" - + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" - + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" - + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" - + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" - + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" - + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" - + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" - + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF", + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF", base=16, ), "generator": 2, @@ -66,27 +66,27 @@ primes = { 16: { "prime": int( "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" - + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" - + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" - + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" - + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" - + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" - + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" - + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" - + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" - + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" - + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" - + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" - + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" - + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" - + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" - + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" - + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" - + "FFFFFFFFFFFFFFFF", + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" + "FFFFFFFFFFFFFFFF", base=16, ), "generator": 2, @@ -95,33 +95,33 @@ primes = { 17: { "prime": int( "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" - + "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" - + "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" - + "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" - + "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8" - + "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D" - + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C" - + "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" - + "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D" - + "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D" - + "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226" - + "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C" - + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC" - + "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26" - + "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB" - + "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2" - + "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127" - + "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" - + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406" - + "AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918" - + "DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151" - + "2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03" - + "F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F" - + "BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" - + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B" - + "B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632" - + "387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E" - + "6DCC4024FFFFFFFFFFFFFFFF", + "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" + "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" + "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" + "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8" + "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C" + "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" + "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D" + "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D" + "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226" + "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC" + "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26" + "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB" + "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2" + "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127" + "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406" + "AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918" + "DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151" + "2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03" + "F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F" + "BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B" + "B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632" + "387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E" + "6DCC4024FFFFFFFFFFFFFFFF", base=16, ), "generator": 2, @@ -130,48 +130,48 @@ primes = { 18: { "prime": int( "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" - + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" - + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" - + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" - + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" - + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" - + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" - + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" - + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" - + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" - + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" - + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" - + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" - + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" - + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" - + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" - + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" - + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" - + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" - + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" - + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" - + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" - + "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" - + "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" - + "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" - + "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" - + "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" - + "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" - + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" - + "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" - + "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" - + "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" - + "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300" - + "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" - + "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" - + "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" - + "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A" - + "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" - + "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1" - + "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" - + "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47" - + "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" - + "60C980DD98EDD3DFFFFFFFFFFFFFFFFF", + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" + "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" + "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" + "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" + "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" + "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" + "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" + "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" + "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" + "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" + "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300" + "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" + "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" + "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" + "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A" + "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" + "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1" + "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" + "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47" + "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" + "60C980DD98EDD3DFFFFFFFFFFFFFFFFF", base=16, ), "generator": 2, diff --git a/compression/burrows_wheeler.py b/compression/burrows_wheeler.py index 0916b8a65..52bb045d9 100644 --- a/compression/burrows_wheeler.py +++ b/compression/burrows_wheeler.py @@ -150,7 +150,7 @@ def reverse_bwt(bwt_string: str, idx_original_string: int) -> str: raise ValueError("The parameter idx_original_string must not be lower than 0.") if idx_original_string >= len(bwt_string): raise ValueError( - "The parameter idx_original_string must be lower than" " len(bwt_string)." + "The parameter idx_original_string must be lower than len(bwt_string)." ) ordered_rotations = [""] * len(bwt_string) diff --git a/neural_network/input_data.py b/neural_network/input_data.py index 94c018ece..a58e64907 100644 --- a/neural_network/input_data.py +++ b/neural_network/input_data.py @@ -263,9 +263,7 @@ def _maybe_download(filename, work_directory, source_url): return filepath -@deprecated( - None, "Please use alternatives such as:" " tensorflow_datasets.load('mnist')" -) +@deprecated(None, "Please use alternatives such as: tensorflow_datasets.load('mnist')") def read_data_sets( train_dir, fake_data=False, diff --git a/pyproject.toml b/pyproject.toml index 4f21a9519..f9091fb85 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,6 +49,7 @@ select = [ # https://beta.ruff.rs/docs/rules "ICN", # flake8-import-conventions "INP", # flake8-no-pep420 "INT", # flake8-gettext + "ISC", # flake8-implicit-str-concat "N", # pep8-naming "NPY", # NumPy-specific rules "PGH", # pygrep-hooks @@ -72,7 +73,6 @@ select = [ # https://beta.ruff.rs/docs/rules # "DJ", # flake8-django # "ERA", # eradicate -- DO NOT FIX # "FBT", # flake8-boolean-trap # FIX ME - # "ISC", # flake8-implicit-str-concat # FIX ME # "PD", # pandas-vet # "PT", # flake8-pytest-style # "PTH", # flake8-use-pathlib # FIX ME diff --git a/strings/is_srilankan_phone_number.py b/strings/is_srilankan_phone_number.py index 7bded93f7..6456f85e1 100644 --- a/strings/is_srilankan_phone_number.py +++ b/strings/is_srilankan_phone_number.py @@ -22,9 +22,7 @@ def is_sri_lankan_phone_number(phone: str) -> bool: False """ - pattern = re.compile( - r"^(?:0|94|\+94|0{2}94)" r"7(0|1|2|4|5|6|7|8)" r"(-| |)" r"\d{7}$" - ) + pattern = re.compile(r"^(?:0|94|\+94|0{2}94)7(0|1|2|4|5|6|7|8)(-| |)\d{7}$") return bool(re.search(pattern, phone)) diff --git a/web_programming/world_covid19_stats.py b/web_programming/world_covid19_stats.py index 1dd1ff6d1..ca81abdc4 100644 --- a/web_programming/world_covid19_stats.py +++ b/web_programming/world_covid19_stats.py @@ -22,6 +22,5 @@ def world_covid19_stats(url: str = "https://www.worldometers.info/coronavirus") if __name__ == "__main__": - print("\033[1m" + "COVID-19 Status of the World" + "\033[0m\n") - for key, value in world_covid19_stats().items(): - print(f"{key}\n{value}\n") + print("\033[1m COVID-19 Status of the World \033[0m\n") + print("\n".join(f"{key}\n{value}" for key, value in world_covid19_stats().items())) From 46454e204cc587d1ef044e4b1a11050c30aab4f6 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Fri, 28 Jul 2023 18:54:45 +0200 Subject: [PATCH 707/726] [skip-ci] In .devcontainer/Dockerfile: pipx install pre-commit ruff (#8893) [skip-ci] In .devcontainer/Dockerfile: pipx install pre-commit ruff --- .devcontainer/Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 27b25c09b..b5a5347c6 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -3,4 +3,6 @@ ARG VARIANT=3.11-bookworm FROM mcr.microsoft.com/vscode/devcontainers/python:${VARIANT} COPY requirements.txt /tmp/pip-tmp/ RUN python3 -m pip install --upgrade pip \ - && python3 -m pip install --no-cache-dir install ruff -r /tmp/pip-tmp/requirements.txt + && python3 -m pip install --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \ + && pipx install pre-commit ruff \ + && pre-commit install From 4a83e3f0b1b2a3b414134c3498e57c0fea3b9fcf Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Fri, 28 Jul 2023 21:12:31 +0300 Subject: [PATCH 708/726] Fix failing build due to missing requirement (#8900) * feat(cellular_automata): Create wa-tor algorithm * updating DIRECTORY.md * chore(quality): Implement algo-keeper bot changes * build: Fix broken ci * git rm cellular_automata/wa_tor.py * updating DIRECTORY.md --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index acfbc823e..2702523d5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,6 +9,7 @@ pandas pillow projectq qiskit +qiskit-aer requests rich scikit-fuzzy From e406801f9e3967ff0533dfe8cb98a3249db48d33 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Fri, 28 Jul 2023 11:17:46 -0700 Subject: [PATCH 709/726] Reimplement polynomial_regression.py (#8889) * Reimplement polynomial_regression.py Rename machine_learning/polymonial_regression.py to machine_learning/polynomial_regression.py Reimplement machine_learning/polynomial_regression.py using numpy because the old original implementation was just a how-to on doing polynomial regression using sklearn Add detailed function documentation, doctests, and algorithm explanation * updating DIRECTORY.md * Fix matrix formatting in docstrings * Try to fix failing doctest * Debugging failing doctest * Fix failing doctest attempt 2 * Remove unnecessary return value descriptions in docstrings * Readd placeholder doctest for main function * Fix typo in algorithm description --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 2 +- machine_learning/polymonial_regression.py | 44 ----- machine_learning/polynomial_regression.py | 213 ++++++++++++++++++++++ 3 files changed, 214 insertions(+), 45 deletions(-) delete mode 100644 machine_learning/polymonial_regression.py create mode 100644 machine_learning/polynomial_regression.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 77938f450..133a1ab01 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -511,7 +511,7 @@ * Lstm * [Lstm Prediction](machine_learning/lstm/lstm_prediction.py) * [Multilayer Perceptron Classifier](machine_learning/multilayer_perceptron_classifier.py) - * [Polymonial Regression](machine_learning/polymonial_regression.py) + * [Polynomial Regression](machine_learning/polynomial_regression.py) * [Scoring Functions](machine_learning/scoring_functions.py) * [Self Organizing Map](machine_learning/self_organizing_map.py) * [Sequential Minimum Optimization](machine_learning/sequential_minimum_optimization.py) diff --git a/machine_learning/polymonial_regression.py b/machine_learning/polymonial_regression.py deleted file mode 100644 index 487fb8145..000000000 --- a/machine_learning/polymonial_regression.py +++ /dev/null @@ -1,44 +0,0 @@ -import pandas as pd -from matplotlib import pyplot as plt -from sklearn.linear_model import LinearRegression - -# Splitting the dataset into the Training set and Test set -from sklearn.model_selection import train_test_split - -# Fitting Polynomial Regression to the dataset -from sklearn.preprocessing import PolynomialFeatures - -# Importing the dataset -dataset = pd.read_csv( - "https://s3.us-west-2.amazonaws.com/public.gamelab.fun/dataset/" - "position_salaries.csv" -) -X = dataset.iloc[:, 1:2].values -y = dataset.iloc[:, 2].values - - -X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0) - - -poly_reg = PolynomialFeatures(degree=4) -X_poly = poly_reg.fit_transform(X) -pol_reg = LinearRegression() -pol_reg.fit(X_poly, y) - - -# Visualizing the Polymonial Regression results -def viz_polymonial(): - plt.scatter(X, y, color="red") - plt.plot(X, pol_reg.predict(poly_reg.fit_transform(X)), color="blue") - plt.title("Truth or Bluff (Linear Regression)") - plt.xlabel("Position level") - plt.ylabel("Salary") - plt.show() - - -if __name__ == "__main__": - viz_polymonial() - - # Predicting a new result with Polymonial Regression - pol_reg.predict(poly_reg.fit_transform([[5.5]])) - # output should be 132148.43750003 diff --git a/machine_learning/polynomial_regression.py b/machine_learning/polynomial_regression.py new file mode 100644 index 000000000..5bafea96f --- /dev/null +++ b/machine_learning/polynomial_regression.py @@ -0,0 +1,213 @@ +""" +Polynomial regression is a type of regression analysis that models the relationship +between a predictor x and the response y as an mth-degree polynomial: + +y = β₀ + β₁x + β₂x² + ... + βₘxᵐ + ε + +By treating x, x², ..., xᵐ as distinct variables, we see that polynomial regression is a +special case of multiple linear regression. Therefore, we can use ordinary least squares +(OLS) estimation to estimate the vector of model parameters β = (β₀, β₁, β₂, ..., βₘ) +for polynomial regression: + +β = (XᵀX)⁻¹Xᵀy = X⁺y + +where X is the design matrix, y is the response vector, and X⁺ denotes the Moore–Penrose +pseudoinverse of X. In the case of polynomial regression, the design matrix is + + |1 x₁ x₁² ⋯ x₁ᵐ| +X = |1 x₂ x₂² ⋯ x₂ᵐ| + |⋮ ⋮ ⋮ ⋱ ⋮ | + |1 xₙ xₙ² ⋯ xₙᵐ| + +In OLS estimation, inverting XᵀX to compute X⁺ can be very numerically unstable. This +implementation sidesteps this need to invert XᵀX by computing X⁺ using singular value +decomposition (SVD): + +β = VΣ⁺Uᵀy + +where UΣVᵀ is an SVD of X. + +References: + - https://en.wikipedia.org/wiki/Polynomial_regression + - https://en.wikipedia.org/wiki/Moore%E2%80%93Penrose_inverse + - https://en.wikipedia.org/wiki/Numerical_methods_for_linear_least_squares + - https://en.wikipedia.org/wiki/Singular_value_decomposition +""" + +import matplotlib.pyplot as plt +import numpy as np + + +class PolynomialRegression: + __slots__ = "degree", "params" + + def __init__(self, degree: int) -> None: + """ + @raises ValueError: if the polynomial degree is negative + """ + if degree < 0: + raise ValueError("Polynomial degree must be non-negative") + + self.degree = degree + self.params = None + + @staticmethod + def _design_matrix(data: np.ndarray, degree: int) -> np.ndarray: + """ + Constructs a polynomial regression design matrix for the given input data. For + input data x = (x₁, x₂, ..., xₙ) and polynomial degree m, the design matrix is + the Vandermonde matrix + + |1 x₁ x₁² ⋯ x₁ᵐ| + X = |1 x₂ x₂² ⋯ x₂ᵐ| + |⋮ ⋮ ⋮ ⋱ ⋮ | + |1 xₙ xₙ² ⋯ xₙᵐ| + + Reference: https://en.wikipedia.org/wiki/Vandermonde_matrix + + @param data: the input predictor values x, either for model fitting or for + prediction + @param degree: the polynomial degree m + @returns: the Vandermonde matrix X (see above) + @raises ValueError: if input data is not N x 1 + + >>> x = np.array([0, 1, 2]) + >>> PolynomialRegression._design_matrix(x, degree=0) + array([[1], + [1], + [1]]) + >>> PolynomialRegression._design_matrix(x, degree=1) + array([[1, 0], + [1, 1], + [1, 2]]) + >>> PolynomialRegression._design_matrix(x, degree=2) + array([[1, 0, 0], + [1, 1, 1], + [1, 2, 4]]) + >>> PolynomialRegression._design_matrix(x, degree=3) + array([[1, 0, 0, 0], + [1, 1, 1, 1], + [1, 2, 4, 8]]) + >>> PolynomialRegression._design_matrix(np.array([[0, 0], [0 , 0]]), degree=3) + Traceback (most recent call last): + ... + ValueError: Data must have dimensions N x 1 + """ + rows, *remaining = data.shape + if remaining: + raise ValueError("Data must have dimensions N x 1") + + return np.vander(data, N=degree + 1, increasing=True) + + def fit(self, x_train: np.ndarray, y_train: np.ndarray) -> None: + """ + Computes the polynomial regression model parameters using ordinary least squares + (OLS) estimation: + + β = (XᵀX)⁻¹Xᵀy = X⁺y + + where X⁺ denotes the Moore–Penrose pseudoinverse of the design matrix X. This + function computes X⁺ using singular value decomposition (SVD). + + References: + - https://en.wikipedia.org/wiki/Moore%E2%80%93Penrose_inverse + - https://en.wikipedia.org/wiki/Singular_value_decomposition + - https://en.wikipedia.org/wiki/Multicollinearity + + @param x_train: the predictor values x for model fitting + @param y_train: the response values y for model fitting + @raises ArithmeticError: if X isn't full rank, then XᵀX is singular and β + doesn't exist + + >>> x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) + >>> y = x**3 - 2 * x**2 + 3 * x - 5 + >>> poly_reg = PolynomialRegression(degree=3) + >>> poly_reg.fit(x, y) + >>> poly_reg.params + array([-5., 3., -2., 1.]) + >>> poly_reg = PolynomialRegression(degree=20) + >>> poly_reg.fit(x, y) + Traceback (most recent call last): + ... + ArithmeticError: Design matrix is not full rank, can't compute coefficients + + Make sure errors don't grow too large: + >>> coefs = np.array([-250, 50, -2, 36, 20, -12, 10, 2, -1, -15, 1]) + >>> y = PolynomialRegression._design_matrix(x, len(coefs) - 1) @ coefs + >>> poly_reg = PolynomialRegression(degree=len(coefs) - 1) + >>> poly_reg.fit(x, y) + >>> np.allclose(poly_reg.params, coefs, atol=10e-3) + True + """ + X = PolynomialRegression._design_matrix(x_train, self.degree) # noqa: N806 + _, cols = X.shape + if np.linalg.matrix_rank(X) < cols: + raise ArithmeticError( + "Design matrix is not full rank, can't compute coefficients" + ) + + # np.linalg.pinv() computes the Moore–Penrose pseudoinverse using SVD + self.params = np.linalg.pinv(X) @ y_train + + def predict(self, data: np.ndarray) -> np.ndarray: + """ + Computes the predicted response values y for the given input data by + constructing the design matrix X and evaluating y = Xβ. + + @param data: the predictor values x for prediction + @returns: the predicted response values y = Xβ + @raises ArithmeticError: if this function is called before the model + parameters are fit + + >>> x = np.array([0, 1, 2, 3, 4]) + >>> y = x**3 - 2 * x**2 + 3 * x - 5 + >>> poly_reg = PolynomialRegression(degree=3) + >>> poly_reg.fit(x, y) + >>> poly_reg.predict(np.array([-1])) + array([-11.]) + >>> poly_reg.predict(np.array([-2])) + array([-27.]) + >>> poly_reg.predict(np.array([6])) + array([157.]) + >>> PolynomialRegression(degree=3).predict(x) + Traceback (most recent call last): + ... + ArithmeticError: Predictor hasn't been fit yet + """ + if self.params is None: + raise ArithmeticError("Predictor hasn't been fit yet") + + return PolynomialRegression._design_matrix(data, self.degree) @ self.params + + +def main() -> None: + """ + Fit a polynomial regression model to predict fuel efficiency using seaborn's mpg + dataset + + >>> pass # Placeholder, function is only for demo purposes + """ + import seaborn as sns + + mpg_data = sns.load_dataset("mpg") + + poly_reg = PolynomialRegression(degree=2) + poly_reg.fit(mpg_data.weight, mpg_data.mpg) + + weight_sorted = np.sort(mpg_data.weight) + predictions = poly_reg.predict(weight_sorted) + + plt.scatter(mpg_data.weight, mpg_data.mpg, color="gray", alpha=0.5) + plt.plot(weight_sorted, predictions, color="red", linewidth=3) + plt.title("Predicting Fuel Efficiency Using Polynomial Regression") + plt.xlabel("Weight (lbs)") + plt.ylabel("Fuel Efficiency (mpg)") + plt.show() + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + + main() From a0b642cfe58c215b8ead3f2a40655e144e07aacc Mon Sep 17 00:00:00 2001 From: Alex Bernhardt <54606095+FatAnorexic@users.noreply.github.com> Date: Fri, 28 Jul 2023 14:30:05 -0400 Subject: [PATCH 710/726] Physics/basic orbital capture (#8857) * Added file basic_orbital_capture * updating DIRECTORY.md * added second source * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fixed spelling errors * accepted changes * updating DIRECTORY.md * corrected spelling error * Added file basic_orbital_capture * added second source * fixed spelling errors * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * applied changes * reviewed and checked file * added doctest * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * removed redundant constnant * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * added scipy imports * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * added doctests to capture_radii and scipy const * fixed conflicts * finalizing file. Added tests * Update physics/basic_orbital_capture.py --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- DIRECTORY.md | 1 + physics/basic_orbital_capture.py | 178 +++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 physics/basic_orbital_capture.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 133a1ab01..29514579c 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -741,6 +741,7 @@ ## Physics * [Archimedes Principle](physics/archimedes_principle.py) + * [Basic Orbital Capture](physics/basic_orbital_capture.py) * [Casimir Effect](physics/casimir_effect.py) * [Centripetal Force](physics/centripetal_force.py) * [Grahams Law](physics/grahams_law.py) diff --git a/physics/basic_orbital_capture.py b/physics/basic_orbital_capture.py new file mode 100644 index 000000000..eeb45e602 --- /dev/null +++ b/physics/basic_orbital_capture.py @@ -0,0 +1,178 @@ +from math import pow, sqrt + +from scipy.constants import G, c, pi + +""" +These two functions will return the radii of impact for a target object +of mass M and radius R as well as it's effective cross sectional area σ(sigma). +That is to say any projectile with velocity v passing within σ, will impact the +target object with mass M. The derivation of which is given at the bottom +of this file. + +The derivation shows that a projectile does not need to aim directly at the target +body in order to hit it, as R_capture>R_target. Astronomers refer to the effective +cross section for capture as σ=π*R_capture**2. + +This algorithm does not account for an N-body problem. + +""" + + +def capture_radii( + target_body_radius: float, target_body_mass: float, projectile_velocity: float +) -> float: + """ + Input Params: + ------------- + target_body_radius: Radius of the central body SI units: meters | m + target_body_mass: Mass of the central body SI units: kilograms | kg + projectile_velocity: Velocity of object moving toward central body + SI units: meters/second | m/s + Returns: + -------- + >>> capture_radii(6.957e8, 1.99e30, 25000.0) + 17209590691.0 + >>> capture_radii(-6.957e8, 1.99e30, 25000.0) + Traceback (most recent call last): + ... + ValueError: Radius cannot be less than 0 + >>> capture_radii(6.957e8, -1.99e30, 25000.0) + Traceback (most recent call last): + ... + ValueError: Mass cannot be less than 0 + >>> capture_radii(6.957e8, 1.99e30, c+1) + Traceback (most recent call last): + ... + ValueError: Cannot go beyond speed of light + + Returned SI units: + ------------------ + meters | m + """ + + if target_body_mass < 0: + raise ValueError("Mass cannot be less than 0") + if target_body_radius < 0: + raise ValueError("Radius cannot be less than 0") + if projectile_velocity > c: + raise ValueError("Cannot go beyond speed of light") + + escape_velocity_squared = (2 * G * target_body_mass) / target_body_radius + capture_radius = target_body_radius * sqrt( + 1 + escape_velocity_squared / pow(projectile_velocity, 2) + ) + return round(capture_radius, 0) + + +def capture_area(capture_radius: float) -> float: + """ + Input Param: + ------------ + capture_radius: The radius of orbital capture and impact for a central body of + mass M and a projectile moving towards it with velocity v + SI units: meters | m + Returns: + -------- + >>> capture_area(17209590691) + 9.304455331329126e+20 + >>> capture_area(-1) + Traceback (most recent call last): + ... + ValueError: Cannot have a capture radius less than 0 + + Returned SI units: + ------------------ + meters*meters | m**2 + """ + + if capture_radius < 0: + raise ValueError("Cannot have a capture radius less than 0") + sigma = pi * pow(capture_radius, 2) + return round(sigma, 0) + + +if __name__ == "__main__": + from doctest import testmod + + testmod() + +""" +Derivation: + +Let: Mt=target mass, Rt=target radius, v=projectile_velocity, + r_0=radius of projectile at instant 0 to CM of target + v_p=v at closest approach, + r_p=radius from projectile to target CM at closest approach, + R_capture= radius of impact for projectile with velocity v + +(1)At time=0 the projectile's energy falling from infinity| E=K+U=0.5*m*(v**2)+0 + + E_initial=0.5*m*(v**2) + +(2)at time=0 the angular momentum of the projectile relative to CM target| + L_initial=m*r_0*v*sin(Θ)->m*r_0*v*(R_capture/r_0)->m*v*R_capture + + L_i=m*v*R_capture + +(3)The energy of the projectile at closest approach will be its kinetic energy + at closest approach plus gravitational potential energy(-(GMm)/R)| + E_p=K_p+U_p->E_p=0.5*m*(v_p**2)-(G*Mt*m)/r_p + + E_p=0.0.5*m*(v_p**2)-(G*Mt*m)/r_p + +(4)The angular momentum of the projectile relative to the target at closest + approach will be L_p=m*r_p*v_p*sin(Θ), however relative to the target Θ=90° + sin(90°)=1| + + L_p=m*r_p*v_p +(5)Using conservation of angular momentum and energy, we can write a quadratic + equation that solves for r_p| + + (a) + Ei=Ep-> 0.5*m*(v**2)=0.5*m*(v_p**2)-(G*Mt*m)/r_p-> v**2=v_p**2-(2*G*Mt)/r_p + + (b) + Li=Lp-> m*v*R_capture=m*r_p*v_p-> v*R_capture=r_p*v_p-> v_p=(v*R_capture)/r_p + + (c) b plugs int a| + v**2=((v*R_capture)/r_p)**2-(2*G*Mt)/r_p-> + + v**2-(v**2)*(R_c**2)/(r_p**2)+(2*G*Mt)/r_p=0-> + + (v**2)*(r_p**2)+2*G*Mt*r_p-(v**2)*(R_c**2)=0 + + (d) Using the quadratic formula, we'll solve for r_p then rearrange to solve to + R_capture + + r_p=(-2*G*Mt ± sqrt(4*G^2*Mt^2+ 4(v^4*R_c^2)))/(2*v^2)-> + + r_p=(-G*Mt ± sqrt(G^2*Mt+v^4*R_c^2))/v^2-> + + r_p<0 is something we can ignore, as it has no physical meaning for our purposes.-> + + r_p=(-G*Mt)/v^2 + sqrt(G^2*Mt^2/v^4 + R_c^2) + + (e)We are trying to solve for R_c. We are looking for impact, so we want r_p=Rt + + Rt + G*Mt/v^2 = sqrt(G^2*Mt^2/v^4 + R_c^2)-> + + (Rt + G*Mt/v^2)^2 = G^2*Mt^2/v^4 + R_c^2-> + + Rt^2 + 2*G*Mt*Rt/v^2 + G^2*Mt^2/v^4 = G^2*Mt^2/v^4 + R_c^2-> + + Rt**2 + 2*G*Mt*Rt/v**2 = R_c**2-> + + Rt**2 * (1 + 2*G*Mt/Rt *1/v**2) = R_c**2-> + + escape velocity = sqrt(2GM/R)= v_escape**2=2GM/R-> + + Rt**2 * (1 + v_esc**2/v**2) = R_c**2-> + +(6) + R_capture = Rt * sqrt(1 + v_esc**2/v**2) + +Source: Problem Set 3 #8 c.Fall_2017|Honors Astronomy|Professor Rachel Bezanson + +Source #2: http://www.nssc.ac.cn/wxzygx/weixin/201607/P020160718380095698873.pdf + 8.8 Planetary Rendezvous: Pg.368 +""" From 0ef930697632a1f05dbbd956c4ccab0473025f5b Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Fri, 28 Jul 2023 13:08:40 -0700 Subject: [PATCH 711/726] Disable quantum/quantum_random.py (attempt 2) (#8902) * Disable quantum/quantum_random.py Temporarily disable quantum/quantum_random.py because it produces an illegal instruction error that causes all builds to fail * updating DIRECTORY.md * Disable quantum/quantum_random.py attempt 2 --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 1 - quantum/{quantum_random.py => quantum_random.py.DISABLED.txt} | 0 2 files changed, 1 deletion(-) rename quantum/{quantum_random.py => quantum_random.py.DISABLED.txt} (100%) diff --git a/DIRECTORY.md b/DIRECTORY.md index 29514579c..af150b129 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -1063,7 +1063,6 @@ * [Q Fourier Transform](quantum/q_fourier_transform.py) * [Q Full Adder](quantum/q_full_adder.py) * [Quantum Entanglement](quantum/quantum_entanglement.py) - * [Quantum Random](quantum/quantum_random.py) * [Quantum Teleportation](quantum/quantum_teleportation.py) * [Ripple Adder Classic](quantum/ripple_adder_classic.py) * [Single Qubit Measure](quantum/single_qubit_measure.py) diff --git a/quantum/quantum_random.py b/quantum/quantum_random.py.DISABLED.txt similarity index 100% rename from quantum/quantum_random.py rename to quantum/quantum_random.py.DISABLED.txt From 2cfef0913a36e967d828881386ae78457cf65f33 Mon Sep 17 00:00:00 2001 From: Colin Leroy-Mira Date: Sat, 29 Jul 2023 19:03:43 +0200 Subject: [PATCH 712/726] Fix greyscale computation and inverted coords (#8905) * Fix greyscale computation and inverted coords * Fix test * Add test cases * Add reference to the greyscaling formula --------- Co-authored-by: Colin Leroy-Mira --- digital_image_processing/dithering/burkes.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/digital_image_processing/dithering/burkes.py b/digital_image_processing/dithering/burkes.py index 0804104ab..35aedc16d 100644 --- a/digital_image_processing/dithering/burkes.py +++ b/digital_image_processing/dithering/burkes.py @@ -39,9 +39,18 @@ class Burkes: def get_greyscale(cls, blue: int, green: int, red: int) -> float: """ >>> Burkes.get_greyscale(3, 4, 5) - 3.753 + 4.185 + >>> Burkes.get_greyscale(0, 0, 0) + 0.0 + >>> Burkes.get_greyscale(255, 255, 255) + 255.0 """ - return 0.114 * blue + 0.587 * green + 0.2126 * red + """ + Formula from https://en.wikipedia.org/wiki/HSL_and_HSV + cf Lightness section, and Fig 13c. + We use the first of four possible. + """ + return 0.114 * blue + 0.587 * green + 0.299 * red def process(self) -> None: for y in range(self.height): @@ -49,10 +58,10 @@ class Burkes: greyscale = int(self.get_greyscale(*self.input_img[y][x])) if self.threshold > greyscale + self.error_table[y][x]: self.output_img[y][x] = (0, 0, 0) - current_error = greyscale + self.error_table[x][y] + current_error = greyscale + self.error_table[y][x] else: self.output_img[y][x] = (255, 255, 255) - current_error = greyscale + self.error_table[x][y] - 255 + current_error = greyscale + self.error_table[y][x] - 255 """ Burkes error propagation (`*` is current pixel): From d31750adece86ebf39a09dd3adb2039098f58586 Mon Sep 17 00:00:00 2001 From: Yatharth Mathur <31852880+yatharthmathur@users.noreply.github.com> Date: Sun, 30 Jul 2023 02:27:45 -0700 Subject: [PATCH 713/726] Pythonic implementation of LRU Cache (#4630) * Added a more pythonic implementation of LRU_Cache.[#4628] * Added test cases and doctest * Fixed doc tests * Added more tests in doctests and fixed return types fixes [#4628] * better doctests * added doctests to main() * Added dutch_national_flag.py in sorts. fixing [#4636] * Delete dutch_national_flag.py incorrect commit * Update lru_cache_pythonic.py * Remove pontification --------- Co-authored-by: Christian Clauss --- other/lru_cache_pythonic.py | 113 ++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 other/lru_cache_pythonic.py diff --git a/other/lru_cache_pythonic.py b/other/lru_cache_pythonic.py new file mode 100644 index 000000000..425691ef1 --- /dev/null +++ b/other/lru_cache_pythonic.py @@ -0,0 +1,113 @@ +""" +This implementation of LRU Cache uses the in-built Python dictionary (dict) which from +Python 3.6 onward maintain the insertion order of keys and ensures O(1) operations on +insert, delete and access. https://docs.python.org/3/library/stdtypes.html#typesmapping +""" +from typing import Any, Hashable + + +class LRUCache(dict): + def __init__(self, capacity: int) -> None: + """ + Initialize an LRU Cache with given capacity. + capacity : int -> the capacity of the LRU Cache + >>> cache = LRUCache(2) + >>> cache + {} + """ + self.remaining: int = capacity + + def get(self, key: Hashable) -> Any: + """ + This method returns the value associated with the key. + key : A hashable object that is mapped to a value in the LRU cache. + return -> Any object that has been stored as a value in the LRU cache. + + >>> cache = LRUCache(2) + >>> cache.put(1,1) + >>> cache.get(1) + 1 + >>> cache.get(2) + Traceback (most recent call last): + ... + KeyError: '2 not found.' + """ + if key not in self: + raise KeyError(f"{key} not found.") + val = self.pop(key) # Pop the key-value and re-insert to maintain the order + self[key] = val + return val + + def put(self, key: Hashable, value: Any) -> None: + """ + This method puts the value associated with the key provided in the LRU cache. + key : A hashable object that is mapped to a value in the LRU cache. + value: Any object that is to be associated with the key in the LRU cache. + >>> cache = LRUCache(2) + >>> cache.put(3,3) + >>> cache + {3: 3} + >>> cache.put(2,2) + >>> cache + {3: 3, 2: 2} + """ + # To pop the last value inside of the LRU cache + if key in self: + self.pop(key) + self[key] = value + return + + if self.remaining > 0: + self.remaining -= 1 + # To pop the least recently used item from the dictionary + else: + self.pop(next(iter(self))) + self[key] = value + + +def main() -> None: + """Example test case with LRU_Cache of size 2 + >>> main() + 1 + Key=2 not found in cache + Key=1 not found in cache + 3 + 4 + """ + cache = LRUCache(2) # Creates an LRU cache with size 2 + cache.put(1, 1) # cache = {1:1} + cache.put(2, 2) # cache = {1:1, 2:2} + try: + print(cache.get(1)) # Prints 1 + except KeyError: + print("Key not found in cache") + cache.put( + 3, 3 + ) # cache = {1:1, 3:3} key=2 is evicted because it wasn't used recently + try: + print(cache.get(2)) + except KeyError: + print("Key=2 not found in cache") # Prints key not found + cache.put( + 4, 4 + ) # cache = {4:4, 3:3} key=1 is evicted because it wasn't used recently + try: + print(cache.get(1)) + except KeyError: + print("Key=1 not found in cache") # Prints key not found + try: + print(cache.get(3)) # Prints value 3 + except KeyError: + print("Key not found in cache") + + try: + print(cache.get(4)) # Prints value 4 + except KeyError: + print("Key not found in cache") + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + main() From 8b831cb60003443c9967ac8a33df4151dc883484 Mon Sep 17 00:00:00 2001 From: Bazif Rasool <45148731+Bazifrasool@users.noreply.github.com> Date: Sun, 30 Jul 2023 20:30:58 +0530 Subject: [PATCH 714/726] Added Altitude Pressure equation (#8909) * Added Altitude Pressure equation * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Removed trailing whitespaces * Removed pylint * Fix lru_cache_pythonic.py * Fixed spellings * Fix again lru_cache_pythonic.py * Update .vscode/settings.json Co-authored-by: Christian Clauss * Third fix lru_cache_pythonic.py * Update .vscode/settings.json Co-authored-by: Christian Clauss * 4th fix lru_cache_pythonic.py * Update physics/altitude_pressure.py Co-authored-by: Christian Clauss * lru_cache_pythonic.py: def get(self, key: Any, /) -> Any | None: * Delete lru_cache_pythonic.py * Added positive and negative pressure test cases * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- other/lru_cache_pythonic.py | 113 ----------------------------------- physics/altitude_pressure.py | 52 ++++++++++++++++ 2 files changed, 52 insertions(+), 113 deletions(-) delete mode 100644 other/lru_cache_pythonic.py create mode 100644 physics/altitude_pressure.py diff --git a/other/lru_cache_pythonic.py b/other/lru_cache_pythonic.py deleted file mode 100644 index 425691ef1..000000000 --- a/other/lru_cache_pythonic.py +++ /dev/null @@ -1,113 +0,0 @@ -""" -This implementation of LRU Cache uses the in-built Python dictionary (dict) which from -Python 3.6 onward maintain the insertion order of keys and ensures O(1) operations on -insert, delete and access. https://docs.python.org/3/library/stdtypes.html#typesmapping -""" -from typing import Any, Hashable - - -class LRUCache(dict): - def __init__(self, capacity: int) -> None: - """ - Initialize an LRU Cache with given capacity. - capacity : int -> the capacity of the LRU Cache - >>> cache = LRUCache(2) - >>> cache - {} - """ - self.remaining: int = capacity - - def get(self, key: Hashable) -> Any: - """ - This method returns the value associated with the key. - key : A hashable object that is mapped to a value in the LRU cache. - return -> Any object that has been stored as a value in the LRU cache. - - >>> cache = LRUCache(2) - >>> cache.put(1,1) - >>> cache.get(1) - 1 - >>> cache.get(2) - Traceback (most recent call last): - ... - KeyError: '2 not found.' - """ - if key not in self: - raise KeyError(f"{key} not found.") - val = self.pop(key) # Pop the key-value and re-insert to maintain the order - self[key] = val - return val - - def put(self, key: Hashable, value: Any) -> None: - """ - This method puts the value associated with the key provided in the LRU cache. - key : A hashable object that is mapped to a value in the LRU cache. - value: Any object that is to be associated with the key in the LRU cache. - >>> cache = LRUCache(2) - >>> cache.put(3,3) - >>> cache - {3: 3} - >>> cache.put(2,2) - >>> cache - {3: 3, 2: 2} - """ - # To pop the last value inside of the LRU cache - if key in self: - self.pop(key) - self[key] = value - return - - if self.remaining > 0: - self.remaining -= 1 - # To pop the least recently used item from the dictionary - else: - self.pop(next(iter(self))) - self[key] = value - - -def main() -> None: - """Example test case with LRU_Cache of size 2 - >>> main() - 1 - Key=2 not found in cache - Key=1 not found in cache - 3 - 4 - """ - cache = LRUCache(2) # Creates an LRU cache with size 2 - cache.put(1, 1) # cache = {1:1} - cache.put(2, 2) # cache = {1:1, 2:2} - try: - print(cache.get(1)) # Prints 1 - except KeyError: - print("Key not found in cache") - cache.put( - 3, 3 - ) # cache = {1:1, 3:3} key=2 is evicted because it wasn't used recently - try: - print(cache.get(2)) - except KeyError: - print("Key=2 not found in cache") # Prints key not found - cache.put( - 4, 4 - ) # cache = {4:4, 3:3} key=1 is evicted because it wasn't used recently - try: - print(cache.get(1)) - except KeyError: - print("Key=1 not found in cache") # Prints key not found - try: - print(cache.get(3)) # Prints value 3 - except KeyError: - print("Key not found in cache") - - try: - print(cache.get(4)) # Prints value 4 - except KeyError: - print("Key not found in cache") - - -if __name__ == "__main__": - import doctest - - doctest.testmod() - main() diff --git a/physics/altitude_pressure.py b/physics/altitude_pressure.py new file mode 100644 index 000000000..65307d223 --- /dev/null +++ b/physics/altitude_pressure.py @@ -0,0 +1,52 @@ +""" +Title : Calculate altitude using Pressure + +Description : + The below algorithm approximates the altitude using Barometric formula + + +""" + + +def get_altitude_at_pressure(pressure: float) -> float: + """ + This method calculates the altitude from Pressure wrt to + Sea level pressure as reference .Pressure is in Pascals + https://en.wikipedia.org/wiki/Pressure_altitude + https://community.bosch-sensortec.com/t5/Question-and-answers/How-to-calculate-the-altitude-from-the-pressure-sensor-data/qaq-p/5702 + + H = 44330 * [1 - (P/p0)^(1/5.255) ] + + Where : + H = altitude (m) + P = measured pressure + p0 = reference pressure at sea level 101325 Pa + + Examples: + >>> get_altitude_at_pressure(pressure=100_000) + 105.47836610778828 + >>> get_altitude_at_pressure(pressure=101_325) + 0.0 + >>> get_altitude_at_pressure(pressure=80_000) + 1855.873388064995 + >>> get_altitude_at_pressure(pressure=201_325) + Traceback (most recent call last): + ... + ValueError: Value Higher than Pressure at Sea Level ! + >>> get_altitude_at_pressure(pressure=-80_000) + Traceback (most recent call last): + ... + ValueError: Atmospheric Pressure can not be negative ! + """ + + if pressure > 101325: + raise ValueError("Value Higher than Pressure at Sea Level !") + if pressure < 0: + raise ValueError("Atmospheric Pressure can not be negative !") + return 44_330 * (1 - (pressure / 101_325) ** (1 / 5.5255)) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From d4f2873e39f041513aa9f5c287ec9b46e2236dad Mon Sep 17 00:00:00 2001 From: AmirSoroush Date: Mon, 31 Jul 2023 03:54:15 +0300 Subject: [PATCH 715/726] add reverse_inorder traversal to binary_tree_traversals.py (#8726) * add reverse_inorder traversal to binary_tree_traversals.py * Apply suggestions from code review Co-authored-by: Tianyi Zheng --------- Co-authored-by: Tianyi Zheng --- .../binary_tree/binary_tree_traversals.py | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/data_structures/binary_tree/binary_tree_traversals.py b/data_structures/binary_tree/binary_tree_traversals.py index 71a895e76..2afb7604f 100644 --- a/data_structures/binary_tree/binary_tree_traversals.py +++ b/data_structures/binary_tree/binary_tree_traversals.py @@ -58,6 +58,19 @@ def inorder(root: Node | None) -> list[int]: return [*inorder(root.left), root.data, *inorder(root.right)] if root else [] +def reverse_inorder(root: Node | None) -> list[int]: + """ + Reverse in-order traversal visits right subtree, root node, left subtree. + >>> reverse_inorder(make_tree()) + [3, 1, 5, 2, 4] + """ + return ( + [*reverse_inorder(root.right), root.data, *reverse_inorder(root.left)] + if root + else [] + ) + + def height(root: Node | None) -> int: """ Recursive function for calculating the height of the binary tree. @@ -161,15 +174,12 @@ def zigzag(root: Node | None) -> Sequence[Node | None] | list[Any]: def main() -> None: # Main function for testing. - """ - Create binary tree. - """ + # Create binary tree. root = make_tree() - """ - All Traversals of the binary are as follows: - """ + # All Traversals of the binary are as follows: print(f"In-order Traversal: {inorder(root)}") + print(f"Reverse In-order Traversal: {reverse_inorder(root)}") print(f"Pre-order Traversal: {preorder(root)}") print(f"Post-order Traversal: {postorder(root)}", "\n") From 4710e51deb2dc07e32884391a36d40e08398e6be Mon Sep 17 00:00:00 2001 From: David Leal Date: Sun, 30 Jul 2023 19:15:30 -0600 Subject: [PATCH 716/726] chore: use newest Discord invite link (#8696) * updating DIRECTORY.md * chore: use newest Discord invite link --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bf6e0ed3c..d8eba4e01 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Contributions Welcome - + Discord chat @@ -42,7 +42,7 @@ Read through our [Contribution Guidelines](CONTRIBUTING.md) before you contribut ## Community Channels -We are on [Discord](https://discord.gg/c7MnfGFGa6) and [Gitter](https://gitter.im/TheAlgorithms/community)! Community channels are a great way for you to ask questions and get help. Please join us! +We are on [Discord](https://the-algorithms.com/discord) and [Gitter](https://gitter.im/TheAlgorithms/community)! Community channels are a great way for you to ask questions and get help. Please join us! ## List of Algorithms From 8cce9cf066396bb220515c03849fbc1a16d800d0 Mon Sep 17 00:00:00 2001 From: Almas Bekbayev <121730304+bekbayev@users.noreply.github.com> Date: Mon, 31 Jul 2023 07:32:05 +0600 Subject: [PATCH 717/726] Fix linear_search docstring return value (#8644) --- searches/linear_search.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/searches/linear_search.py b/searches/linear_search.py index 777080d14..ba6e81d6b 100644 --- a/searches/linear_search.py +++ b/searches/linear_search.py @@ -15,7 +15,7 @@ def linear_search(sequence: list, target: int) -> int: :param sequence: a collection with comparable items (as sorted items not required in Linear Search) :param target: item value to search - :return: index of found item or None if item is not found + :return: index of found item or -1 if item is not found Examples: >>> linear_search([0, 5, 7, 10, 15], 0) From 384c407a265ac44d15eecdd339bb154147cda4f8 Mon Sep 17 00:00:00 2001 From: AmirSoroush Date: Mon, 31 Jul 2023 05:07:35 +0300 Subject: [PATCH 718/726] Enhance the implementation of Queue using list (#8608) * enhance the implementation of queue using list * enhance readability of queue_on_list.py * rename 'queue_on_list' to 'queue_by_list' to match the class name --- data_structures/queue/queue_by_list.py | 141 +++++++++++++++++++++++++ data_structures/queue/queue_on_list.py | 52 --------- 2 files changed, 141 insertions(+), 52 deletions(-) create mode 100644 data_structures/queue/queue_by_list.py delete mode 100644 data_structures/queue/queue_on_list.py diff --git a/data_structures/queue/queue_by_list.py b/data_structures/queue/queue_by_list.py new file mode 100644 index 000000000..4b05be9fd --- /dev/null +++ b/data_structures/queue/queue_by_list.py @@ -0,0 +1,141 @@ +"""Queue represented by a Python list""" + +from collections.abc import Iterable +from typing import Generic, TypeVar + +_T = TypeVar("_T") + + +class QueueByList(Generic[_T]): + def __init__(self, iterable: Iterable[_T] | None = None) -> None: + """ + >>> QueueByList() + Queue(()) + >>> QueueByList([10, 20, 30]) + Queue((10, 20, 30)) + >>> QueueByList((i**2 for i in range(1, 4))) + Queue((1, 4, 9)) + """ + self.entries: list[_T] = list(iterable or []) + + def __len__(self) -> int: + """ + >>> len(QueueByList()) + 0 + >>> from string import ascii_lowercase + >>> len(QueueByList(ascii_lowercase)) + 26 + >>> queue = QueueByList() + >>> for i in range(1, 11): + ... queue.put(i) + >>> len(queue) + 10 + >>> for i in range(2): + ... queue.get() + 1 + 2 + >>> len(queue) + 8 + """ + + return len(self.entries) + + def __repr__(self) -> str: + """ + >>> queue = QueueByList() + >>> queue + Queue(()) + >>> str(queue) + 'Queue(())' + >>> queue.put(10) + >>> queue + Queue((10,)) + >>> queue.put(20) + >>> queue.put(30) + >>> queue + Queue((10, 20, 30)) + """ + + return f"Queue({tuple(self.entries)})" + + def put(self, item: _T) -> None: + """Put `item` to the Queue + + >>> queue = QueueByList() + >>> queue.put(10) + >>> queue.put(20) + >>> len(queue) + 2 + >>> queue + Queue((10, 20)) + """ + + self.entries.append(item) + + def get(self) -> _T: + """ + Get `item` from the Queue + + >>> queue = QueueByList((10, 20, 30)) + >>> queue.get() + 10 + >>> queue.put(40) + >>> queue.get() + 20 + >>> queue.get() + 30 + >>> len(queue) + 1 + >>> queue.get() + 40 + >>> queue.get() + Traceback (most recent call last): + ... + IndexError: Queue is empty + """ + + if not self.entries: + raise IndexError("Queue is empty") + return self.entries.pop(0) + + def rotate(self, rotation: int) -> None: + """Rotate the items of the Queue `rotation` times + + >>> queue = QueueByList([10, 20, 30, 40]) + >>> queue + Queue((10, 20, 30, 40)) + >>> queue.rotate(1) + >>> queue + Queue((20, 30, 40, 10)) + >>> queue.rotate(2) + >>> queue + Queue((40, 10, 20, 30)) + """ + + put = self.entries.append + get = self.entries.pop + + for _ in range(rotation): + put(get(0)) + + def get_front(self) -> _T: + """Get the front item from the Queue + + >>> queue = QueueByList((10, 20, 30)) + >>> queue.get_front() + 10 + >>> queue + Queue((10, 20, 30)) + >>> queue.get() + 10 + >>> queue.get_front() + 20 + """ + + return self.entries[0] + + +if __name__ == "__main__": + from doctest import testmod + + testmod() diff --git a/data_structures/queue/queue_on_list.py b/data_structures/queue/queue_on_list.py deleted file mode 100644 index 71fca6b2f..000000000 --- a/data_structures/queue/queue_on_list.py +++ /dev/null @@ -1,52 +0,0 @@ -"""Queue represented by a Python list""" - - -class Queue: - def __init__(self): - self.entries = [] - self.length = 0 - self.front = 0 - - def __str__(self): - printed = "<" + str(self.entries)[1:-1] + ">" - return printed - - """Enqueues {@code item} - @param item - item to enqueue""" - - def put(self, item): - self.entries.append(item) - self.length = self.length + 1 - - """Dequeues {@code item} - @requirement: |self.length| > 0 - @return dequeued - item that was dequeued""" - - def get(self): - self.length = self.length - 1 - dequeued = self.entries[self.front] - # self.front-=1 - # self.entries = self.entries[self.front:] - self.entries = self.entries[1:] - return dequeued - - """Rotates the queue {@code rotation} times - @param rotation - number of times to rotate queue""" - - def rotate(self, rotation): - for _ in range(rotation): - self.put(self.get()) - - """Enqueues {@code item} - @return item at front of self.entries""" - - def get_front(self): - return self.entries[0] - - """Returns the length of this.entries""" - - def size(self): - return self.length From 629eb86ce0d30dd6031fa482f4a477ac3df345ab Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Sun, 30 Jul 2023 22:23:23 -0700 Subject: [PATCH 719/726] Fix merge conflicts to merge change from #5080 (#8911) * Input for user choose his Collatz sequence Now the user can tell the algorithm what number he wants to run on the Collatz Sequence. * updating DIRECTORY.md --------- Co-authored-by: Hugo Folloni Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 1 + maths/collatz_sequence.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index af150b129..aa9bd313b 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -740,6 +740,7 @@ * [Tower Of Hanoi](other/tower_of_hanoi.py) ## Physics + * [Altitude Pressure](physics/altitude_pressure.py) * [Archimedes Principle](physics/archimedes_principle.py) * [Basic Orbital Capture](physics/basic_orbital_capture.py) * [Casimir Effect](physics/casimir_effect.py) diff --git a/maths/collatz_sequence.py b/maths/collatz_sequence.py index 4f3aa5582..b47017146 100644 --- a/maths/collatz_sequence.py +++ b/maths/collatz_sequence.py @@ -57,7 +57,7 @@ def collatz_sequence(n: int) -> Generator[int, None, None]: def main(): - n = 43 + n = int(input("Your number: ")) sequence = tuple(collatz_sequence(n)) print(sequence) print(f"Collatz sequence from {n} took {len(sequence)} steps.") From 0b0214c42f563e7af885058c0e3a32d292f7f1da Mon Sep 17 00:00:00 2001 From: roger-sato Date: Tue, 1 Aug 2023 03:46:30 +0900 Subject: [PATCH 720/726] Handle empty input case in Segment Tree build process (#8718) --- data_structures/binary_tree/segment_tree.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data_structures/binary_tree/segment_tree.py b/data_structures/binary_tree/segment_tree.py index b05803869..5f822407d 100644 --- a/data_structures/binary_tree/segment_tree.py +++ b/data_structures/binary_tree/segment_tree.py @@ -7,7 +7,8 @@ class SegmentTree: self.st = [0] * ( 4 * self.N ) # approximate the overall size of segment tree with array N - self.build(1, 0, self.N - 1) + if self.N: + self.build(1, 0, self.N - 1) def left(self, idx): return idx * 2 From 90a8e6e0d210a5c526c8f485fa825e1649d217e2 Mon Sep 17 00:00:00 2001 From: Dylan Buchi Date: Mon, 31 Jul 2023 15:50:00 -0300 Subject: [PATCH 721/726] Update `sorts/bubble_sort.py` (#5802) * Add missing type annotations in bubble_sort.py * Refactor bubble_sort function --- sorts/bubble_sort.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sorts/bubble_sort.py b/sorts/bubble_sort.py index aef2da272..7da4362a5 100644 --- a/sorts/bubble_sort.py +++ b/sorts/bubble_sort.py @@ -1,4 +1,7 @@ -def bubble_sort(collection): +from typing import Any + + +def bubble_sort(collection: list[Any]) -> list[Any]: """Pure implementation of bubble sort algorithm in Python :param collection: some mutable ordered collection with heterogeneous @@ -28,9 +31,9 @@ def bubble_sort(collection): True """ length = len(collection) - for i in range(length - 1): + for i in reversed(range(length)): swapped = False - for j in range(length - 1 - i): + for j in range(i): if collection[j] > collection[j + 1]: swapped = True collection[j], collection[j + 1] = collection[j + 1], collection[j] From 5cf34d901e32b65425103309bbad0068b1851238 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Mon, 31 Jul 2023 13:53:26 -0700 Subject: [PATCH 722/726] Ruff fixes (#8913) * updating DIRECTORY.md * Fix ruff error in eulerian_path_and_circuit_for_undirected_graph.py * Fix ruff error in newtons_second_law_of_motion.py --------- Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 2 +- graphs/eulerian_path_and_circuit_for_undirected_graph.py | 2 +- physics/newtons_second_law_of_motion.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index aa9bd313b..fdcf0ceed 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -236,8 +236,8 @@ * [Double Ended Queue](data_structures/queue/double_ended_queue.py) * [Linked Queue](data_structures/queue/linked_queue.py) * [Priority Queue Using List](data_structures/queue/priority_queue_using_list.py) + * [Queue By List](data_structures/queue/queue_by_list.py) * [Queue By Two Stacks](data_structures/queue/queue_by_two_stacks.py) - * [Queue On List](data_structures/queue/queue_on_list.py) * [Queue On Pseudo Stack](data_structures/queue/queue_on_pseudo_stack.py) * Stacks * [Balanced Parentheses](data_structures/stacks/balanced_parentheses.py) diff --git a/graphs/eulerian_path_and_circuit_for_undirected_graph.py b/graphs/eulerian_path_and_circuit_for_undirected_graph.py index 6c43c5d3e..6b4ea8e21 100644 --- a/graphs/eulerian_path_and_circuit_for_undirected_graph.py +++ b/graphs/eulerian_path_and_circuit_for_undirected_graph.py @@ -20,7 +20,7 @@ def check_circuit_or_path(graph, max_node): odd_degree_nodes = 0 odd_node = -1 for i in range(max_node): - if i not in graph.keys(): + if i not in graph: continue if len(graph[i]) % 2 == 1: odd_degree_nodes += 1 diff --git a/physics/newtons_second_law_of_motion.py b/physics/newtons_second_law_of_motion.py index cb53f8f65..53fab6ce7 100644 --- a/physics/newtons_second_law_of_motion.py +++ b/physics/newtons_second_law_of_motion.py @@ -60,7 +60,7 @@ def newtons_second_law_of_motion(mass: float, acceleration: float) -> float: >>> newtons_second_law_of_motion(2.0, 1) 2.0 """ - force = float() + force = 0.0 try: force = mass * acceleration except Exception: From f8fe72dc378232107100acc1924fef31b1198124 Mon Sep 17 00:00:00 2001 From: "Minha, Jeong" Date: Tue, 1 Aug 2023 06:24:12 +0900 Subject: [PATCH 723/726] Update game_of_life.py (#4921) * Update game_of_life.py docstring error fix delete no reason delete next_gen_canvas code(local variable) * Update cellular_automata/game_of_life.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Tianyi Zheng Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- cellular_automata/game_of_life.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/cellular_automata/game_of_life.py b/cellular_automata/game_of_life.py index b69afdce0..d691a2b73 100644 --- a/cellular_automata/game_of_life.py +++ b/cellular_automata/game_of_life.py @@ -10,7 +10,7 @@ Python: - 3.5 Usage: - - $python3 game_o_life + - $python3 game_of_life Game-Of-Life Rules: @@ -52,7 +52,8 @@ def seed(canvas: list[list[bool]]) -> None: def run(canvas: list[list[bool]]) -> list[list[bool]]: - """This function runs the rules of game through all points, and changes their + """ + This function runs the rules of game through all points, and changes their status accordingly.(in the same canvas) @Args: -- @@ -60,7 +61,7 @@ def run(canvas: list[list[bool]]) -> list[list[bool]]: @returns: -- - None + canvas of population after one step """ current_canvas = np.array(canvas) next_gen_canvas = np.array(create_canvas(current_canvas.shape[0])) @@ -70,10 +71,7 @@ def run(canvas: list[list[bool]]) -> list[list[bool]]: pt, current_canvas[r - 1 : r + 2, c - 1 : c + 2] ) - current_canvas = next_gen_canvas - del next_gen_canvas # cleaning memory as we move on. - return_canvas: list[list[bool]] = current_canvas.tolist() - return return_canvas + return next_gen_canvas.tolist() def __judge_point(pt: bool, neighbours: list[list[bool]]) -> bool: From f7c5e55609afa1e4e7ae2ee3f442bbd5d0b43b8a Mon Sep 17 00:00:00 2001 From: Jan Wojciechowski <96974442+yanvoi@users.noreply.github.com> Date: Tue, 1 Aug 2023 05:02:49 +0200 Subject: [PATCH 724/726] Window closing fix (#8625) * The window will now remain open after the fractal is finished being drawn, and will only close upon your click. * Update fractals/sierpinski_triangle.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Tianyi Zheng Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- fractals/sierpinski_triangle.py | 1 + 1 file changed, 1 insertion(+) diff --git a/fractals/sierpinski_triangle.py b/fractals/sierpinski_triangle.py index c28ec00b2..45f7ab84c 100644 --- a/fractals/sierpinski_triangle.py +++ b/fractals/sierpinski_triangle.py @@ -82,3 +82,4 @@ if __name__ == "__main__": vertices = [(-175, -125), (0, 175), (175, -125)] # vertices of triangle triangle(vertices[0], vertices[1], vertices[2], int(sys.argv[1])) + turtle.Screen().exitonclick() From c9a7234a954dd280dc8192ae77a564e647d013d4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 09:26:23 +0530 Subject: [PATCH 725/726] [pre-commit.ci] pre-commit autoupdate (#8914) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.0.280 → v0.0.281](https://github.com/astral-sh/ruff-pre-commit/compare/v0.0.280...v0.0.281) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5adf12cc7..e158bd8d6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: auto-walrus - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.0.280 + rev: v0.0.281 hooks: - id: ruff From ce218c57f1f494cfca69bc01ba660c97385e5330 Mon Sep 17 00:00:00 2001 From: AmirSoroush Date: Tue, 1 Aug 2023 21:23:34 +0300 Subject: [PATCH 726/726] =?UTF-8?q?fixes=20#8673;=20Add=20operator's=20ass?= =?UTF-8?q?ociativity=20check=20for=20stacks/infix=5Fto=5Fp=E2=80=A6=20(#8?= =?UTF-8?q?674)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fixes #8673; Add operator's associativity check for stacks/infix_to_postfix_conversion.py * fix ruff N806 in stacks/infix_to_postfix_conversion.py * Update data_structures/stacks/infix_to_postfix_conversion.py Co-authored-by: Tianyi Zheng * Update data_structures/stacks/infix_to_postfix_conversion.py Co-authored-by: Tianyi Zheng --------- Co-authored-by: Tianyi Zheng --- .../stacks/infix_to_postfix_conversion.py | 50 +++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/data_structures/stacks/infix_to_postfix_conversion.py b/data_structures/stacks/infix_to_postfix_conversion.py index 901744309..e69706193 100644 --- a/data_structures/stacks/infix_to_postfix_conversion.py +++ b/data_structures/stacks/infix_to_postfix_conversion.py @@ -4,9 +4,26 @@ https://en.wikipedia.org/wiki/Reverse_Polish_notation https://en.wikipedia.org/wiki/Shunting-yard_algorithm """ +from typing import Literal + from .balanced_parentheses import balanced_parentheses from .stack import Stack +PRECEDENCES: dict[str, int] = { + "+": 1, + "-": 1, + "*": 2, + "/": 2, + "^": 3, +} +ASSOCIATIVITIES: dict[str, Literal["LR", "RL"]] = { + "+": "LR", + "-": "LR", + "*": "LR", + "/": "LR", + "^": "RL", +} + def precedence(char: str) -> int: """ @@ -14,7 +31,15 @@ def precedence(char: str) -> int: order of operation. https://en.wikipedia.org/wiki/Order_of_operations """ - return {"+": 1, "-": 1, "*": 2, "/": 2, "^": 3}.get(char, -1) + return PRECEDENCES.get(char, -1) + + +def associativity(char: str) -> Literal["LR", "RL"]: + """ + Return the associativity of the operator `char`. + https://en.wikipedia.org/wiki/Operator_associativity + """ + return ASSOCIATIVITIES[char] def infix_to_postfix(expression_str: str) -> str: @@ -35,6 +60,8 @@ def infix_to_postfix(expression_str: str) -> str: 'a b c * + d e * f + g * +' >>> infix_to_postfix("x^y/(5*z)+2") 'x y ^ 5 z * / 2 +' + >>> infix_to_postfix("2^3^2") + '2 3 2 ^ ^' """ if not balanced_parentheses(expression_str): raise ValueError("Mismatched parentheses") @@ -50,9 +77,26 @@ def infix_to_postfix(expression_str: str) -> str: postfix.append(stack.pop()) stack.pop() else: - while not stack.is_empty() and precedence(char) <= precedence(stack.peek()): + while True: + if stack.is_empty(): + stack.push(char) + break + + char_precedence = precedence(char) + tos_precedence = precedence(stack.peek()) + + if char_precedence > tos_precedence: + stack.push(char) + break + if char_precedence < tos_precedence: + postfix.append(stack.pop()) + continue + # Precedences are equal + if associativity(char) == "RL": + stack.push(char) + break postfix.append(stack.pop()) - stack.push(char) + while not stack.is_empty(): postfix.append(stack.pop()) return " ".join(postfix)