From 4997bae2b539164cb89274ecaf7e89ccabbaaa62 Mon Sep 17 00:00:00 2001 From: MaximSmolskiy Date: Thu, 3 Nov 2022 00:13:33 +0300 Subject: [PATCH 1/7] Reduce the complexity of other/graham_scan.py --- other/graham_scan.py | 150 ++++++++++++++++++++++--------------------- 1 file changed, 76 insertions(+), 74 deletions(-) diff --git a/other/graham_scan.py b/other/graham_scan.py index 91bb6812fefc..598584c6bddc 100644 --- a/other/graham_scan.py +++ b/other/graham_scan.py @@ -13,6 +13,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 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 + + +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 + 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 b1725059a65c1073669d7caf7f1f3392429676af Mon Sep 17 00:00:00 2001 From: MaximSmolskiy Date: Thu, 3 Nov 2022 00:19:26 +0300 Subject: [PATCH 2/7] Lower the --max-complexity threshold in the file .flake8 --- .flake8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.flake8 b/.flake8 index 1a62d57f9a57..2f74f421d020 100644 --- a/.flake8 +++ b/.flake8 @@ -1,7 +1,7 @@ [flake8] max-line-length = 88 # max-complexity should be 10 -max-complexity = 21 +max-complexity = 19 extend-ignore = # Formatting style for `black` E203 # Whitespace before ':' From d40c51f215858812491114ac24f67440b53bb95f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 2 Nov 2022 21:23:24 +0000 Subject: [PATCH 3/7] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- other/graham_scan.py | 1 + 1 file changed, 1 insertion(+) diff --git a/other/graham_scan.py b/other/graham_scan.py index 598584c6bddc..b5f8765c0bc6 100644 --- a/other/graham_scan.py +++ b/other/graham_scan.py @@ -13,6 +13,7 @@ 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): From 3095a9c7dda8f000c386ca12bcde916c05beb26b Mon Sep 17 00:00:00 2001 From: MaximSmolskiy Date: Thu, 3 Nov 2022 00:49:09 +0300 Subject: [PATCH 4/7] Fix tests --- other/graham_scan.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/other/graham_scan.py b/other/graham_scan.py index b5f8765c0bc6..bc9d6f3c056a 100644 --- a/other/graham_scan.py +++ b/other/graham_scan.py @@ -21,6 +21,9 @@ class Direction(Enum): 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) From 6b31071e50b9b01201739feed3906b5ac503cfee Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Thu, 3 Nov 2022 01:12:07 +0300 Subject: [PATCH 5/7] Update other/graham_scan.py Co-authored-by: Christian Clauss --- other/graham_scan.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/other/graham_scan.py b/other/graham_scan.py index bc9d6f3c056a..ad2cf97accc3 100644 --- a/other/graham_scan.py +++ b/other/graham_scan.py @@ -44,8 +44,7 @@ def angle_comparer(point: tuple[int, int], minx: int, miny: int) -> float: 33.690067525979785 """ # sort the points accorgind to the angle from the lowest and the most left point - x = point[0] - y = point[1] + x, y = point angle = degrees(atan2(y - miny, x - minx)) return angle From 37343c2cd995f5b7c3f8d38a53cb12acd054e3ed Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Thu, 3 Nov 2022 01:13:54 +0300 Subject: [PATCH 6/7] Update graham_scan.py --- other/graham_scan.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/other/graham_scan.py b/other/graham_scan.py index ad2cf97accc3..3417a9ddf8a9 100644 --- a/other/graham_scan.py +++ b/other/graham_scan.py @@ -45,8 +45,7 @@ def angle_comparer(point: tuple[int, int], minx: int, miny: int) -> float: """ # sort the points accorgind to the angle from the lowest and the most left point x, y = point - angle = degrees(atan2(y - miny, x - minx)) - return angle + return degrees(atan2(y - miny, x - minx)) def check_direction( From caffdc58f347310d2057ad322dbb52b83bbb579c Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 2 Nov 2022 23:40:11 +0100 Subject: [PATCH 7/7] Update other/graham_scan.py --- other/graham_scan.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/other/graham_scan.py b/other/graham_scan.py index 3417a9ddf8a9..8e83bfcf4c49 100644 --- a/other/graham_scan.py +++ b/other/graham_scan.py @@ -72,11 +72,9 @@ def check_direction( x1, y1 = via x2, y2 = target via_angle = degrees(atan2(y1 - y0, x1 - x0)) - if via_angle < 0: - via_angle += 360 + via_angle %= 360 target_angle = degrees(atan2(y2 - y0, x2 - x0)) - if target_angle < 0: - target_angle += 360 + target_angle %= 360 # t- # \ \ # \ v