From 10b1a2a32d69c07e8bb25cb3ae5557e19ea3d095 Mon Sep 17 00:00:00 2001 From: MapleBauhinia <3626172038@qq.com> Date: Sat, 5 Jul 2025 13:03:06 +0800 Subject: [PATCH 01/15] Add Traveling Salesman Problem algorithms and tests --- .../tests/test_traveling_salesman_problem.py | 48 ++++++ graphs/traveling_salesman_problem.py | 151 ++++++++++++++++++ 2 files changed, 199 insertions(+) create mode 100644 graphs/tests/test_traveling_salesman_problem.py create mode 100644 graphs/traveling_salesman_problem.py diff --git a/graphs/tests/test_traveling_salesman_problem.py b/graphs/tests/test_traveling_salesman_problem.py new file mode 100644 index 000000000000..c2919ba8e776 --- /dev/null +++ b/graphs/tests/test_traveling_salesman_problem.py @@ -0,0 +1,48 @@ +import pytest +from graphs.traveling_salesman_problem import tsp_brute_force, tsp_dp, tsp_greedy + +def sample_graph_1() -> list[list[int]]: + return [ + [0, 29, 20], + [29, 0, 15], + [20, 15, 0], + ] + +def sample_graph_2() -> list[list[int]]: + return [ + [0, 10, 15, 20], + [10, 0, 35, 25], + [15, 35, 0, 30], + [20, 25, 30, 0], + ] + +def test_brute_force(): + graph = sample_graph_1() + assert tsp_brute_force(graph) == 64 + +def test_dp(): + graph = sample_graph_1() + assert tsp_dp(graph) == 64 + +def test_greedy(): + graph = sample_graph_1() + # The greedy algorithm does not guarantee an optimal solution; + # it is necessary to verify that its output is an integer greater than 0. + result = tsp_greedy(graph) + assert isinstance(result, int) + assert result > 0 + +def test_dp_larger_graph(): + graph = sample_graph_2() + assert tsp_dp(graph) == 80 + +def test_brute_force_larger_graph(): + graph = sample_graph_2() + assert tsp_brute_force(graph) == 80 + +def test_greedy_larger_graph(): + graph = sample_graph_2() + # An approximate solution cannot be represented by '==' and can only ensure that the result is reasonable. + result = tsp_greedy(graph) + assert isinstance(result, int) + assert result >= 80 diff --git a/graphs/traveling_salesman_problem.py b/graphs/traveling_salesman_problem.py new file mode 100644 index 000000000000..969008a6dfec --- /dev/null +++ b/graphs/traveling_salesman_problem.py @@ -0,0 +1,151 @@ +from itertools import permutations + +def tsp_brute_force(graph: list[list[int]]) -> int: + """ + Solves TSP using brute-force permutations. + + Args: + graph: 2D list representing distances between cities. + + Returns: + The minimal total travel distance visiting all cities exactly once and returning to the start. + + Example: + >>> tsp_brute_force([[0, 29, 20], [29, 0, 15], [20, 15, 0]]) + 64 + """ + n = len(graph) + # Apart from other cities aside from City 0, City 0 serves as the starting point. + nodes = list(range(1, n)) + min_path = float('inf') + + # Enumerate all the permutations from city 1 to city n-1. + for perm in permutations(nodes): + # Construct a complete path: + # starting from point 0, visit in the order of arrangement, and then return to point 0. + path = [0] + list(perm) + [0] + + # Calculate the total distance of the path. + # Update the shortest path. + total_cost = sum(graph[path[i]][path[i + 1]] for i in range(n)) + min_path = min(min_path, total_cost) + + return min_path + +def tsp_dp(graph: list[list[int]]) -> int: + """ + Solves the Traveling Salesman Problem using Held-Karp dynamic programming. + + Args: + graph: A 2D list representing distances between cities (n x n matrix). + + Returns: + The minimum cost to visit all cities exactly once and return to the origin. + + Example: + >>> tsp_dp([[0, 29, 20], [29, 0, 15], [20, 15, 0]]) + 64 + """ + n = len(graph) + # Create a dynamic programming table of size (2^n) x n. + # Noting: 1 << n = 2^n + # dp[mask][i] represents the shortest path starting from city 0, passing through the cities in the mask, and ultimately ending at city i. + dp = [[float('inf')] * n for _ in range(1 << n)] + # Initial state: only city 0 is visited, and the path length is 0. + dp[1][0] = 0 + + for mask in range(1 << n): + # The mask indicates which cities have been visited. + for u in range(n): + if not (mask & (1 << u)): + # If the city u is not included in the mask, skip it. + continue + + for v in range(n): + # City v has not been accessed and is different from city u. + if mask & (1 << v) or u == v: + continue + + # New State: Transition to city v + # State Transition: From city u to city v, updating the shortest path. + next_mask = mask | (1 << v) + dp[next_mask][v] = min(dp[next_mask][v], dp[mask][u] + graph[u][v]) + + # After completing visits to all cities, return to city 0 and obtain the minimum value. + return min(dp[(1 << n) - 1][i] + graph[i][0] for i in range(1, n)) + +def tsp_greedy(graph: list[list[int]]) -> int: + """ + Solves TSP approximately using the nearest neighbor heuristic. + Warming: This algorithm is not guaranteed to find the optimal solution! But it is fast and applicable to any input size. + + Args: + graph: 2D list representing distances between cities. + + Returns: + The total distance of the approximated TSP route. + + Example: + >>> tsp_greedy([[0, 29, 20], [29, 0, 15], [20, 15, 0]]) + 64 + """ + n = len(graph) + visited = [False] * n # Mark whether each city has been visited. + path = [0] + total_cost = 0 + visited[0] = True # Start from city 0. + current = 0 # Current city. + + for _ in range(n - 1): + # Find the nearest city to the current location that has not been visited. + next_city = min( + ((city, cost) for city, cost in enumerate(graph[current]) if not visited[city] and city != current), + key=lambda x: x[1], + default=(None, float('inf')) + )[0] + + # If no such city exists, break the loop. + if next_city is None: + break + + # Update the total cost and the current city. + # Mark the city as visited. + # Append the city to the path. + total_cost += graph[current][next_city] + visited[next_city] = True + current = next_city + path.append(current) + + # Back to start + total_cost += graph[current][0] + path.append(0) + + return total_cost + + +def test_tsp_example(): + graph = [[0, 29, 20], [29, 0, 15], [20, 15, 0]] + + result = tsp_brute_force(graph) + if result != 64: + raise Exception('tsp_brute_force Incorrect result') + else: + print('Test passed') + + result = tsp_dp(graph) + if result != 64: + raise Exception('tsp_dp Incorrect result') + else: + print("Test passed") + + result = tsp_greedy(graph) + if result != 64: + if result < 0: + raise Exception('tsp_greedy Incorrect result') + else: + print("tsp_greedy gets an approximate result.") + else: + print('Test passed') + +if __name__ == '__main__': + test_tsp_example() \ No newline at end of file From e39c3ce8c77daf05af89cbcf9548c9343d6dc237 Mon Sep 17 00:00:00 2001 From: MapleBauhinia <3626172038@qq.com> Date: Sat, 5 Jul 2025 14:47:03 +0800 Subject: [PATCH 02/15] Add TSP Problem --- graphs/tests/test_traveling_salesman_problem.py | 4 ++-- graphs/traveling_salesman_problem.py | 15 +++++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/graphs/tests/test_traveling_salesman_problem.py b/graphs/tests/test_traveling_salesman_problem.py index c2919ba8e776..3b3b9441ef66 100644 --- a/graphs/tests/test_traveling_salesman_problem.py +++ b/graphs/tests/test_traveling_salesman_problem.py @@ -28,9 +28,10 @@ def test_greedy(): graph = sample_graph_1() # The greedy algorithm does not guarantee an optimal solution; # it is necessary to verify that its output is an integer greater than 0. + # An approximate solution cannot be represented by '==' and can only ensure that the result is reasonable. result = tsp_greedy(graph) assert isinstance(result, int) - assert result > 0 + assert result >= 64 def test_dp_larger_graph(): graph = sample_graph_2() @@ -42,7 +43,6 @@ def test_brute_force_larger_graph(): def test_greedy_larger_graph(): graph = sample_graph_2() - # An approximate solution cannot be represented by '==' and can only ensure that the result is reasonable. result = tsp_greedy(graph) assert isinstance(result, int) assert result >= 80 diff --git a/graphs/traveling_salesman_problem.py b/graphs/traveling_salesman_problem.py index 969008a6dfec..5985d9b1ee16 100644 --- a/graphs/traveling_salesman_problem.py +++ b/graphs/traveling_salesman_problem.py @@ -88,6 +88,8 @@ def tsp_greedy(graph: list[list[int]]) -> int: Example: >>> tsp_greedy([[0, 29, 20], [29, 0, 15], [20, 15, 0]]) 64 + >>> tsp_greedy([[0, 10, 15, 20], [10, 0, 35, 25], [15, 35, 0, 30], [20, 25, 30, 0]]) + 80 """ n = len(graph) visited = [False] * n # Mark whether each city has been visited. @@ -124,22 +126,27 @@ def tsp_greedy(graph: list[list[int]]) -> int: def test_tsp_example(): - graph = [[0, 29, 20], [29, 0, 15], [20, 15, 0]] + graph = [ + [0, 10, 15, 20], + [10, 0, 35, 25], + [15, 35, 0, 30], + [20, 25, 30, 0], + ] result = tsp_brute_force(graph) - if result != 64: + if result != 80: raise Exception('tsp_brute_force Incorrect result') else: print('Test passed') result = tsp_dp(graph) - if result != 64: + if result != 80: raise Exception('tsp_dp Incorrect result') else: print("Test passed") result = tsp_greedy(graph) - if result != 64: + if result != 80: if result < 0: raise Exception('tsp_greedy Incorrect result') else: From c32a022a18274df74217b4fa4b52857faf98d643 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 5 Jul 2025 07:39:01 +0000 Subject: [PATCH 03/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../tests/test_traveling_salesman_problem.py | 12 ++++- graphs/traveling_salesman_problem.py | 46 +++++++++++-------- 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/graphs/tests/test_traveling_salesman_problem.py b/graphs/tests/test_traveling_salesman_problem.py index 3b3b9441ef66..acca211b0f31 100644 --- a/graphs/tests/test_traveling_salesman_problem.py +++ b/graphs/tests/test_traveling_salesman_problem.py @@ -1,6 +1,7 @@ import pytest from graphs.traveling_salesman_problem import tsp_brute_force, tsp_dp, tsp_greedy + def sample_graph_1() -> list[list[int]]: return [ [0, 29, 20], @@ -8,6 +9,7 @@ def sample_graph_1() -> list[list[int]]: [20, 15, 0], ] + def sample_graph_2() -> list[list[int]]: return [ [0, 10, 15, 20], @@ -16,31 +18,37 @@ def sample_graph_2() -> list[list[int]]: [20, 25, 30, 0], ] + def test_brute_force(): graph = sample_graph_1() assert tsp_brute_force(graph) == 64 + def test_dp(): graph = sample_graph_1() assert tsp_dp(graph) == 64 + def test_greedy(): graph = sample_graph_1() - # The greedy algorithm does not guarantee an optimal solution; + # The greedy algorithm does not guarantee an optimal solution; # it is necessary to verify that its output is an integer greater than 0. # An approximate solution cannot be represented by '==' and can only ensure that the result is reasonable. result = tsp_greedy(graph) assert isinstance(result, int) assert result >= 64 + def test_dp_larger_graph(): graph = sample_graph_2() - assert tsp_dp(graph) == 80 + assert tsp_dp(graph) == 80 + def test_brute_force_larger_graph(): graph = sample_graph_2() assert tsp_brute_force(graph) == 80 + def test_greedy_larger_graph(): graph = sample_graph_2() result = tsp_greedy(graph) diff --git a/graphs/traveling_salesman_problem.py b/graphs/traveling_salesman_problem.py index 5985d9b1ee16..ce6db28569fe 100644 --- a/graphs/traveling_salesman_problem.py +++ b/graphs/traveling_salesman_problem.py @@ -1,5 +1,6 @@ from itertools import permutations + def tsp_brute_force(graph: list[list[int]]) -> int: """ Solves TSP using brute-force permutations. @@ -16,22 +17,23 @@ def tsp_brute_force(graph: list[list[int]]) -> int: """ n = len(graph) # Apart from other cities aside from City 0, City 0 serves as the starting point. - nodes = list(range(1, n)) - min_path = float('inf') - + nodes = list(range(1, n)) + min_path = float("inf") + # Enumerate all the permutations from city 1 to city n-1. for perm in permutations(nodes): - # Construct a complete path: + # Construct a complete path: # starting from point 0, visit in the order of arrangement, and then return to point 0. path = [0] + list(perm) + [0] - # Calculate the total distance of the path. + # Calculate the total distance of the path. # Update the shortest path. total_cost = sum(graph[path[i]][path[i + 1]] for i in range(n)) min_path = min(min_path, total_cost) return min_path + def tsp_dp(graph: list[list[int]]) -> int: """ Solves the Traveling Salesman Problem using Held-Karp dynamic programming. @@ -50,9 +52,9 @@ def tsp_dp(graph: list[list[int]]) -> int: # Create a dynamic programming table of size (2^n) x n. # Noting: 1 << n = 2^n # dp[mask][i] represents the shortest path starting from city 0, passing through the cities in the mask, and ultimately ending at city i. - dp = [[float('inf')] * n for _ in range(1 << n)] + dp = [[float("inf")] * n for _ in range(1 << n)] # Initial state: only city 0 is visited, and the path length is 0. - dp[1][0] = 0 + dp[1][0] = 0 for mask in range(1 << n): # The mask indicates which cities have been visited. @@ -70,10 +72,11 @@ def tsp_dp(graph: list[list[int]]) -> int: # State Transition: From city u to city v, updating the shortest path. next_mask = mask | (1 << v) dp[next_mask][v] = min(dp[next_mask][v], dp[mask][u] + graph[u][v]) - + # After completing visits to all cities, return to city 0 and obtain the minimum value. return min(dp[(1 << n) - 1][i] + graph[i][0] for i in range(1, n)) + def tsp_greedy(graph: list[list[int]]) -> int: """ Solves TSP approximately using the nearest neighbor heuristic. @@ -101,9 +104,13 @@ def tsp_greedy(graph: list[list[int]]) -> int: for _ in range(n - 1): # Find the nearest city to the current location that has not been visited. next_city = min( - ((city, cost) for city, cost in enumerate(graph[current]) if not visited[city] and city != current), + ( + (city, cost) + for city, cost in enumerate(graph[current]) + if not visited[city] and city != current + ), key=lambda x: x[1], - default=(None, float('inf')) + default=(None, float("inf")), )[0] # If no such city exists, break the loop. @@ -135,24 +142,25 @@ def test_tsp_example(): result = tsp_brute_force(graph) if result != 80: - raise Exception('tsp_brute_force Incorrect result') + raise Exception("tsp_brute_force Incorrect result") else: - print('Test passed') - + print("Test passed") + result = tsp_dp(graph) if result != 80: - raise Exception('tsp_dp Incorrect result') + raise Exception("tsp_dp Incorrect result") else: print("Test passed") - + result = tsp_greedy(graph) if result != 80: if result < 0: - raise Exception('tsp_greedy Incorrect result') + raise Exception("tsp_greedy Incorrect result") else: print("tsp_greedy gets an approximate result.") else: - print('Test passed') + print("Test passed") + -if __name__ == '__main__': - test_tsp_example() \ No newline at end of file +if __name__ == "__main__": + test_tsp_example() From 85f14011bf4d44395f98bc79b2e4e1ba4e645016 Mon Sep 17 00:00:00 2001 From: MapleBauhinia <3626172038@qq.com> Date: Sat, 5 Jul 2025 16:00:28 +0800 Subject: [PATCH 04/15] Fix: TSP rename lambda parameter and add type hints --- graphs/tests/test_traveling_salesman_problem.py | 12 ++++++------ graphs/traveling_salesman_problem.py | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/graphs/tests/test_traveling_salesman_problem.py b/graphs/tests/test_traveling_salesman_problem.py index 3b3b9441ef66..e30a379f0bb0 100644 --- a/graphs/tests/test_traveling_salesman_problem.py +++ b/graphs/tests/test_traveling_salesman_problem.py @@ -16,15 +16,15 @@ def sample_graph_2() -> list[list[int]]: [20, 25, 30, 0], ] -def test_brute_force(): +def test_brute_force() -> None: graph = sample_graph_1() assert tsp_brute_force(graph) == 64 -def test_dp(): +def test_dp() -> None: graph = sample_graph_1() assert tsp_dp(graph) == 64 -def test_greedy(): +def test_greedy() -> None: graph = sample_graph_1() # The greedy algorithm does not guarantee an optimal solution; # it is necessary to verify that its output is an integer greater than 0. @@ -33,15 +33,15 @@ def test_greedy(): assert isinstance(result, int) assert result >= 64 -def test_dp_larger_graph(): +def test_dp_larger_graph() -> None: graph = sample_graph_2() assert tsp_dp(graph) == 80 -def test_brute_force_larger_graph(): +def test_brute_force_larger_graph() -> None: graph = sample_graph_2() assert tsp_brute_force(graph) == 80 -def test_greedy_larger_graph(): +def test_greedy_larger_graph() -> None: graph = sample_graph_2() result = tsp_greedy(graph) assert isinstance(result, int) diff --git a/graphs/traveling_salesman_problem.py b/graphs/traveling_salesman_problem.py index 5985d9b1ee16..c889efb72df7 100644 --- a/graphs/traveling_salesman_problem.py +++ b/graphs/traveling_salesman_problem.py @@ -102,7 +102,7 @@ def tsp_greedy(graph: list[list[int]]) -> int: # Find the nearest city to the current location that has not been visited. next_city = min( ((city, cost) for city, cost in enumerate(graph[current]) if not visited[city] and city != current), - key=lambda x: x[1], + key=lambda cost: cost[1], default=(None, float('inf')) )[0] @@ -125,7 +125,7 @@ def tsp_greedy(graph: list[list[int]]) -> int: return total_cost -def test_tsp_example(): +def test_tsp_example() -> None: graph = [ [0, 10, 15, 20], [10, 0, 35, 25], From c7be8c03a30d7baef2df261c48509722d70d92bf Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 5 Jul 2025 08:23:29 +0000 Subject: [PATCH 05/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- graphs/tests/test_traveling_salesman_problem.py | 5 +++++ graphs/traveling_salesman_problem.py | 8 ++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/graphs/tests/test_traveling_salesman_problem.py b/graphs/tests/test_traveling_salesman_problem.py index 6cbc4108391c..5576baee8815 100644 --- a/graphs/tests/test_traveling_salesman_problem.py +++ b/graphs/tests/test_traveling_salesman_problem.py @@ -18,14 +18,17 @@ def sample_graph_2() -> list[list[int]]: [20, 25, 30, 0], ] + def test_brute_force() -> None: graph = sample_graph_1() assert tsp_brute_force(graph) == 64 + def test_dp() -> None: graph = sample_graph_1() assert tsp_dp(graph) == 64 + def test_greedy() -> None: graph = sample_graph_1() # The greedy algorithm does not guarantee an optimal solution; @@ -35,6 +38,7 @@ def test_greedy() -> None: assert isinstance(result, int) assert result >= 64 + def test_dp_larger_graph() -> None: graph = sample_graph_2() assert tsp_dp(graph) == 80 @@ -44,6 +48,7 @@ def test_brute_force_larger_graph() -> None: graph = sample_graph_2() assert tsp_brute_force(graph) == 80 + def test_greedy_larger_graph() -> None: graph = sample_graph_2() result = tsp_greedy(graph) diff --git a/graphs/traveling_salesman_problem.py b/graphs/traveling_salesman_problem.py index 81d707f47c92..cdbb12ec516b 100644 --- a/graphs/traveling_salesman_problem.py +++ b/graphs/traveling_salesman_problem.py @@ -104,9 +104,13 @@ def tsp_greedy(graph: list[list[int]]) -> int: for _ in range(n - 1): # Find the nearest city to the current location that has not been visited. next_city = min( - ((city, cost) for city, cost in enumerate(graph[current]) if not visited[city] and city != current), + ( + (city, cost) + for city, cost in enumerate(graph[current]) + if not visited[city] and city != current + ), key=lambda cost: cost[1], - default=(None, float('inf')) + default=(None, float("inf")), )[0] # If no such city exists, break the loop. From a766f381dc2be1c5463852b2e6bceca32ab3ff85 Mon Sep 17 00:00:00 2001 From: MapleBauhinia <3626172038@qq.com> Date: Sat, 5 Jul 2025 17:25:25 +0800 Subject: [PATCH 06/15] Fix: format and pass all tests --- .../tests/test_traveling_salesman_problem.py | 4 +-- graphs/traveling_salesman_problem.py | 25 ++++++++++++------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/graphs/tests/test_traveling_salesman_problem.py b/graphs/tests/test_traveling_salesman_problem.py index 6cbc4108391c..4fe61e2c7052 100644 --- a/graphs/tests/test_traveling_salesman_problem.py +++ b/graphs/tests/test_traveling_salesman_problem.py @@ -1,4 +1,3 @@ -import pytest from graphs.traveling_salesman_problem import tsp_brute_force, tsp_dp, tsp_greedy @@ -30,7 +29,8 @@ def test_greedy() -> None: graph = sample_graph_1() # The greedy algorithm does not guarantee an optimal solution; # it is necessary to verify that its output is an integer greater than 0. - # An approximate solution cannot be represented by '==' and can only ensure that the result is reasonable. + # An approximate solution cannot be represented by '==', + # and can only ensure that the result is reasonable. result = tsp_greedy(graph) assert isinstance(result, int) assert result >= 64 diff --git a/graphs/traveling_salesman_problem.py b/graphs/traveling_salesman_problem.py index 81d707f47c92..53e2c11ddb61 100644 --- a/graphs/traveling_salesman_problem.py +++ b/graphs/traveling_salesman_problem.py @@ -9,7 +9,8 @@ def tsp_brute_force(graph: list[list[int]]) -> int: graph: 2D list representing distances between cities. Returns: - The minimal total travel distance visiting all cities exactly once and returning to the start. + The minimal total travel distance visiting all cities exactly once, + and then returning to the start. Example: >>> tsp_brute_force([[0, 29, 20], [29, 0, 15], [20, 15, 0]]) @@ -23,8 +24,9 @@ def tsp_brute_force(graph: list[list[int]]) -> int: # Enumerate all the permutations from city 1 to city n-1. for perm in permutations(nodes): # Construct a complete path: - # starting from point 0, visit in the order of arrangement, and then return to point 0. - path = [0] + list(perm) + [0] + # Starting from point 0, visit in the order of arrangement, + # and then return to point 0. + path = [0, *perm, 0] # Calculate the total distance of the path. # Update the shortest path. @@ -51,7 +53,8 @@ def tsp_dp(graph: list[list[int]]) -> int: n = len(graph) # Create a dynamic programming table of size (2^n) x n. # Noting: 1 << n = 2^n - # dp[mask][i] represents the shortest path starting from city 0, passing through the cities in the mask, and ultimately ending at city i. + # dp[mask][i] represents the shortest path starting from city 0, + # passing through the cities in the mask, and ultimately ending at city i. dp = [[float("inf")] * n for _ in range(1 << n)] # Initial state: only city 0 is visited, and the path length is 0. dp[1][0] = 0 @@ -73,14 +76,16 @@ def tsp_dp(graph: list[list[int]]) -> int: next_mask = mask | (1 << v) dp[next_mask][v] = min(dp[next_mask][v], dp[mask][u] + graph[u][v]) - # After completing visits to all cities, return to city 0 and obtain the minimum value. + # After completing visits to all cities, + # return to city 0 and obtain the minimum value. return min(dp[(1 << n) - 1][i] + graph[i][0] for i in range(1, n)) def tsp_greedy(graph: list[list[int]]) -> int: """ Solves TSP approximately using the nearest neighbor heuristic. - Warming: This algorithm is not guaranteed to find the optimal solution! But it is fast and applicable to any input size. + Warming: This algorithm is not guaranteed to find the optimal solution! + But it is fast and applicable to any input size. Args: graph: 2D list representing distances between cities. @@ -91,7 +96,8 @@ def tsp_greedy(graph: list[list[int]]) -> int: Example: >>> tsp_greedy([[0, 29, 20], [29, 0, 15], [20, 15, 0]]) 64 - >>> tsp_greedy([[0, 10, 15, 20], [10, 0, 35, 25], [15, 35, 0, 30], [20, 25, 30, 0]]) + >>> tsp_greedy([[0, 10, 15, 20], [10, 0, 35, 25], + [15, 35, 0, 30], [20, 25, 30, 0]]) 80 """ n = len(graph) @@ -104,8 +110,9 @@ def tsp_greedy(graph: list[list[int]]) -> int: for _ in range(n - 1): # Find the nearest city to the current location that has not been visited. next_city = min( - ((city, cost) for city, cost in enumerate(graph[current]) if not visited[city] and city != current), - key=lambda cost: cost[1], + ((city, cost) for city, cost in enumerate(graph[current]) + if not visited[city] and city != current), + key=lambda cost: cost[1], default=(None, float('inf')) )[0] From 13df43ef4517a60a906cbc2dcfb8899f9333c7a2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 5 Jul 2025 10:16:57 +0000 Subject: [PATCH 07/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- graphs/traveling_salesman_problem.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/graphs/traveling_salesman_problem.py b/graphs/traveling_salesman_problem.py index 53e2c11ddb61..ade565873a9e 100644 --- a/graphs/traveling_salesman_problem.py +++ b/graphs/traveling_salesman_problem.py @@ -110,10 +110,13 @@ def tsp_greedy(graph: list[list[int]]) -> int: for _ in range(n - 1): # Find the nearest city to the current location that has not been visited. next_city = min( - ((city, cost) for city, cost in enumerate(graph[current]) - if not visited[city] and city != current), - key=lambda cost: cost[1], - default=(None, float('inf')) + ( + (city, cost) + for city, cost in enumerate(graph[current]) + if not visited[city] and city != current + ), + key=lambda cost: cost[1], + default=(None, float("inf")), )[0] # If no such city exists, break the loop. From 7bd83fd8d045cb777e569026aa23a86869626666 Mon Sep 17 00:00:00 2001 From: MapleBauhinia <3626172038@qq.com> Date: Sat, 5 Jul 2025 18:26:18 +0800 Subject: [PATCH 08/15] Standardize output to int --- graphs/traveling_salesman_problem.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/graphs/traveling_salesman_problem.py b/graphs/traveling_salesman_problem.py index 53e2c11ddb61..16195134c469 100644 --- a/graphs/traveling_salesman_problem.py +++ b/graphs/traveling_salesman_problem.py @@ -33,7 +33,7 @@ def tsp_brute_force(graph: list[list[int]]) -> int: total_cost = sum(graph[path[i]][path[i + 1]] for i in range(n)) min_path = min(min_path, total_cost) - return min_path + return int(min_path) def tsp_dp(graph: list[list[int]]) -> int: @@ -78,7 +78,7 @@ def tsp_dp(graph: list[list[int]]) -> int: # After completing visits to all cities, # return to city 0 and obtain the minimum value. - return min(dp[(1 << n) - 1][i] + graph[i][0] for i in range(1, n)) + return int(min(dp[(1 << n) - 1][i] + graph[i][0] for i in range(1, n))) def tsp_greedy(graph: list[list[int]]) -> int: @@ -132,7 +132,7 @@ def tsp_greedy(graph: list[list[int]]) -> int: total_cost += graph[current][0] path.append(0) - return total_cost + return int(total_cost) def test_tsp_example() -> None: From 80cc148675ee19d9602ce17ac37b84b7dee85a03 Mon Sep 17 00:00:00 2001 From: MapleBauhinia <3626172038@qq.com> Date: Sat, 5 Jul 2025 18:39:09 +0800 Subject: [PATCH 09/15] Fix: Build PR --- graphs/traveling_salesman_problem.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/graphs/traveling_salesman_problem.py b/graphs/traveling_salesman_problem.py index a317c874e6bd..255da98e106d 100644 --- a/graphs/traveling_salesman_problem.py +++ b/graphs/traveling_salesman_problem.py @@ -96,8 +96,12 @@ def tsp_greedy(graph: list[list[int]]) -> int: Example: >>> tsp_greedy([[0, 29, 20], [29, 0, 15], [20, 15, 0]]) 64 - >>> tsp_greedy([[0, 10, 15, 20], [10, 0, 35, 25], - [15, 35, 0, 30], [20, 25, 30, 0]]) + >>> tsp_greedy([ + [0, 10, 15, 20], + [10, 0, 35, 25], + [15, 35, 0, 30], + [20, 25, 30, 0] + ]) 80 """ n = len(graph) From cef217a1ca5d6ffeeed71d27f5af86aa7ed0f39b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 5 Jul 2025 10:48:12 +0000 Subject: [PATCH 10/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- graphs/traveling_salesman_problem.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graphs/traveling_salesman_problem.py b/graphs/traveling_salesman_problem.py index 255da98e106d..60900af28388 100644 --- a/graphs/traveling_salesman_problem.py +++ b/graphs/traveling_salesman_problem.py @@ -97,9 +97,9 @@ def tsp_greedy(graph: list[list[int]]) -> int: >>> tsp_greedy([[0, 29, 20], [29, 0, 15], [20, 15, 0]]) 64 >>> tsp_greedy([ - [0, 10, 15, 20], + [0, 10, 15, 20], [10, 0, 35, 25], - [15, 35, 0, 30], + [15, 35, 0, 30], [20, 25, 30, 0] ]) 80 From f61f7cfa4597a4cce603e13b205eb75dcd185f35 Mon Sep 17 00:00:00 2001 From: MapleBauhinia <3626172038@qq.com> Date: Sat, 5 Jul 2025 19:23:12 +0800 Subject: [PATCH 11/15] Fix: format --- ciphers/base64_cipher.py | 12 +++--- .../hashing/number_theory/prime_numbers.py | 6 +-- data_structures/heap/min_heap.py | 6 +-- data_structures/kd_tree/tests/test_kdtree.py | 12 +++--- .../suffix_tree/tests/test_suffix_tree.py | 24 +++++------ .../filters/gabor_filter.py | 6 +-- dynamic_programming/climbing_stairs.py | 6 +-- .../iterating_through_submasks.py | 6 +-- financial/time_and_half_pay.py | 18 ++++---- graphs/traveling_salesman_problem.py | 4 +- greedy_methods/fractional_knapsack.py | 8 ++-- machine_learning/frequent_pattern_growth.py | 2 +- .../integration_by_simpson_approx.py | 12 +++--- maths/prime_check.py | 12 +++--- maths/primelib.py | 42 +++++++++---------- matrix/matrix_class.py | 8 ++-- neural_network/input_data.py | 6 +-- quantum/quantum_teleportation.py.DISABLED.txt | 3 +- scripts/validate_solutions.py | 6 +-- sorts/bead_sort.py | 2 +- strings/min_cost_string_conversion.py | 2 +- 21 files changed, 104 insertions(+), 99 deletions(-) diff --git a/ciphers/base64_cipher.py b/ciphers/base64_cipher.py index 038d13963d95..2b950b1be37d 100644 --- a/ciphers/base64_cipher.py +++ b/ciphers/base64_cipher.py @@ -105,13 +105,13 @@ def base64_decode(encoded_data: str) -> bytes: # Check if the encoded string contains non base64 characters if padding: - assert all(char in B64_CHARSET for char in encoded_data[:-padding]), ( - "Invalid base64 character(s) found." - ) + assert all( + char in B64_CHARSET for char in encoded_data[:-padding] + ), "Invalid base64 character(s) found." else: - assert all(char in B64_CHARSET for char in encoded_data), ( - "Invalid base64 character(s) found." - ) + assert all( + char in B64_CHARSET for char in encoded_data + ), "Invalid base64 character(s) found." # Check the padding assert len(encoded_data) % 4 == 0 and padding < 3, "Incorrect padding" diff --git a/data_structures/hashing/number_theory/prime_numbers.py b/data_structures/hashing/number_theory/prime_numbers.py index 82071b5e9f09..2549a1477b2b 100644 --- a/data_structures/hashing/number_theory/prime_numbers.py +++ b/data_structures/hashing/number_theory/prime_numbers.py @@ -32,9 +32,9 @@ def is_prime(number: int) -> bool: """ # precondition - assert isinstance(number, int) and (number >= 0), ( - "'number' must been an int and positive" - ) + assert isinstance(number, int) and ( + number >= 0 + ), "'number' must been an int and positive" if 1 < number < 4: # 2 and 3 are primes diff --git a/data_structures/heap/min_heap.py b/data_structures/heap/min_heap.py index 577b98d788a1..ce7ed570a58d 100644 --- a/data_structures/heap/min_heap.py +++ b/data_structures/heap/min_heap.py @@ -124,9 +124,9 @@ def is_empty(self): return len(self.heap) == 0 def decrease_key(self, node, new_value): - assert self.heap[self.idx_of_element[node]].val > new_value, ( - "newValue must be less that current value" - ) + assert ( + self.heap[self.idx_of_element[node]].val > new_value + ), "newValue must be less that current value" node.val = new_value self.heap_dict[node.name] = new_value self.sift_up(self.idx_of_element[node]) diff --git a/data_structures/kd_tree/tests/test_kdtree.py b/data_structures/kd_tree/tests/test_kdtree.py index d6a4a66dd24d..dce5e4f34ff4 100644 --- a/data_structures/kd_tree/tests/test_kdtree.py +++ b/data_structures/kd_tree/tests/test_kdtree.py @@ -48,14 +48,14 @@ def test_build_kdtree(num_points, cube_size, num_dimensions, depth, expected_res assert kdtree is not None, "Expected a KDNode, got None" # Check if root has correct dimensions - assert len(kdtree.point) == num_dimensions, ( - f"Expected point dimension {num_dimensions}, got {len(kdtree.point)}" - ) + assert ( + len(kdtree.point) == num_dimensions + ), f"Expected point dimension {num_dimensions}, got {len(kdtree.point)}" # Check that the tree is balanced to some extent (simplistic check) - assert isinstance(kdtree, KDNode), ( - f"Expected KDNode instance, got {type(kdtree)}" - ) + assert isinstance( + kdtree, KDNode + ), f"Expected KDNode instance, got {type(kdtree)}" def test_nearest_neighbour_search(): diff --git a/data_structures/suffix_tree/tests/test_suffix_tree.py b/data_structures/suffix_tree/tests/test_suffix_tree.py index c9dbe199d19d..45c6790ac48a 100644 --- a/data_structures/suffix_tree/tests/test_suffix_tree.py +++ b/data_structures/suffix_tree/tests/test_suffix_tree.py @@ -22,18 +22,18 @@ def test_search_existing_patterns(self) -> None: patterns = ["ana", "ban", "na"] for pattern in patterns: with self.subTest(pattern=pattern): - assert self.suffix_tree.search(pattern), ( - f"Pattern '{pattern}' should be found." - ) + assert self.suffix_tree.search( + pattern + ), f"Pattern '{pattern}' should be found." def test_search_non_existing_patterns(self) -> None: """Test searching for patterns that do not exist in the suffix tree.""" patterns = ["xyz", "apple", "cat"] for pattern in patterns: with self.subTest(pattern=pattern): - assert not self.suffix_tree.search(pattern), ( - f"Pattern '{pattern}' should not be found." - ) + assert not self.suffix_tree.search( + pattern + ), f"Pattern '{pattern}' should not be found." def test_search_empty_pattern(self) -> None: """Test searching for an empty pattern.""" @@ -41,18 +41,18 @@ def test_search_empty_pattern(self) -> None: def test_search_full_text(self) -> None: """Test searching for the full text.""" - assert self.suffix_tree.search(self.text), ( - "The full text should be found in the suffix tree." - ) + assert self.suffix_tree.search( + self.text + ), "The full text should be found in the suffix tree." def test_search_substrings(self) -> None: """Test searching for substrings of the full text.""" substrings = ["ban", "ana", "a", "na"] for substring in substrings: with self.subTest(substring=substring): - assert self.suffix_tree.search(substring), ( - f"Substring '{substring}' should be found." - ) + assert self.suffix_tree.search( + substring + ), f"Substring '{substring}' should be found." if __name__ == "__main__": diff --git a/digital_image_processing/filters/gabor_filter.py b/digital_image_processing/filters/gabor_filter.py index aaec567f4c99..8f9212a35a79 100644 --- a/digital_image_processing/filters/gabor_filter.py +++ b/digital_image_processing/filters/gabor_filter.py @@ -48,9 +48,9 @@ def gabor_filter_kernel( _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 - ) + gabor[y, x] = np.exp( + -(_x**2 + gamma**2 * _y**2) / (2 * sigma**2) + ) * np.cos(2 * np.pi * _x / lambd + psi) return gabor diff --git a/dynamic_programming/climbing_stairs.py b/dynamic_programming/climbing_stairs.py index 38bdb427eedc..d6273d025f08 100644 --- a/dynamic_programming/climbing_stairs.py +++ b/dynamic_programming/climbing_stairs.py @@ -25,9 +25,9 @@ def climb_stairs(number_of_steps: int) -> int: ... AssertionError: number_of_steps needs to be positive integer, your input -7 """ - assert isinstance(number_of_steps, int) and number_of_steps > 0, ( - f"number_of_steps needs to be positive integer, your input {number_of_steps}" - ) + assert ( + 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 previous, current = 1, 1 diff --git a/dynamic_programming/iterating_through_submasks.py b/dynamic_programming/iterating_through_submasks.py index efab6dacff3f..372dd2c74a71 100644 --- a/dynamic_programming/iterating_through_submasks.py +++ b/dynamic_programming/iterating_through_submasks.py @@ -37,9 +37,9 @@ def list_of_submasks(mask: int) -> list[int]: """ - assert isinstance(mask, int) and mask > 0, ( - f"mask needs to be positive integer, your input {mask}" - ) + assert ( + isinstance(mask, int) and mask > 0 + ), f"mask needs to be positive integer, your input {mask}" """ first submask iterated will be mask itself then operation will be performed diff --git a/financial/time_and_half_pay.py b/financial/time_and_half_pay.py index c5dff1bc1ce1..3e35c373a4e1 100644 --- a/financial/time_and_half_pay.py +++ b/financial/time_and_half_pay.py @@ -17,15 +17,15 @@ def pay(hours_worked: float, pay_rate: float, hours: float = 40) -> float: 10.0 """ # Check that all input parameters are float or integer - assert isinstance(hours_worked, (float, int)), ( - "Parameter 'hours_worked' must be of type 'int' or 'float'" - ) - assert isinstance(pay_rate, (float, int)), ( - "Parameter 'pay_rate' must be of type 'int' or 'float'" - ) - assert isinstance(hours, (float, int)), ( - "Parameter 'hours' must be of type 'int' or 'float'" - ) + assert isinstance( + hours_worked, (float, int) + ), "Parameter 'hours_worked' must be of type 'int' or 'float'" + assert isinstance( + pay_rate, (float, int) + ), "Parameter 'pay_rate' must be of type 'int' or 'float'" + assert isinstance( + hours, (float, int) + ), "Parameter 'hours' must be of type 'int' or 'float'" normal_pay = hours_worked * pay_rate over_time = max(0, hours_worked - hours) diff --git a/graphs/traveling_salesman_problem.py b/graphs/traveling_salesman_problem.py index 255da98e106d..60900af28388 100644 --- a/graphs/traveling_salesman_problem.py +++ b/graphs/traveling_salesman_problem.py @@ -97,9 +97,9 @@ def tsp_greedy(graph: list[list[int]]) -> int: >>> tsp_greedy([[0, 29, 20], [29, 0, 15], [20, 15, 0]]) 64 >>> tsp_greedy([ - [0, 10, 15, 20], + [0, 10, 15, 20], [10, 0, 35, 25], - [15, 35, 0, 30], + [15, 35, 0, 30], [20, 25, 30, 0] ]) 80 diff --git a/greedy_methods/fractional_knapsack.py b/greedy_methods/fractional_knapsack.py index d52b56f23569..f7455a9c9fce 100644 --- a/greedy_methods/fractional_knapsack.py +++ b/greedy_methods/fractional_knapsack.py @@ -39,9 +39,11 @@ def frac_knapsack(vl, wt, w, n): return ( 0 if k == 0 - else sum(vl[:k]) + (w - acc[k - 1]) * (vl[k]) / (wt[k]) - if k != n - else sum(vl[:k]) + else ( + sum(vl[:k]) + (w - acc[k - 1]) * (vl[k]) / (wt[k]) + if k != n + else sum(vl[:k]) + ) ) diff --git a/machine_learning/frequent_pattern_growth.py b/machine_learning/frequent_pattern_growth.py index fae2df16efb1..c2a5e640c0bb 100644 --- a/machine_learning/frequent_pattern_growth.py +++ b/machine_learning/frequent_pattern_growth.py @@ -240,7 +240,7 @@ def ascend_tree(leaf_node: TreeNode, prefix_path: list[str]) -> None: ascend_tree(leaf_node.parent, prefix_path) -def find_prefix_path(base_pat: frozenset, tree_node: TreeNode | None) -> dict: # noqa: ARG001 +def find_prefix_path(base_pat: frozenset, tree_node: TreeNode | None) -> dict: """ Find the conditional pattern base for a given base pattern. diff --git a/maths/numerical_analysis/integration_by_simpson_approx.py b/maths/numerical_analysis/integration_by_simpson_approx.py index 043f3a9a72af..934299997aac 100644 --- a/maths/numerical_analysis/integration_by_simpson_approx.py +++ b/maths/numerical_analysis/integration_by_simpson_approx.py @@ -88,18 +88,18 @@ def simpson_integration(function, a: float, b: float, precision: int = 4) -> flo AssertionError: precision should be positive integer your input : -1 """ - assert callable(function), ( - f"the function(object) passed should be callable your input : {function}" - ) + assert callable( + function + ), f"the function(object) passed should be callable your input : {function}" 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, 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}" - ) + assert ( + isinstance(precision, int) and precision > 0 + ), f"precision should be positive integer your input : {precision}" # just applying the formula of simpson for approximate integration written in # mentioned article in first comment of this file and above this function diff --git a/maths/prime_check.py b/maths/prime_check.py index a757c4108f24..f1bc4def2469 100644 --- a/maths/prime_check.py +++ b/maths/prime_check.py @@ -73,12 +73,12 @@ def test_primes(self): def test_not_primes(self): with pytest.raises(ValueError): is_prime(-19) - assert not is_prime(0), ( - "Zero doesn't have any positive factors, primes must have exactly two." - ) - assert not is_prime(1), ( - "One only has 1 positive factor, primes must have exactly two." - ) + assert not is_prime( + 0 + ), "Zero doesn't have any positive factors, primes must have exactly two." + assert not is_prime( + 1 + ), "One only has 1 positive factor, primes must have exactly two." assert not is_prime(2 * 2) assert not is_prime(2 * 3) assert not is_prime(3 * 3) diff --git a/maths/primelib.py b/maths/primelib.py index 9f031efc50a9..c41aa07e09c4 100644 --- a/maths/primelib.py +++ b/maths/primelib.py @@ -66,9 +66,9 @@ def is_prime(number: int) -> bool: """ # precondition - assert isinstance(number, int) and (number >= 0), ( - "'number' must been an int and positive" - ) + assert isinstance(number, int) and ( + number >= 0 + ), "'number' must been an int and positive" status = True @@ -254,9 +254,9 @@ def greatest_prime_factor(number): """ # precondition - assert isinstance(number, int) and (number >= 0), ( - "'number' must been an int and >= 0" - ) + assert isinstance(number, int) and ( + number >= 0 + ), "'number' must been an int and >= 0" ans = 0 @@ -296,9 +296,9 @@ def smallest_prime_factor(number): """ # precondition - assert isinstance(number, int) and (number >= 0), ( - "'number' must been an int and >= 0" - ) + assert isinstance(number, int) and ( + number >= 0 + ), "'number' must been an int and >= 0" ans = 0 @@ -399,9 +399,9 @@ def goldbach(number): """ # precondition - assert isinstance(number, int) and (number > 2) and is_even(number), ( - "'number' must been an int, even and > 2" - ) + assert ( + isinstance(number, int) and (number > 2) and is_even(number) + ), "'number' must been an int, even and > 2" ans = [] # this list will returned @@ -525,9 +525,9 @@ def kg_v(number1, number2): done.append(n) # precondition - assert isinstance(ans, int) and (ans >= 0), ( - "'ans' must been from type int and positive" - ) + assert isinstance(ans, int) and ( + ans >= 0 + ), "'ans' must been from type int and positive" return ans @@ -574,9 +574,9 @@ def get_prime(n): ans += 1 # precondition - assert isinstance(ans, int) and is_prime(ans), ( - "'ans' must been a prime number and from type int" - ) + assert isinstance(ans, int) and is_prime( + ans + ), "'ans' must been a prime number and from type int" return ans @@ -705,9 +705,9 @@ def is_perfect_number(number): """ # precondition - assert isinstance(number, int) and (number > 1), ( - "'number' must been an int and >= 1" - ) + assert isinstance(number, int) and ( + number > 1 + ), "'number' must been an int and >= 1" divisors = get_divisors(number) diff --git a/matrix/matrix_class.py b/matrix/matrix_class.py index a5940a38e836..230eb95006fa 100644 --- a/matrix/matrix_class.py +++ b/matrix/matrix_class.py @@ -204,9 +204,11 @@ def cofactors(self) -> Matrix: return Matrix( [ [ - self.minors().rows[row][column] - if (row + column) % 2 == 0 - else self.minors().rows[row][column] * -1 + ( + 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) diff --git a/neural_network/input_data.py b/neural_network/input_data.py index 3a8628f939f8..72debabb566a 100644 --- a/neural_network/input_data.py +++ b/neural_network/input_data.py @@ -160,9 +160,9 @@ def __init__( self._num_examples = 10000 self.one_hot = one_hot else: - assert images.shape[0] == labels.shape[0], ( - f"images.shape: {images.shape} labels.shape: {labels.shape}" - ) + assert ( + images.shape[0] == labels.shape[0] + ), f"images.shape: {images.shape} labels.shape: {labels.shape}" self._num_examples = images.shape[0] # Convert shape from [num examples, rows, columns, depth] diff --git a/quantum/quantum_teleportation.py.DISABLED.txt b/quantum/quantum_teleportation.py.DISABLED.txt index 5da79ed20183..f57be19685ad 100644 --- a/quantum/quantum_teleportation.py.DISABLED.txt +++ b/quantum/quantum_teleportation.py.DISABLED.txt @@ -12,7 +12,8 @@ https://qiskit.org/textbook/ch-algorithms/teleportation.html import numpy as np import qiskit -from qiskit import Aer, ClassicalRegister, QuantumCircuit, QuantumRegister, execute +from qiskit import (Aer, ClassicalRegister, QuantumCircuit, QuantumRegister, + execute) def quantum_teleportation( diff --git a/scripts/validate_solutions.py b/scripts/validate_solutions.py index f426153b5683..79a2f790081f 100755 --- a/scripts/validate_solutions.py +++ b/scripts/validate_solutions.py @@ -103,6 +103,6 @@ def test_project_euler(solution_path: pathlib.Path) -> None: solution_module = convert_path_to_module(solution_path) answer = str(solution_module.solution()) answer = hashlib.sha256(answer.encode()).hexdigest() - assert answer == expected, ( - f"Expected solution to {problem_number} to have hash {expected}, got {answer}" - ) + assert ( + answer == expected + ), f"Expected solution to {problem_number} to have hash {expected}, got {answer}" diff --git a/sorts/bead_sort.py b/sorts/bead_sort.py index 8ce0619fd573..e51173643d81 100644 --- a/sorts/bead_sort.py +++ b/sorts/bead_sort.py @@ -31,7 +31,7 @@ def bead_sort(sequence: list) -> list: if any(not isinstance(x, int) or x < 0 for x in sequence): 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:])): # noqa: RUF007 + for i, (rod_upper, rod_lower) in enumerate(zip(sequence, sequence[1:])): if rod_upper > rod_lower: sequence[i] -= rod_upper - rod_lower sequence[i + 1] += rod_upper - rod_lower diff --git a/strings/min_cost_string_conversion.py b/strings/min_cost_string_conversion.py index 87eb5189e16a..363f46755e08 100644 --- a/strings/min_cost_string_conversion.py +++ b/strings/min_cost_string_conversion.py @@ -140,7 +140,7 @@ def assemble_transformation(ops: list[list[str]], i: int, j: int) -> list[str]: elif op[0] == "R": string[i] = op[2] - file.write("%-16s" % ("Replace %c" % op[1] + " with " + str(op[2]))) # noqa: UP031 + file.write("%-16s" % ("Replace %c" % op[1] + " with " + str(op[2]))) file.write("\t\t" + "".join(string)) file.write("\r\n") From 9cc0448e110cfc2f66f879a3bc44510a3baa46b0 Mon Sep 17 00:00:00 2001 From: MapleBauhinia <3626172038@qq.com> Date: Sat, 5 Jul 2025 20:49:48 +0800 Subject: [PATCH 12/15] Fix: tsp-greedy --- graphs/traveling_salesman_problem.py | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/graphs/traveling_salesman_problem.py b/graphs/traveling_salesman_problem.py index 60900af28388..33ec3e59aec4 100644 --- a/graphs/traveling_salesman_problem.py +++ b/graphs/traveling_salesman_problem.py @@ -96,13 +96,6 @@ def tsp_greedy(graph: list[list[int]]) -> int: Example: >>> tsp_greedy([[0, 29, 20], [29, 0, 15], [20, 15, 0]]) 64 - >>> tsp_greedy([ - [0, 10, 15, 20], - [10, 0, 35, 25], - [15, 35, 0, 30], - [20, 25, 30, 0] - ]) - 80 """ n = len(graph) visited = [False] * n # Mark whether each city has been visited. @@ -143,27 +136,22 @@ def tsp_greedy(graph: list[list[int]]) -> int: def test_tsp_example() -> None: - graph = [ - [0, 10, 15, 20], - [10, 0, 35, 25], - [15, 35, 0, 30], - [20, 25, 30, 0], - ] + graph = [[0, 29, 20], [29, 0, 15], [20, 15, 0]] result = tsp_brute_force(graph) - if result != 80: + if result != 64: raise Exception("tsp_brute_force Incorrect result") else: print("Test passed") result = tsp_dp(graph) - if result != 80: + if result != 64: raise Exception("tsp_dp Incorrect result") else: print("Test passed") result = tsp_greedy(graph) - if result != 80: + if result != 64: if result < 0: raise Exception("tsp_greedy Incorrect result") else: From 9c9a3e43be8b0cc519f36e218367506980e9f1eb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 5 Jul 2025 12:52:24 +0000 Subject: [PATCH 13/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- ciphers/base64_cipher.py | 12 +++--- .../hashing/number_theory/prime_numbers.py | 6 +-- data_structures/heap/min_heap.py | 6 +-- data_structures/kd_tree/tests/test_kdtree.py | 12 +++--- .../suffix_tree/tests/test_suffix_tree.py | 24 +++++------ .../filters/gabor_filter.py | 6 +-- dynamic_programming/climbing_stairs.py | 6 +-- .../iterating_through_submasks.py | 6 +-- financial/time_and_half_pay.py | 18 ++++---- .../integration_by_simpson_approx.py | 12 +++--- maths/prime_check.py | 12 +++--- maths/primelib.py | 42 +++++++++---------- neural_network/input_data.py | 6 +-- scripts/validate_solutions.py | 6 +-- 14 files changed, 87 insertions(+), 87 deletions(-) diff --git a/ciphers/base64_cipher.py b/ciphers/base64_cipher.py index 2b950b1be37d..038d13963d95 100644 --- a/ciphers/base64_cipher.py +++ b/ciphers/base64_cipher.py @@ -105,13 +105,13 @@ def base64_decode(encoded_data: str) -> bytes: # Check if the encoded string contains non base64 characters if padding: - assert all( - char in B64_CHARSET for char in encoded_data[:-padding] - ), "Invalid base64 character(s) found." + assert all(char in B64_CHARSET for char in encoded_data[:-padding]), ( + "Invalid base64 character(s) found." + ) else: - assert all( - char in B64_CHARSET for char in encoded_data - ), "Invalid base64 character(s) found." + assert all(char in B64_CHARSET for char in encoded_data), ( + "Invalid base64 character(s) found." + ) # Check the padding assert len(encoded_data) % 4 == 0 and padding < 3, "Incorrect padding" diff --git a/data_structures/hashing/number_theory/prime_numbers.py b/data_structures/hashing/number_theory/prime_numbers.py index 2549a1477b2b..82071b5e9f09 100644 --- a/data_structures/hashing/number_theory/prime_numbers.py +++ b/data_structures/hashing/number_theory/prime_numbers.py @@ -32,9 +32,9 @@ def is_prime(number: int) -> bool: """ # precondition - assert isinstance(number, int) and ( - number >= 0 - ), "'number' must been an int and positive" + assert isinstance(number, int) and (number >= 0), ( + "'number' must been an int and positive" + ) if 1 < number < 4: # 2 and 3 are primes diff --git a/data_structures/heap/min_heap.py b/data_structures/heap/min_heap.py index ce7ed570a58d..577b98d788a1 100644 --- a/data_structures/heap/min_heap.py +++ b/data_structures/heap/min_heap.py @@ -124,9 +124,9 @@ def is_empty(self): return len(self.heap) == 0 def decrease_key(self, node, new_value): - assert ( - self.heap[self.idx_of_element[node]].val > new_value - ), "newValue must be less that current value" + assert self.heap[self.idx_of_element[node]].val > new_value, ( + "newValue must be less that current value" + ) node.val = new_value self.heap_dict[node.name] = new_value self.sift_up(self.idx_of_element[node]) diff --git a/data_structures/kd_tree/tests/test_kdtree.py b/data_structures/kd_tree/tests/test_kdtree.py index dce5e4f34ff4..d6a4a66dd24d 100644 --- a/data_structures/kd_tree/tests/test_kdtree.py +++ b/data_structures/kd_tree/tests/test_kdtree.py @@ -48,14 +48,14 @@ def test_build_kdtree(num_points, cube_size, num_dimensions, depth, expected_res assert kdtree is not None, "Expected a KDNode, got None" # Check if root has correct dimensions - assert ( - len(kdtree.point) == num_dimensions - ), f"Expected point dimension {num_dimensions}, got {len(kdtree.point)}" + assert len(kdtree.point) == num_dimensions, ( + f"Expected point dimension {num_dimensions}, got {len(kdtree.point)}" + ) # Check that the tree is balanced to some extent (simplistic check) - assert isinstance( - kdtree, KDNode - ), f"Expected KDNode instance, got {type(kdtree)}" + assert isinstance(kdtree, KDNode), ( + f"Expected KDNode instance, got {type(kdtree)}" + ) def test_nearest_neighbour_search(): diff --git a/data_structures/suffix_tree/tests/test_suffix_tree.py b/data_structures/suffix_tree/tests/test_suffix_tree.py index 45c6790ac48a..c9dbe199d19d 100644 --- a/data_structures/suffix_tree/tests/test_suffix_tree.py +++ b/data_structures/suffix_tree/tests/test_suffix_tree.py @@ -22,18 +22,18 @@ def test_search_existing_patterns(self) -> None: patterns = ["ana", "ban", "na"] for pattern in patterns: with self.subTest(pattern=pattern): - assert self.suffix_tree.search( - pattern - ), f"Pattern '{pattern}' should be found." + assert self.suffix_tree.search(pattern), ( + f"Pattern '{pattern}' should be found." + ) def test_search_non_existing_patterns(self) -> None: """Test searching for patterns that do not exist in the suffix tree.""" patterns = ["xyz", "apple", "cat"] for pattern in patterns: with self.subTest(pattern=pattern): - assert not self.suffix_tree.search( - pattern - ), f"Pattern '{pattern}' should not be found." + assert not self.suffix_tree.search(pattern), ( + f"Pattern '{pattern}' should not be found." + ) def test_search_empty_pattern(self) -> None: """Test searching for an empty pattern.""" @@ -41,18 +41,18 @@ def test_search_empty_pattern(self) -> None: def test_search_full_text(self) -> None: """Test searching for the full text.""" - assert self.suffix_tree.search( - self.text - ), "The full text should be found in the suffix tree." + assert self.suffix_tree.search(self.text), ( + "The full text should be found in the suffix tree." + ) def test_search_substrings(self) -> None: """Test searching for substrings of the full text.""" substrings = ["ban", "ana", "a", "na"] for substring in substrings: with self.subTest(substring=substring): - assert self.suffix_tree.search( - substring - ), f"Substring '{substring}' should be found." + assert self.suffix_tree.search(substring), ( + f"Substring '{substring}' should be found." + ) if __name__ == "__main__": diff --git a/digital_image_processing/filters/gabor_filter.py b/digital_image_processing/filters/gabor_filter.py index 8f9212a35a79..aaec567f4c99 100644 --- a/digital_image_processing/filters/gabor_filter.py +++ b/digital_image_processing/filters/gabor_filter.py @@ -48,9 +48,9 @@ def gabor_filter_kernel( _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) + gabor[y, x] = np.exp(-(_x**2 + gamma**2 * _y**2) / (2 * sigma**2)) * np.cos( + 2 * np.pi * _x / lambd + psi + ) return gabor diff --git a/dynamic_programming/climbing_stairs.py b/dynamic_programming/climbing_stairs.py index d6273d025f08..38bdb427eedc 100644 --- a/dynamic_programming/climbing_stairs.py +++ b/dynamic_programming/climbing_stairs.py @@ -25,9 +25,9 @@ def climb_stairs(number_of_steps: int) -> int: ... AssertionError: number_of_steps needs to be positive integer, your input -7 """ - assert ( - isinstance(number_of_steps, int) and number_of_steps > 0 - ), f"number_of_steps needs to be positive integer, your input {number_of_steps}" + assert 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 previous, current = 1, 1 diff --git a/dynamic_programming/iterating_through_submasks.py b/dynamic_programming/iterating_through_submasks.py index 372dd2c74a71..efab6dacff3f 100644 --- a/dynamic_programming/iterating_through_submasks.py +++ b/dynamic_programming/iterating_through_submasks.py @@ -37,9 +37,9 @@ def list_of_submasks(mask: int) -> list[int]: """ - assert ( - isinstance(mask, int) and mask > 0 - ), f"mask needs to be positive integer, your input {mask}" + assert isinstance(mask, int) and mask > 0, ( + f"mask needs to be positive integer, your input {mask}" + ) """ first submask iterated will be mask itself then operation will be performed diff --git a/financial/time_and_half_pay.py b/financial/time_and_half_pay.py index 3e35c373a4e1..c5dff1bc1ce1 100644 --- a/financial/time_and_half_pay.py +++ b/financial/time_and_half_pay.py @@ -17,15 +17,15 @@ def pay(hours_worked: float, pay_rate: float, hours: float = 40) -> float: 10.0 """ # Check that all input parameters are float or integer - assert isinstance( - hours_worked, (float, int) - ), "Parameter 'hours_worked' must be of type 'int' or 'float'" - assert isinstance( - pay_rate, (float, int) - ), "Parameter 'pay_rate' must be of type 'int' or 'float'" - assert isinstance( - hours, (float, int) - ), "Parameter 'hours' must be of type 'int' or 'float'" + assert isinstance(hours_worked, (float, int)), ( + "Parameter 'hours_worked' must be of type 'int' or 'float'" + ) + assert isinstance(pay_rate, (float, int)), ( + "Parameter 'pay_rate' must be of type 'int' or 'float'" + ) + assert isinstance(hours, (float, int)), ( + "Parameter 'hours' must be of type 'int' or 'float'" + ) normal_pay = hours_worked * pay_rate over_time = max(0, hours_worked - hours) diff --git a/maths/numerical_analysis/integration_by_simpson_approx.py b/maths/numerical_analysis/integration_by_simpson_approx.py index 934299997aac..043f3a9a72af 100644 --- a/maths/numerical_analysis/integration_by_simpson_approx.py +++ b/maths/numerical_analysis/integration_by_simpson_approx.py @@ -88,18 +88,18 @@ def simpson_integration(function, a: float, b: float, precision: int = 4) -> flo AssertionError: precision should be positive integer your input : -1 """ - assert callable( - function - ), f"the function(object) passed should be callable your input : {function}" + assert callable(function), ( + f"the function(object) passed should be callable your input : {function}" + ) 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, 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}" + assert isinstance(precision, int) and precision > 0, ( + f"precision should be positive integer your input : {precision}" + ) # just applying the formula of simpson for approximate integration written in # mentioned article in first comment of this file and above this function diff --git a/maths/prime_check.py b/maths/prime_check.py index f1bc4def2469..a757c4108f24 100644 --- a/maths/prime_check.py +++ b/maths/prime_check.py @@ -73,12 +73,12 @@ def test_primes(self): def test_not_primes(self): with pytest.raises(ValueError): is_prime(-19) - assert not is_prime( - 0 - ), "Zero doesn't have any positive factors, primes must have exactly two." - assert not is_prime( - 1 - ), "One only has 1 positive factor, primes must have exactly two." + assert not is_prime(0), ( + "Zero doesn't have any positive factors, primes must have exactly two." + ) + assert not is_prime(1), ( + "One only has 1 positive factor, primes must have exactly two." + ) assert not is_prime(2 * 2) assert not is_prime(2 * 3) assert not is_prime(3 * 3) diff --git a/maths/primelib.py b/maths/primelib.py index c41aa07e09c4..9f031efc50a9 100644 --- a/maths/primelib.py +++ b/maths/primelib.py @@ -66,9 +66,9 @@ def is_prime(number: int) -> bool: """ # precondition - assert isinstance(number, int) and ( - number >= 0 - ), "'number' must been an int and positive" + assert isinstance(number, int) and (number >= 0), ( + "'number' must been an int and positive" + ) status = True @@ -254,9 +254,9 @@ def greatest_prime_factor(number): """ # precondition - assert isinstance(number, int) and ( - number >= 0 - ), "'number' must been an int and >= 0" + assert isinstance(number, int) and (number >= 0), ( + "'number' must been an int and >= 0" + ) ans = 0 @@ -296,9 +296,9 @@ def smallest_prime_factor(number): """ # precondition - assert isinstance(number, int) and ( - number >= 0 - ), "'number' must been an int and >= 0" + assert isinstance(number, int) and (number >= 0), ( + "'number' must been an int and >= 0" + ) ans = 0 @@ -399,9 +399,9 @@ def goldbach(number): """ # precondition - assert ( - isinstance(number, int) and (number > 2) and is_even(number) - ), "'number' must been an int, even and > 2" + assert isinstance(number, int) and (number > 2) and is_even(number), ( + "'number' must been an int, even and > 2" + ) ans = [] # this list will returned @@ -525,9 +525,9 @@ def kg_v(number1, number2): done.append(n) # precondition - assert isinstance(ans, int) and ( - ans >= 0 - ), "'ans' must been from type int and positive" + assert isinstance(ans, int) and (ans >= 0), ( + "'ans' must been from type int and positive" + ) return ans @@ -574,9 +574,9 @@ def get_prime(n): ans += 1 # precondition - assert isinstance(ans, int) and is_prime( - ans - ), "'ans' must been a prime number and from type int" + assert isinstance(ans, int) and is_prime(ans), ( + "'ans' must been a prime number and from type int" + ) return ans @@ -705,9 +705,9 @@ def is_perfect_number(number): """ # precondition - assert isinstance(number, int) and ( - number > 1 - ), "'number' must been an int and >= 1" + assert isinstance(number, int) and (number > 1), ( + "'number' must been an int and >= 1" + ) divisors = get_divisors(number) diff --git a/neural_network/input_data.py b/neural_network/input_data.py index 72debabb566a..3a8628f939f8 100644 --- a/neural_network/input_data.py +++ b/neural_network/input_data.py @@ -160,9 +160,9 @@ def __init__( self._num_examples = 10000 self.one_hot = one_hot else: - assert ( - images.shape[0] == labels.shape[0] - ), f"images.shape: {images.shape} labels.shape: {labels.shape}" + assert images.shape[0] == labels.shape[0], ( + f"images.shape: {images.shape} labels.shape: {labels.shape}" + ) self._num_examples = images.shape[0] # Convert shape from [num examples, rows, columns, depth] diff --git a/scripts/validate_solutions.py b/scripts/validate_solutions.py index 79a2f790081f..f426153b5683 100755 --- a/scripts/validate_solutions.py +++ b/scripts/validate_solutions.py @@ -103,6 +103,6 @@ def test_project_euler(solution_path: pathlib.Path) -> None: solution_module = convert_path_to_module(solution_path) answer = str(solution_module.solution()) answer = hashlib.sha256(answer.encode()).hexdigest() - assert ( - answer == expected - ), f"Expected solution to {problem_number} to have hash {expected}, got {answer}" + assert answer == expected, ( + f"Expected solution to {problem_number} to have hash {expected}, got {answer}" + ) From 4c59775f8a7d9ef8e2a7ddd73c3e348f0ff30ecb Mon Sep 17 00:00:00 2001 From: MapleBauhinia <3626172038@qq.com> Date: Sat, 5 Jul 2025 21:23:30 +0800 Subject: [PATCH 14/15] Fix: ruff check --- machine_learning/frequent_pattern_growth.py | 2 +- sorts/bead_sort.py | 4 ++-- strings/min_cost_string_conversion.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/machine_learning/frequent_pattern_growth.py b/machine_learning/frequent_pattern_growth.py index c2a5e640c0bb..9f1817df2fb3 100644 --- a/machine_learning/frequent_pattern_growth.py +++ b/machine_learning/frequent_pattern_growth.py @@ -240,7 +240,7 @@ def ascend_tree(leaf_node: TreeNode, prefix_path: list[str]) -> None: ascend_tree(leaf_node.parent, prefix_path) -def find_prefix_path(base_pat: frozenset, tree_node: TreeNode | None) -> dict: +def find_prefix_path(_base_pat: frozenset, tree_node: TreeNode | None) -> dict: """ Find the conditional pattern base for a given base pattern. diff --git a/sorts/bead_sort.py b/sorts/bead_sort.py index e51173643d81..403c77c79078 100644 --- a/sorts/bead_sort.py +++ b/sorts/bead_sort.py @@ -2,7 +2,7 @@ Bead sort only works for sequences of non-negative integers. https://en.wikipedia.org/wiki/Bead_sort """ - +from itertools import pairwise def bead_sort(sequence: list) -> list: """ @@ -31,7 +31,7 @@ def bead_sort(sequence: list) -> list: if any(not isinstance(x, int) or x < 0 for x in sequence): 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:])): + for i, (rod_upper, rod_lower) in enumerate(pairwise(sequence)): if rod_upper > rod_lower: sequence[i] -= rod_upper - rod_lower sequence[i + 1] += rod_upper - rod_lower diff --git a/strings/min_cost_string_conversion.py b/strings/min_cost_string_conversion.py index 363f46755e08..70cd08d6faf4 100644 --- a/strings/min_cost_string_conversion.py +++ b/strings/min_cost_string_conversion.py @@ -140,7 +140,7 @@ def assemble_transformation(ops: list[list[str]], i: int, j: int) -> list[str]: elif op[0] == "R": string[i] = op[2] - file.write("%-16s" % ("Replace %c" % op[1] + " with " + str(op[2]))) + file.write(f"{'Replace ' + op[1] + ' with ' + str(op[2]):<16}") file.write("\t\t" + "".join(string)) file.write("\r\n") From 86be4813d647af875b6ec734db41dd9dcac4bebc Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 5 Jul 2025 13:25:20 +0000 Subject: [PATCH 15/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- sorts/bead_sort.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sorts/bead_sort.py b/sorts/bead_sort.py index 403c77c79078..51133f7a2a64 100644 --- a/sorts/bead_sort.py +++ b/sorts/bead_sort.py @@ -2,8 +2,10 @@ Bead sort only works for sequences of non-negative integers. https://en.wikipedia.org/wiki/Bead_sort """ + from itertools import pairwise + def bead_sort(sequence: list) -> list: """ >>> bead_sort([6, 11, 12, 4, 1, 5])