Skip to content

Commit 978414b

Browse files
MaximSmolskiypre-commit-ci[bot]cclauss
authored
Reduce the complexity of other/graham_scan.py (TheAlgorithms#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 <[email protected]> * 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 <[email protected]>
1 parent a02de96 commit 978414b

File tree

2 files changed

+77
-75
lines changed

2 files changed

+77
-75
lines changed

Diff for: .flake8

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[flake8]
22
max-line-length = 88
33
# max-complexity should be 10
4-
max-complexity = 20
4+
max-complexity = 19
55
extend-ignore =
66
# Formatting style for `black`
77
E203 # Whitespace before ':'

Diff for: other/graham_scan.py

+76-74
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,82 @@
1414
from sys import maxsize
1515

1616

17+
# traversal from the lowest and the most left point in anti-clockwise direction
18+
# if direction gets right, the previous point is not the convex hull.
19+
class Direction(Enum):
20+
left = 1
21+
straight = 2
22+
right = 3
23+
24+
def __repr__(self):
25+
return f"{self.__class__.__name__}.{self.name}"
26+
27+
28+
def angle_comparer(point: tuple[int, int], minx: int, miny: int) -> float:
29+
"""Return the angle toward to point from (minx, miny)
30+
31+
:param point: The target point
32+
minx: The starting point's x
33+
miny: The starting point's y
34+
:return: the angle
35+
36+
Examples:
37+
>>> angle_comparer((1,1), 0, 0)
38+
45.0
39+
40+
>>> angle_comparer((100,1), 10, 10)
41+
-5.710593137499642
42+
43+
>>> angle_comparer((5,5), 2, 3)
44+
33.690067525979785
45+
"""
46+
# sort the points accorgind to the angle from the lowest and the most left point
47+
x, y = point
48+
return degrees(atan2(y - miny, x - minx))
49+
50+
51+
def check_direction(
52+
starting: tuple[int, int], via: tuple[int, int], target: tuple[int, int]
53+
) -> Direction:
54+
"""Return the direction toward to the line from via to target from starting
55+
56+
:param starting: The starting point
57+
via: The via point
58+
target: The target point
59+
:return: the Direction
60+
61+
Examples:
62+
>>> check_direction((1,1), (2,2), (3,3))
63+
Direction.straight
64+
65+
>>> check_direction((60,1), (-50,199), (30,2))
66+
Direction.left
67+
68+
>>> check_direction((0,0), (5,5), (10,0))
69+
Direction.right
70+
"""
71+
x0, y0 = starting
72+
x1, y1 = via
73+
x2, y2 = target
74+
via_angle = degrees(atan2(y1 - y0, x1 - x0))
75+
via_angle %= 360
76+
target_angle = degrees(atan2(y2 - y0, x2 - x0))
77+
target_angle %= 360
78+
# t-
79+
# \ \
80+
# \ v
81+
# \|
82+
# s
83+
# via_angle is always lower than target_angle, if direction is left.
84+
# If they are same, it means they are on a same line of convex hull.
85+
if target_angle > via_angle:
86+
return Direction.left
87+
elif target_angle == via_angle:
88+
return Direction.straight
89+
else:
90+
return Direction.right
91+
92+
1793
def graham_scan(points: list[tuple[int, int]]) -> list[tuple[int, int]]:
1894
"""Pure implementation of graham scan algorithm in Python
1995
@@ -57,86 +133,12 @@ def graham_scan(points: list[tuple[int, int]]) -> list[tuple[int, int]]:
57133
# remove the lowest and the most left point from points for preparing for sort
58134
points.pop(minidx)
59135

60-
def angle_comparer(point: tuple[int, int], minx: int, miny: int) -> float:
61-
"""Return the angle toward to point from (minx, miny)
62-
63-
:param point: The target point
64-
minx: The starting point's x
65-
miny: The starting point's y
66-
:return: the angle
67-
68-
Examples:
69-
>>> angle_comparer((1,1), 0, 0)
70-
45.0
71-
72-
>>> angle_comparer((100,1), 10, 10)
73-
-5.710593137499642
74-
75-
>>> angle_comparer((5,5), 2, 3)
76-
33.690067525979785
77-
"""
78-
# sort the points accorgind to the angle from the lowest and the most left point
79-
x = point[0]
80-
y = point[1]
81-
angle = degrees(atan2(y - miny, x - minx))
82-
return angle
83-
84136
sorted_points = sorted(points, key=lambda point: angle_comparer(point, minx, miny))
85137
# This insert actually costs complexity,
86138
# and you should instead add (minx, miny) into stack later.
87139
# I'm using insert just for easy understanding.
88140
sorted_points.insert(0, (minx, miny))
89141

90-
# traversal from the lowest and the most left point in anti-clockwise direction
91-
# if direction gets right, the previous point is not the convex hull.
92-
class Direction(Enum):
93-
left = 1
94-
straight = 2
95-
right = 3
96-
97-
def check_direction(
98-
starting: tuple[int, int], via: tuple[int, int], target: tuple[int, int]
99-
) -> Direction:
100-
"""Return the direction toward to the line from via to target from starting
101-
102-
:param starting: The starting point
103-
via: The via point
104-
target: The target point
105-
:return: the Direction
106-
107-
Examples:
108-
>>> check_direction((1,1), (2,2), (3,3))
109-
Direction.straight
110-
111-
>>> check_direction((60,1), (-50,199), (30,2))
112-
Direction.left
113-
114-
>>> check_direction((0,0), (5,5), (10,0))
115-
Direction.right
116-
"""
117-
x0, y0 = starting
118-
x1, y1 = via
119-
x2, y2 = target
120-
via_angle = degrees(atan2(y1 - y0, x1 - x0))
121-
if via_angle < 0:
122-
via_angle += 360
123-
target_angle = degrees(atan2(y2 - y0, x2 - x0))
124-
if target_angle < 0:
125-
target_angle += 360
126-
# t-
127-
# \ \
128-
# \ v
129-
# \|
130-
# s
131-
# via_angle is always lower than target_angle, if direction is left.
132-
# If they are same, it means they are on a same line of convex hull.
133-
if target_angle > via_angle:
134-
return Direction.left
135-
elif target_angle == via_angle:
136-
return Direction.straight
137-
else:
138-
return Direction.right
139-
140142
stack: deque[tuple[int, int]] = deque()
141143
stack.append(sorted_points[0])
142144
stack.append(sorted_points[1])

0 commit comments

Comments
 (0)